简单展示什么是mvvm
题目
- 说一下使用jQuery和使用框架的区别
- 说一下对MVVM的理解
- vue中是如何实现响应式
- vue中如何解析模板
- vue的整个实现流程
使用jQuery和使用vue的区别
- 数据和视图的分离
- 以数据驱动视图
说一下对MVVM的理解
- MVVM - Model View ViewModel
MVVM三要素
- 响应式:vue如何监听到data的每个属性变化
- 模板引擎:vue的模板如何被解析,指令如何处理
- 渲染:vue的模板如何被渲染成html?以及渲染过程
要素1:vue如何实现响应式
- 关键是理解Object.defineProperty
- 将data的属性代理到vm上
// 模拟vue的将data属性代理到vue实例,并监听其数据变化,利用Object.defineProperty方法
var vm = {}
var data = {
name: 'zhangsan',
age: 20
}
var key, value
for (key in data) {
(function (key) {
Object.defineProperty(vm, key, {
get: function () {
console.log(data[key]) //监听
return data[key]
},
set: function (newVal) {
console.log(newVal) //监听
data[key] = newVal
}
})
})(key)
}
要素2:vue如何解析模板
- 模板是什么
- 本质:字符串
- 有逻辑,如v-if v-for
- 与html格式很像,但是有很大区别
- 最终还是要转化为html显示
- 模板是需要先转化为js代码(render函数)
要素3:渲染
- render函数
vue的整个实现流程
- 解析模板成render函数
- 响应式开始监听
- 首次渲染,显示页面,且绑定依赖
- data属性变化,出发rerender(重新pacth)
<div id="app">
<div>
<input v-model="title">
<button v-on:click="add">submit</button>
</div>
<ul>
<li v-for="item in list">{{item}}</li>
</ul>
</div>
<script src="vue.js"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
title: '',
list: []
},
methods: {
add: function () {
this.list.push(this.title)
this.title = ''
}
}
})
</script>
第一步:解析模板成render函数
<div id="app">
<div>
<input v-model="title">
<button v-on:click="add">submit</button>
</div>
<ul>
<li v-for="item in list">{{item}}</li>
</ul>
</div>
//render函数,返回vnode
with(this){return _c('div',{attrs:{"id":"app"}},[_c('div',[_c('input',{directives:[{name:"model",rawName:"v-model",value:(title),expression:"title"}],domProps:{"value":(title)},on:{"input":function($event){if($event.target.composing)return;title=$event.target.value}}}),_v(" "),_c('button',{on:{"click":add}},[_v("submit")])]),_v(" "),_c('ul',_l((list),function(item){return _c('li',[_v(_s(item))])}),0)])}
第二步,响应式开始监听
第三步:首次渲染,显示页面,绑定依赖
vm._updata(vnode) {
const preVnode = vm.vnode //老的vnode
vm._vnode = vnode //新vnode赋值
if (!preVnode) {
vm.$el = vm.__patch__(vm.$el, vnode)
} else {
vm.$el = vm.__patch__(preVnode, vnode)
}
}
function updataeComponent() {
vm._update(vm._render())
}
- 初次渲染,执行updateComponent ,执行vm._render()
- 执行render函数,会访问到vm.list 和 vm.title
- 会被响应式get方法监听到
- 执行updateComponent , 会走到vdom的patch方法
- patch 将 vnode 渲染成 DOM ,初次渲染完成
第四步:data属性变化,触发rerender
- 修改属性,被响应式的set监听到
- set中执行updateComponent
- updateComponent重新执行vm._render()
- 生成的vnode 和 preVnode, 通过patch进行对比
- 渲染到html中