前言
Vue的特点
-
采用
组件化
的模式,提高代码复用率,让代码更好维护 -
声明式
编码,开发者无需直接操作DOM,提高开发效率 -
使用
虚拟DOM
+Diff算法
,尽量复用DOM节点-
虚拟DOM(Virtual DOM):
在Vue中,虚拟DOM)是一种用JS对象表示真实DOM的轻量级表示形式。它是Vue的核心概念之一,用于提高性能并优化DOM操作。
当我们编写Vue模板时,实际上是在描述应该如何渲染真实的DOM结构。而虚拟DOM则是根据这个模板生成的一棵以JavaScript对象表示的树形结构,它与真实的DOM节点对应。 -
Diff算法:
diff算法是虚拟DOM实现的关键步骤,用于比较新旧虚拟DOM树的差异。它的核心思想是通过最小化操作来更新DOM,使得整个更新过程更加高效。
-
Vue官网
V2官网这里有很多好用的第三方库:
初识Vue
1.准备好一个容器,比如这里我在body里面写了一个id为root的div:
2.想让Vue工作,就必须创建一个Vue实例,并且传入一个配置对象:
3.root容器里面的东西仍然符合HTML规范,只不过会混合一些Vue语法,Vue去解析容器里面的Vue语法,把其替换成Vue实例里面的内容。
Vue模板语法
HTML中包含了一些JS的语法代码,分为
- 插值语法(双大括号表达式) —用于指定标签体内容(就是被一个html标签包裹起来的内容)
- 指令语法(以v-开头)—功能很强大,可以用来解析标签
插值语法是用来解析标签体的内容,语法:{{xxxx}} , xxxx就会作为js的表达式被解析。xxxx要写js的表达式,且xxxx可以自动读取到data中的所有属性。一旦data中的数据产生变化,那么页面中使用该数据的地方会自动变化。
指令语法:
(1)功能:解析标签属性、解析标签内容、绑定事件。
(2)举例:v-bind:href=“xxxx” , xxxx就会作为js的表达式被解析。
v-bind:
可以简写为 :
数据绑定
单向数据绑定
1.语法:v-bind:href = "xxx"
或者简写为 :href="xxx"
。
2.特点:数据只能从data流向页面,反之不行。
双向数据绑定
1.语法:v-model:value = "xxx"
或者简写为 v-model="xxx"
。
- 注意:双向数据绑定一般都应用在表单类元素上面(如
input
、select
等等) 。 v-model:value
可以简写为v-model
,因为它默认收集的就是value值。
2.特点:数据不仅能从data流向页面,还能从页面流向data。
el的两种写法
- el的两种写法你用哪一种都可以。
data的两种写法
- data的两种写法,对象式和函数式。
- 在之后用组件来写Vue的时候,一般用函数式来写data。
- 要注意的是,在用函数式写data的时候,函数体不要写成箭头函数,就写成普通函数,否则this就不是指向这个函数本身了,而是指向全局window。另外,一般还可以把:function 省略,则直接写成这样
data(){
console.log('@@@',this)
return{
name:'尚硅谷'
}
}
Vue与MVVM模型
Object.defineProperty 方法
基本配置项
比如说我们现在有这么一个对象person
let person = {
name:'张三',
sex:'男性'
}
然后我们要对它追加一个age属性,那就可以这么写:
Object.defineProperty(person,'age',{
value:18,
enumerable:true,//控制属性是否可以枚举,默认值是false
writable:true,//控制属性是否可以被修改,默认值是false
configurable:true //控制属性是否可以被删除,默认值是false
})
此时我们就会得到追加age属性的一个Object对象:
getter
除了value, enumerable, writable, configurable这些基本配置之外,还有一些高级配置,比如说:getter函数
let number = 18
let person = {
name:'张三',
sex:'男性'
}
Object.defineProperty(person,'age',{
// 当有人读取person的age属性的时候,get函数(getter)就会被调用,且返回值就是age的值
get:function(){
return 'hello'
}
})
这样一来,我们一开始加载出来的就是:
然后我们再点一下括号里面的省略号,就会变成这样:
还可以把return的值改成
get: function () {
return number
}
在控制台改变number的属性值,就会变成这样:
setter
还有可能是这样:
let number = 18
let person = {
name:'张三',
sex:'男性'
}
Object.defineProperty(person,'age',{
get: function () {
return number
},
// 当有人修改了person的age属性的时候,set函数(setter)就会被调用,且会收到修改的具体值
set(value){
console.log('有人修改了age属性,且值是',value)
number = value
}
})
小结:
number 和 person 本身是独立的,但是在Object.defineProperty
里面,借助getter
和setter
,两个函数起到的就是桥梁的作用,通过该函数,一旦我们修改了对象中属性的值→触发了setter,那么getter就会自动触发,这样就可以直接更新dom元素,我们就可以直观的看到页面更新。
(靠getter去读取,靠setter去修改)
在 Vue2.x 的版本中,双向绑定是基于 Object.defineProperty 方式实现的。
Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
该方法接受三个参数,第一个参数是 obj:要定义属性的对象,第二个参数是 prop:要定义或修改的属性的名称或 Symbol,第三个参数是 descriptor:要定义或修改的属性描述符。
那么为什么Object.defineProperty方法能够用于实现数据的双向绑定呢?
在Vue.js中,在初始化数据对象时,会使用Object.defineProperty方法将数据对象的属性转化为getter
和setter
,从而实现对数据的监听。当访问数据对象的属性时,实际上会触发定义的getter函数,而当对属性进行赋值时,会触发定义的setter函数。这样,Vue.js能够在数据变动时得到通知,并执行相应的操作,比如更新视图。
通过拦截属性的读取和设置过程,Vue.js能够跟踪依赖的属性以及触发属性变化时需要更新的操作,从而实现了数据的响应式。
在上面的例子中,我们通过Object.defineProperty将person对象的age属性转化为getter和setter。当修改data.age的值时,会调用setter函数并执行相关的更新操作;而当获取data.name的值时,会调用getter函数并返回this.age的值。
Vue.js利用了Object.defineProperty的这个特性,通过劫持数据对象的属性,实现了对数据的监听和更新,从而实现了响应式的数据绑定。
理解数据代理
比如说我们现在的页面是这样写的:
我们现在在Vue实例vm里面写了data对象,并且在里面写了name和address
当有人在页面中读取name
的时候,getter
就会去读取data.name
的内容
当有人在页面中修改name
的时候,setter
就会去修改data.name
的内容
接下来我们来验证一下这个过程(也就是这两根线)
用浏览器打开页面:
那么我们之所以可以在页面上面看到name
的地方显示的是尚硅谷
,就是因为它访问了vm.name
,然后vm.name
的getter
函数工作获取到了data
里面的name
的具体内容,所以可以显示出来尚硅谷
。
我们再在控制台修改vm.name,这个时候就是调用了settter
,setter
收到了你要改的vm.name
的内容,然后去改data
里面的name
的内容。
可以看到,页面的显示内容也发生了改变:
再来看看data
的内容:确实也发生了改变。
小结
数据代理其实就是把vm
里面的_data
里面的数据,copy了一份放在vm
身上,从而使得我们写代码更加方便,可以直接用{{name}}
去访问,这一波操作都是通过Object.defineProperty
来实现的
1.Vue中的数据代理:
通过vm对象来代理data对象中属性的操作(读/写)
2.Vue中数据代理的好处:
更加方便的操作data中的数据
3.基本原理:
通过Object.defineProperty()把data对象中所有属性添加到vm上
为每一个添加到vm上的属性,都指定一个getter/setter
在getter/setter内部去操作(读/写)data中对应的属性