++本文系慕课网学习笔记++
如何理解 MVVM
如何实现 MVVM
是否解读过 vue 的源码(vue 中的 xx 功能是怎么实现的,重点是流程)
说一下使用 jquery 和使用框架的区别?
- 数据和视图的分离,解耦(开放封闭原则)
- 以数据驱动视图,只关心数据变化,DOM 操作被封装
// jQuery 实现 todoList
<div>
<input type="text" name="" id="txt-title">
<button id="btn-submit">submit</button>
</div>
<div>
<ul id="ul-list"></ul>
</div>
<script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
<script>
var $txtTitle = $('#txt-title');
var $ulList = $('#ul-list');
var $btnSubmit = $('#btn-submit');
$btnSubmit.click(function() {
var title = $txtTitle.val();
if (!title) {
return;
}
var $li = $('<li>' + title + '</li>');
$ulList.append($li);
$txtTitle.val('');
})
</script>
// vue 实现 todo-list
<div id="app">
<div>
<input v-model="title">
<button @click="add">submit</button>
</div>
<ul>
<li v-for="(item, index) in list" :key="index">{{ item }}</li>
</ul>
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.0.0/vue.js"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
title: '',
list: []
},
methods: {
add: function() {
if (this.title) {
this.list.push(this.title);
}
this.title = '';
}
}
})
</script>
说一下对 MVVM 的理解?
解答思路
- MVVM - Model View ViewModel(View 通过 事件绑定 影响 Model, Model 通过 数据绑定 影响 View)
- 三者之间的联系,以及如何对应到各段代码
- ViewModel 的理解, 联系 View 和 Model
Vue 三要素
- 响应式:vue 如何监听到 data 的每个属性的变化
- 模板引擎:vue 的模板如何被解析,指令如何处理
- vue 的模板如何被渲染成 html,以及渲染过程
vue 中如何实现响应式?
解答思路:
- 关键是理解 Object.defineProperty
- 将 data 的属性代理到 vm 上
什么是响应式
- 修改 data 属性后,vue 立刻监听到
- data 属性被代理到 vm 上
Object.defineProperty
var obj = {
name: 'zhangsan',
age: 25
}
console.log(obj.name) // 获取属性的时候如何监听到?
obj.age = 26 // 赋值属性的时候如何监听到?
var obj = {}
var name = 'zhangsan'
Object.defineProperty(obj, 'name', {
get: function() {
console.log('get')
return name
},
set: function(newVal) {
console.log('set')
name = newVal
}
})
console.log(obj.name)
obj.name = 'lisi'
模拟
// var vm = new Vue({
// el: '#app',
// data: {
// price: 100,
// name: 'zhangsan'
// }
// })
var vm = {}
var data = {
price: 100,
name: 'zhangsan'
}
var key, value
for (key in data) {
// 闭包,保证 key 的独立作用域
(function(key) {
Object.defineProperty(vm, key, {
get: function() {
return data[key]
},
set: functioon(newVal) {
data[key] = newVal
}
})
})(key)
}
vue 如何解析模板?
解答思路:
- 模板:字符串。有逻辑,嵌入 JS 变量
- 模板必须转换为 JS 代码(有逻辑,渲染 html, JS 变量)
- render 函数是什么样子的
- render 函数执行返回 vnode
- updateComponent
模板是什么
- 本质:字符串
- 有逻辑,如 v-if v-for 等
- 与 html 格式很像,但有很大区别
==模板最终必须转换成 JS 代码;因为有逻辑,必须用 JS 才能实现;转换为 html 渲染页面,必须用 JS 才能实现;模板最终要转换成一个 JS 函数(render 函数)==
<div id="app">
<div>
<input v-model="title">
<button @click="add">submit</button>
</div>
<ul>
<li v-for="(item, index) in list" :key="index">{{ item }}</li>
</ul>
</div>
render 函数
- 模板中所有信息都包含在了 render 函数中
- this 即 vm
- price 即 this.price,即 vm.price,即 data.price
- with 的用法
// 不用 with
function fn() {
alert(obj.name)
alert(obj.age)
obj.add()
}
// 使用 with
function fn1() {
with(obj) {
alert(name)
alert(age)
add()
}
}
<div id="app">
<p>{{ price }}</p>
</div>
// this 就是 vm 实例
function render() {
with(this) {
return _c(
'div',
{
attrs: {'id': app''}
},
[
_c('p', [_v(_s(price))])
]
)
}
}
- 从哪里可以看懂 render 函数?
- 搜索 code.render
- 复杂一点的例子,render 函数是什么样子的?
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,index){
return _c(
'li',
{
key:index
},
[
_v(_s(item))
]
)
}
)
)
]
)
}
- v-if v-for v-on 都是怎么处理的?
render 函数与 vdom
- updateComponent 中实现了 vdom 的patch
- 页面首次渲染执行 updateComponent
- data 每次修改属性,执行 updateComponent
vm._update(vnode) {
const preVnode = vm._vnode
vm._vnode = vnode
if (!perVnode) {
vm.$el = vm.__patch__(vm.$el, vnode)
} else {
vm.$el = vm.__patch__(preVnode, vnode)
}
}
function updateComponent() {
// vm._render 即上面的 render 函数, 返回 vnode
vm._update(vm._render())
}
vue 的整个实现流程?(几个核心的部分,和他们之间的关系)
-
第一步:解析模板成 render 函数
- with 的用法
- 模板中的所有信息都被 render 函数包含
- 模板中用到的 data 中的属性,都变成了 JS 变量
- 模板中的 v-model v-for v-on 都变成了 JS 逻辑
- render 函数返回 vnode
-
第二步:响应式开始监听
- Object.defineProperty
- 将 data 的属性代理到 vm 上
-
第三步:首次渲染,显示页面,且绑定依赖
- 初次渲染,执行 updateComponent,执行 vm_render()
- 执行 render 函数,会访问到 vm.list 和 vm.title
- 会被响应式的 get 方法监听到
- 执行 updateComponent,会走到 vdom 的 patch 方法
- patch 将 vnode 渲染成 DOM,初次渲染完成
为什么要监听 get,直接监听 set 不行吗?
- data中有很多属性,有些被用到,有些可能不被用到
- 被用到的会走 get,不被用到的不会走 get
- 未走到 get 的属性,set 的时候我们也无需关心
- 第四步:data 属性变化,触发 rerender
- 修改属性,会被 set 监听到
- set 中执行 updateComponent
- updateComponent 重新执行vm_render()
- 生成的 vnode 和 prevVnode,通过 patch 进行对比
- 渲染到 html 中
网友评论