1.MVVM
是Model-View-ViewModel的缩写,model层代表数据模型,也可以在model中定义数据修改和操作的业务逻辑。
view代表ui组件,负责将数据模型转化成UI展现出来
view-model是一个同步view和model的对象。
在mvvm架构下,view和model之间没有直接的联系,而是通过view-model进行交互。
model和view-modal之间的交互是双向的,因此view数据的变化会同步到model中,model数据的变化也会立即反映到view上。
view-modal通过双向数据绑定把view和model层连接起来,view和model之间的同步工作是完全自动的,无需人为干涉,因此开发者只需关注业务逻辑,不需要手动操作dom,不需要关注数据状态的同步问题,复杂的数据状态维护完全由mvvm来统一管理。
2.html标签
h:标题标签
p:段落标签
br:换行标签
hr:水平线标签
strong:文字加粗
u、ins:下划线
i、em:倾斜
s、del:删除线
img:图片,src-图片路径,alt-加载失败替换文本,title-鼠标悬停显示文本,width和height-宽高
audio:音频,autoplay-如果有,就续后马上播放,controls-如果有,向用户显示控件,loop-如果有,结束时重新播放,preload-如果有,在页面加载时进行加载,并预备播放,src-音频url
div:一行只显示一个
span:一行可以显示多个
// <!DOCTYPE...>标签用来声明HTML文档的编写标准,放在最开头位置,可写可不写.
//和是中必须有的元素.
//里面必须有标签,和</meta>
Document
{{message}}
3.基础语法
单向绑定数据:v-bind,简写:
双向绑定数据:v-model
data: {
searchMap:{
keyWord: '哪吒'
}
}
您要查询的是:{{searchMap.keyWord}}
v-if,条件成立则执行相应的代码,可以通过v-else添加else块,通过v-else-if在多种条件下进行判断
v-show根据条件展示元素
v-for循环语句,需要通过v-for="todo in todos"的特殊语法,遍历todos里面定义的数组元素,可以通过v-for="value in object"遍历对象的属性,v-for="n in 10"循环整数
getter:创建一个实例object时,此时object没有name属性,调用object.name时,会进入到get name(){...}中,先判断object是否有name属性,若没有,则添加一个name属性并赋值,如果有则直接返回
setter:给name赋值时,进入set name(val){...},可以在此进行双向绑定等操作
计算属性computed:基于data中的state,通过计算得到的一些计算出来的"state"
4.tree shaking
Tree shaking 是一种通过清除多余代码方式来优化项目打包体积的技术,专业术语叫Dead code elimination。
简单来讲,就是在保持代码运行结果不变的前提下,去除无用的代码。
全局组件在tree shaking时不会被去除。
好处:
减少程序体积(更小)
减少程序执行时间(更快)
便于将来对程序架构进行优化(更友好)
5.响应式基础
响应式:当修改响应式状态时,dom会自动更新。不是同步的,会在next tick更新周期中缓冲所以状态的修改。
6.优点
(1)响应式编程:会自动对页面中某些数据的变化做出响应
(2)组件化开发:通过组件,把一个单页面应用中的各种模块拆分到一个个单独的组件中,只需要在父级应用中写好各组件标签,在组件标签中传入组件的参数,再分别写好组件的实现,即可完成开发。组件化开发的优点:提高开发效率,方便重用,简化调试步骤,提高项目的可维护性,便于协同开发
(3)虚拟dom:预先通过js进行计算,把最终的dom操作计算出来并优化,最后才真正将dom操作提交,将dom操作变化反映到dom树上,属于预处理操作
7.生命周期
(1)什么是生命周期:一个vue实例从创建到销毁的过程
(2)作用:在生命周期的过程中运行着一些生命周期的函数,给予开发者在不同的生命周期阶段添加业务代码的能力
(3)几个阶段:创建前/后,载入前/后,更新前/后,销毁前/后
beforeCreate:是 new Vue( ) 之后触发的第一个钩子,在当前阶段 data、methods、computed 以及 watch 上的数据和方法都不能被访问。
created:在实例创建完成后发生,当前阶段已经完成了数据观测,也就是可以使用数据,更改数据,在这里更改数据不会触发 updated 函数。可以做一些初始数据的获取,在当前阶段无法与 DOM 进行交互,如果非要想,可以通过 vm.$nextTick 来访问 DOM 。
beforeMount:发生在挂载之前,在这之前 template 模板已导入渲染函数编译。而当前阶段虚拟 DOM 已经创建完成,即将开始渲染。在此时也可以对数据进行更改,不会触发 updated。
mounted:在挂载完成后发生,在当前阶段,真实的 DOM 挂载完毕,数据完成双向绑定,可以访问到 DOM 节点,使用 $refs 属性对 DOM 进行操作。
beforeUpdate:发生在更新之前,也就是响应式数据发生更新,虚拟 DOM 重新渲染之前被触发,你可以在当前阶段进行更改数据,不会造成重渲染。
updated:发生在更新完成之后,当前阶段组件 DOM 已完成更新。要注意的是避免在此期间更改数据,因为这可能会导致无限循环的更新。
beforeDestroy:发生在实例销毁之前,在当前阶段实例完全可以被使用,我们可以在这时进行善后收尾工作,比如清除计时器。
destroyed:发生在实例销毁之后,这个时候只剩下了 DOM 空壳。组件已被拆解,数据绑定被卸除,监听被移出,子实例也统统被销毁。
第一次页面加载会触发4个hook,beforeCreate、created、beforeMount、mounted
dom渲染在mounted阶段完成,此阶段真实的dom挂载完毕,数据完成双向绑定,可以访问到dom节点
多组件中生命周期的调用顺序:
组件的调用顺序是先父后子,渲染完成的顺序是先子后父,组件的销毁操作是先父后子,销毁完成的顺序是先子后父。
加载渲染过程:父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount- >子mounted->父mounted
子组件更新过程:父beforeUpdate->子beforeUpdate->子updated->父updated
父组件更新过程:父 beforeUpdate -> 父 updated
销毁过程:父beforeDestroy->子beforeDestroy->子destroyed->父destroyed
8.vue实现双向数据绑定的原理
vue2采用数据劫持结合发布订阅模式,通过object.defineProperty来劫持各个属性的setter、getter,在数据变动时发布消息给订阅者,触发相应的监听回调。
当把一个普通js对象传给vue实例来作为data选项时,vue将遍历它的属性,用object.defineProperty将他们转为getter/setter,在内部追踪依赖,在属性被访问和修改时通知变化。vue的数据双向绑定整合了observer,compile和watcher三者,通过observer来监听自己的model的数据变化,通过compile来解析变异模版指令,最终利用watcher搭起observer和compile的通信桥梁,达到数据变化-视图更新,视图交互变化-数据model变更的双向绑定效果,
vue3使用es6原生的proxy,来解决以前使用objext.defineProperty所存在的一些问题。
9.vue2响应式原理
vue在初始化数据时,会使用object.defineProperty重新定义data中的所有属性,当页面使用对应属性时,首先会进行依赖收集(收集当前组件的watcher),如果属性发生变化会通知相关依赖进行更新操作(发布订阅)
如何检测数组的变化:
vue将data中的数组进行了原型链重写,指向了自己定义的数组原型方法,当调用数组api时,可以通知依赖更新。如果数组中包含着引用类型,会对数组中的引用类型再次递归进行监控,这样就实现了检测数组变化。
流程:
初始化传入data数据执行initdata,将数据进行观测new observer,将数组原型方法指向重写的原型,深度观察数组中的引用类型。
当通过索引直接设置一个数组项时,或者修改数组的长度时,无法检测到数组的变化,解决方案:用vm.$set(vm.items, indexOfItem, newValue)替代利用索引设置数组项,使用vm.items.splice(indexOfItem, 1, newValue)更新数组长度。
10.vue3响应式数据
vue3响应式数据原理:
vue2的响应式原理是使用object.defineProperty来实现的,在vue3中采用了proxy。
原因:
object.defineProperty无法监控到数组下标的变化,导致通过数组下标添加元素,不能实时响应
object.defineProperty只能挟持对象属性,从而需要对每个对象、每个属性进行遍历,如果属性值是对象,还需要深度遍历。proxy可以挟持整个对象,并返回一个新的对象。
proxy可以代理对象和数组,还可以代理动态增加的属性。
proxy有多达13种拦截方法,作为新标准收到浏览器厂商重点持续的性能优化。
proxy只会代理对象的第一层,如何处理
vue3会判断当前reflect.get的返回值是否为object,如果是则再通过reactive方法做代理,就实现了深度观测。
检测数组的时候可能触发多次get/set,如何防止触发多次
可以判断key是否为当前被代理对象target自身属性,也可以判断旧值与新值是否相等,只有满足以上两个条件之一时,才可能执行trigger。
11.v-model双向绑定的原理是什么
双向绑定
v-model本质是value+input方法的语法糖,可以通过model属性的prop和event属性来进行自定义,原生的v-model,会根据标签的不同生成不同的事件和属性,例如text和textarea元素使用value属性和input事件,checkbox和radio使用checked属性和change事件,select字段将value作为prop并将change作为事件。