vue3学习随便记2
Posted sjg20010414
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vue3学习随便记2相关的知识,希望对你有一定的参考价值。
引子
初步学习 Vue的概念,一上来就用 vue-cli 的方式的确是找死,会让自己陷入很多复杂的坑。初次尝试,最好是直接引入。
在开始了解 Vue 的概念之前,我们要先来回顾一下 MVC模式、MVVM模式的初步思想。
MVC 模式是一种后端考虑思维,是厚重后端的思维。Model负责对来自用户的数据、从数据库获取的数据进行加工,有关业务逻辑的处理,把一定的数据通过Controller提供给 View 层。View 层负责利用所给的数据生成展示用的 html、CSS、JS 发送给客户浏览器,如果需要一些前端的效果,则在 JS 中通过操作 DOM 实现。Controller 层是很瘦的连接器,负责沟通 View 和 Model。当然,Controller 层是用户端的第一入口,所以往往和路由有关。MVC思维中,用户界面view上的变化都是事件(例如点击了某个链接,提交了表单),我们针对每个事件写代码(对应controller中的action),把用户输入转换到model中处理。
MVVM模式是一种前后端分离的思维,是厚重前端的思维。前后端分离后,后端只是扔一堆数据给前端,后面的事(呈现逻辑)都是前端的事。Model 从前端看就是API请求获得数据,View就是单纯的 HTML、CSS 展示,大量的呈现逻辑都是 ViewModel 负责(ViewModel是专门为View服务的Model,即View的数据对象)。MVVM思维中,view里面的各种控件有一个对应的数据对象,这样,只要修改这个数据对象,view里面显示的内容就自动同步刷新,反之,view里面做了任何操作,这个数据对象也跟着同步修改,这些功能的实现都是底层处理的,开发者不用直接操作DOM。
在 MVC 中,View需要呈现的东西具体数据是怎样的,还是需要较多和后端联系,起码有详细文档说明。而 MVVM 中,View 设计者可以关注设计,关于数据和事件,就是一堆声明,它面向ViewModel中的数据即可。ViewModel开发者可以来协调怎么从后台获取数据,怎么调整成更适合View的数据,换句话说,View和Model解耦了。在 MVVM 下,组件的可复用性更强。
MVVM中的bug调试比MVC中的要困难一些(前端调试本就比较困难),压力也主要在浏览器一侧,大的 ViewModel 构建和维护的成本也比较高。某种程度上,MVVM模式下的SPA应用,基本上和传统的C/S风格的窗口程序无异了。静态内容偏多的网站,可能用 MVVM 没有多少优势,而典型的业务型 SPA 才是能体现它优点的地方。
MVVM的主要魔法是 数据劫持、数据代理、数据编译和“发布订阅模式”。
数据劫持:主要是给对象的(data中的那些)属性添加 get、set 钩子函数。
数据代理:把 data、methods、computed 上的数据挂载到 vm 实例上,这些地方定义的数据,就都是vm实例的数据,从而不用 vm._data.a.b 这样去访问,直接用 vm.a.b 即可。
数据编译:把 ,v-model,v-html,v-on 里面的对应的变量用 data 里面的数据进行替换。
发布订阅:订阅就是将订阅者添加到订阅队列中,发布就是让订阅者得到调用执行。所谓订阅者,就是函数,订阅队列,就是数组。在数据发生改变的时候,订阅者收到通知,执行相应的操作。一般 get 钩子函数被调用时进行数据的订阅,在 set 钩子函数被调用时进行数据的发布。
双向绑定主要是数据劫持和发布订阅模式的作用。
介绍
声明式渲染
<html>
<head>
<script src="vue.global.js"></script>
</head>
<body>
<div id="counter">
计数器: counter
</div>
<script>
const Counter =
data()
return
counter: 0
,
mounted()
setInterval(() =>
this.counter++
, 1000)
Vue.createApp(Counter).mount('#counter')
</script>
</body>
</html>
Vue.createApp 根据 Counter 定义的数据对象配置创建数据对象vm(相当于ViewModel),然后用 mount 方法和 DOM建立关联。数据和DOM建立关联后,所有东西都是响应式的。
data() 返回的对象,其中的键值对直接成为vm的数据(数据代理),之所以插一层 data(),这里意味着 data()内的数据都是vm的被“监视”的变量,一旦这些变量改变,(订阅者收到通知)背后相应的方法调用,该替换修改的地方得到修改(模板编译)。
不仅文本插值可以实现响应式替换,元素的属性也可以绑定到变量,响应式自动替换。
<html>
<head>
<script src="vue.global.js"></script>
</head>
<body>
<div id="bind-attribute">
<span v-bind:title="message">
鼠标悬停几秒钟查看此处动态绑定的提示消息!
</span>
</div>
<script>
const AttributeBinding =
data()
return
message: '你加载此页的时间 ' + new Date().toLocaleString()
,
mounted()
setInterval(() =>
this.counter++
, 1000)
Vue.createApp(AttributeBinding).mount('#bind-attribute')
</script>
</body>
</html>
处理用户输入
用户输入包括在文本框之类的东西输入数据,也包括点击按钮之类的动作。可以用 v-on 指令添加事件监听器,绑定到vm的实例方法。
<html>
<head>
<script src="vue.global.js"></script>
</head>
<body>
<div id="event-handling">
<p> message </p>
<button v-on:click="reverseMessage">反转 消息文本</button>
</div>
<script>
const EventHandling =
data()
return
message: 'Hello Vue3'
,
methods:
reverseMessage()
this.message = this.message.split('').reverse().join('')
Vue.createApp(EventHandling).mount('#event-handling')
</script>
</body>
</html>
用 Vue 提供的 v-model 指令,可以将表单输入和vm变量之间双向绑定,用户输入可以被自动get到并同步到变量,变量被修改时也可以自动反映到表单输入。
<html>
<head>
<script src="vue.global.js"></script>
</head>
<body>
<div id="two-way-binding">
<p> message </p>
<input v-model="message" />
</div>
<script>
const TwoWayBinding =
data()
return
message: 'Hello Vue3'
Vue.createApp(TwoWayBinding).mount('#two-way-binding')
</script>
</body>
</html>
条件与循环
条件控制就是一个元素是否显示的控制,是否显示包含是否渲染(v-if)和渲染后是否隐藏(v-show)。
<html>
<head>
<script src="vue.global.js"></script>
</head>
<body>
<div id="conditional-rendering">
<div>
<span v-if="seen">这个渲染了</span> <br>
<span v-show="show">这个显示了</span>
</div>
<div>
<button @click="toggleSeen">切换渲染的</button>
<button @click="toggleShow">切换显示</button>
</div>
</div>
<script>
const ConditionalRendering =
data()
return
seen: true,
show: true
,
methods:
toggleSeen()
this.seen = !this.seen
,
toggleShow()
this.show = !this.show
Vue.createApp(ConditionalRendering).mount('#conditional-rendering')
</script>
</body>
</html>
我们点击按钮,让两个文本都看不到,再观察实际的HTML元素,可以发现,同样是隐藏,v-if 是不渲染,v-show 是渲染而不显示
对于数组数据的显示,可以用 v-for 指令绑定数组数据来渲染,循环显示成列表或其他相同的块。
<html>
<head>
<script src="vue.global.js"></script>
</head>
<body>
<div id="list-rendering">
<ol>
<li v-for="todo in todos">
todo.text
</li>
</ol>
</div>
<script>
const ListRendering =
data()
return
todos: [
text: 'Learn javascript' ,
text: 'Learn Vue' ,
text: 'Build something awesome'
]
Vue.createApp(ListRendering).mount('#list-rendering')
</script>
</body>
</html>
可以将可复用的,或者功能相对独立的块构建为独立的组件,以便提高复用效果或可维护性。
<html>
<head>
<script src="vue.global.js"></script>
</head>
<body>
<div id="list-rendering">
<ol>
<todo-item v-for="todo in todos"></todo-item>
</ol>
</div>
<script>
const TodoItem =
template: `<li>这是一个待办事项</li>`
const TodoList =
components:
TodoItem
,
data()
return
todos: [
text: 'Learn JavaScript' ,
text: 'Learn Vue' ,
text: 'Build something awesome'
]
Vue.createApp(TodoList).mount('#list-rendering')
</script>
</body>
</html>
我们用声明式数据对象定义了组件
const TodoItem =
template: `<li>这是一个待办事项</li>`
然后在 TodoList 数据对象中注册了该组件 (TodoList 的 components 属性)
components:
TodoItem
,
然后在 TodoList 的 view 中使用该组件 (把它当作新元素)
<todo-item v-for="todo in todos"></todo-item>
最后的效果是
这样不能合乎逻辑,我们希望组件 TodoItem 渲染出来的是 todos 数组中的数据。我们必须有一种机制,可以让组件 TodoItem 这个儿子,能够接受父亲 TodoList 传给它的数据,并渲染出来。实现这一通信的是属性机制,我们修改注册组件部分,使组件包含 todo 属性,并且渲染的文本是该属性的 text 键值 todo.text
const TodoItem =
props: ['todo'],
template: `<li> todo.text </li>`
在使用组件时,把数据绑定到该属性(数据item----->属性todo)
<ol>
<todo-item v-for="item in todos"
v-bind:todo="item"
></todo-item>
</ol>
现在效果就是
事实上,每个应用都有一个组件,即根组件,在上述例子中就是 TodoList 根组件,根组件下可以有子组件。我们尝试用 vue的 devtools 浏览器插件来查看,先要处理该插件,鉴于翻墙太麻烦,我们从 devtools 源码开始
git clone https://github.com/vuejs/devtools.git // 克隆源码
cd devtools
yarn // 安装依赖
yarn build // 构建
然后 packages 子目录下有生成的各种适用于浏览器的东西,关注 shell-chrome 子目录,将它作为解压缩的扩展加载到 Edge 浏览器。重新启动浏览器加载前述页面,F12打开开发人员工具,选择 Vue tab页,可以看到如下页面结构:
Vue应用页面总是一棵 DOM树,这里是最简单的,类似如下
以上是关于vue3学习随便记2的主要内容,如果未能解决你的问题,请参考以下文章