1. v-model原理
双向绑定原理
实现原理数据劫持+发布者+订阅者
① 对vue中所有属性使用Object.defineProperty()
进行数据劫持,并为每个属性分配发布者Dep数组,
② 然后在编译的时候,给这个发布者数组添加订阅者,v-model会加个订阅者,v-bind也会,所有用到这个属性的都会添加一个订阅者;
③ 再给这个属性添加监听,当监听到属性发生变化的时候,就会使用Object.defineProperty()
的set方法来修改属性,然后将变化通知给发布者,发布者再循环去调用订阅者的update方法更新到视图上。
MVVM的进化史:MVC -> MVP -> MVVM
MVC:M(model模型)、V(view视图)、C(controller控制器),M可以理解为后端传过来的数据,V可以理解为前端页面,C就是我们给dom元素添加的事件也就是逻辑代码;它们三个间数据是单向的,也就是M发生变化了就立即通知V,V发生变化了就通知C然后给M,M和V的直接交互导致对dom的频繁操作,降低了性能,所以出现了MVP;
MVP:M(model模型)、V(view视图)、P(Presenter发布层),为了实现页面和数据逻辑分离,所以出现了MVP,实现了M与P之间、V与P之间的数据双向传递,即所有的交互都发生在P那,避免了M与V直接交互;为了实现双向绑定所以出现了MVVM
MVVM:的出现既减少了对DOM的操作又实现了数据的双向绑定;M(model模型)、V(view视图)、VM(viewModel视图模型,是C和P的合体),VM是MVVM的核心,它有2个方向:① 视图更改模型,利用DOM事件监听;② 模型更改视图,利用数据绑定
2. diff算法
浏览器的运行机制:
构建dom树 -> 构建渲染树 -> 布局渲染树 -> 绘制渲染树
重排:渲染树重新构建,比如修改dom尺寸、位置、新增、删除dom都会使浏览器重新构建渲染树;
重绘:部分dom仅外观发生变化,比如颜色、字体大小等,浏览器会根据这个元素的新属性重新绘制;
重排一定会引起重绘,但是重绘不一定会引起重排
如果每修改一个dom,就引起整颗树的重绘和重排,非常影响性能,所以出现了diff算法。
diff算法是对2个虚拟dom树进行同层级一一对比,如果有差异就以新的为准,然后插入到真是dom中,重新渲染。v-for中写Key也是用的这个原理,为了能更快速的找到有差异的那个元素,不写key的话就会进行头尾两端的相互比较。
3. v-for、v-if优先级
v-for比v-if优先级高,因此v-for和v-if一起使用的时候,数组的每一项都要执行v-if语句,所以建议把v-if写在template或外层元素上。
4. vue-router hash、history区别
vue-router的出现是为了防止页面改变的同时向后端发送请求。
hash模式:url后面会跟个#,而且这个#不会跟在请求的url后面,所以对后端没有影响;
history模式:url后面没有#,但是需要后端支持比如nginx需要配置try_files(将页面重定向到首页),不然会出现刷新二级页面显示404(因为刷新页面时会访问真实路由),hitory是利用html5新增的两个方法history.pushState
、history.replaceState
这2个方法,只会使history对象发生变化,从而改变地址栏的url,不会向后端发送请求。
history和hash都是利用浏览器的特性来实现的。
路由守卫:
router.beforeEach
有三个参数:to(去哪儿)、from(正要离开的路由)、next(是个函数,调用next就可以进入路由)。可以在里面做一些操作,比如验证token是否存在、路由是否存在、是否有权限访问这个页面。
5. render、jsx区别
总结:
render使用createElement创建元素,有三个参数标签名、属性对象、子组件数组,写起来繁琐且不直观;
jsx可以直接写html标签,babel会将jsx转成render
6. 自定义指令钩子函数
5个钩子函数:
bind:只调用一次,指令第一次绑定到元素上的时候调用;
inserted:元素插入到父元素上的时候调用;
update:当前组件更新时调用,不管子组件是否更新;
componentUpdated:当前组件和子组件更新完成后调用;
unbind:解绑,只调用一次。
四个参数:
el(指令绑定的元素)、binding(一个对象,里面有很多值)、vnode(虚拟节点)、oldVnode(上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用)
除了 el 之外,其它参数都应该是只读的,切勿进行修改。
如果想修改value,可以dom.dispatchEvent(new Event('input'));
调用input事件使vue v-model绑定更新