前言
-
如何理解 MVVM
-
如何实现 MVVM
-
是否解读过 vue 的源码(理解能力 学习能力 自学能力)
面试问到的题目
-
说一下使用jQuery和使用MVVM框架的区别
-
说一下对 MVVM 的理解
-
vue 中如何实现响应式
-
vue 中如何解析模板
-
vue 的整个实现流程
实现一个todo-list
jQuery版
vue版
两者的区别:
-
数据和视图的分离
-
以数据驱动视图
说一下使用jQuery和使用MVVM框架的区别
-
数据和视图的分离,解耦(开放封闭原则)
-
以数据驱动视图,只关心数据变化,DOM 操作被封装
什么是MVVM
-
MVC
-
MVVM
-
关于 ViewModel
MVC
-
M:Model 数据
-
V:View 视图、界面
-
C:Controller 控制器、逻辑处理
MVVM
-
Model:模型、数据
-
View:视图、模板(视图和模型是分离的)
-
ViewModel:连接 Model 和 View
关于ViewModel
-
MVVM 不算是一种创新
-
但其中的 ViewModel 确实一种创新
-
真正结合前端场景应用的创建
解答
-
MVVM:Model View ViewModel
-
三者之间的联系、以及如何对应到各段代码
-
ViewModel 的理解,联系 View 和 Model,数据驱动视图,视图修改驱动数据变化
vue的MVVM
-
响应式:vue 如何监听到 data 的每个属性变化
-
模板引擎:Vue 的模板如何被解析,指令如何处理
-
渲染:vue 的模板如何被渲染成html?以及渲染过程
vue 中如何实现响应式
什么是响应式
-
修改 data 属性之后,vue 立刻监听到
-
data 属性被代理到 vm 中
-
Object.defineProperty
-
模拟
-
// var obj = {
-
// name: 'zhangsan',
-
// age: 25
-
// }
-
// console.log(obj) // {name: 'zhangsan',age: 25}
-
// var obj = {}
-
// var _name = 'shangsan'
-
// Object.defineProperty(obj, 'name', {
-
// get: function () {
-
// console.log('get', _name) // 监听
-
// return _name
-
// },
-
// set: function (newVal) {
-
// console.log('set', newVal) // 监听
-
// _name = newVal
-
// }
-
// })
-
// var vm = new Vue({
-
// el: '#app',
-
// data: {
-
// name: 'zhangsan',
-
// age: 20
-
// }
-
// })
-
var vm = {}
-
var data = {
-
name: 'zhangsan',
-
age: 20
-
}
-
var key, value
-
for (key in data) {
-
(function (key) { // 保证 key 的独立作用域
-
Object.defineProperty(vm, key, {
-
get: function () {
-
console.log('get', data[key]) // 监听
-
return data[key]
-
},
-
set: function (newVal) {
-
console.log('set', newVal) // 监听
-
data[key] = newVal
-
}
-
})
-
})(key)
-
}
-
关键是理解 Object.defineProperty
-
将 data 的属性代理到 vm 上
vue 中如何解析模板
模板是什么
-
本质:字符串
-
有逻辑,如 v-if v-for 等
-
与 html 格式很想,但有很大区别
-
最终还要转换为 html 来显示
-
分割线
-
模板最终必须转换成 JS 代码,因为
-
有逻辑(v-if v-for),必须用 JS 才能实现
-
转换为 html 渲染页面,必须用 JS 才能实现
-
因此,模板最终要转换成一个 JS 函数(render 函数)
render 函数
-
模板中所有信息都包含在了 render 函数中
-
this 即 vm
-
price 即 this.price 即 vm.price,即 data 中的 price
-
c 即 this.c 即 vm._c
-
从哪里可以看到 render 函数?(源码查找code.render 打印出来)
-
复杂一点的例子,render 函数是什么样子的?(参考下面的 todo-list)
-
vm._c 是什么?(创建元素)
render 函数与 vdom
-
vm._c 其实就相当于 snabbdom 中的 h 函数
-
render 函数执行之后,返回的是 vnode
-
updateComponent 中实现了 vdom 的 patch
-
页面首次渲染执行 updateComponent
-
data 中每次修改属性,执行 updateComponent
-
// jquery
-
// html
-
// <div>
-
// <input type="text" name="" id="txt-title">
-
// <button id="btn-submit">submit</button>
-
// </div>
-
// <div>
-
// <ul id="ul-list"></ul>
-
// </div>
-
var $txtTitle = $('#txt-title')
-
var $btnSubmit = $('#btn-submit')
-
var $ulList = $('#ul-list')
-
$btnSubmit.click(function () {
-
var title = $txtTitle.val()
-
if (!title) {
-
return
-
}
-
var $li = $('<li>' + title + '</li>')
-
$ulList.append($li)
-
$txtTitle.val('')
-
})
-
// vue
-
// <div id="app">
-
// <div>
-
// <input v-model="title">
-
// <button v-on:click="add">submit</button>
-
// </div>
-
// <div>
-
// <ul>
-
// <li v-for="item in list">{{item}}</li>
-
// </ul>
-
// </div>
-
// </div>
-
// data 独立
-
var data = {
-
title: '',
-
list: []
-
}
-
// 初始化 Vue 实例
-
var vm = new Vue({
-
el: '#app',
-
data: data,
-
methods: {
-
add: function () {
-
this.list.push(this.title)
-
this.title = ''
-
}
-
}
-
})
-
/*
-
with(this){ // this 就是 vm
-
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('div',
-
[
-
_c(
-
'ul',
-
_l((list),function(item){return _c('li',[_v(_s(item))])})
-
)
-
]
-
)
-
]
-
)
-
}
-
*/
vue 的整个实现流程
-
模板:字符串,有逻辑,嵌入 JS 变量……
-
模板必须转换为 JS 代码(有逻辑、渲染 html、JS 变量)
-
render 函数是什么样子的
-
render 函数执行是返回 vnode
-
updateComponent
流程:
第一步:解析模板成 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 ,初次渲染完成
第四步:data 属性变化,触发 rerender
-
修改属性,被响应式的 set 监听到
-
set 中执行 updateComponent
-
updateComponent 重新执行 vm._render()
-
生成的 vnode 和 prevVnode ,通过 patch 进行对比
-
渲染到 html 中
阐述自己对 React 和 vue 的认识
两者的本质区别
-
vue:本质是 MVVM 框架,有 MVC 发展而来
-
React:本质是前端组件化框架,由后端组件化发展而来
-
但这并不妨碍他们两者都能实现相同的功能
模板的区别
-
vue - 使用模板(最初由 angular 提出)
-
React - 使用 JSX
-
模板语法上,我更加倾向于 JSX
-
模板分离上,我更加倾向于 vue
-
模板应该和 JS 逻辑分离
-
回顾“开放封闭原则”
组件化的区别
-
React 本身就是组件化,没有组件化就不是 React
-
vue 也支持组件化,不过是在 MVVM 上的扩展
-
查阅 vue 组件化的文档,洋洋洒洒很多(侧面反映)
-
对于组件化,我更加倾向于 React ,做的彻底而清晰
两者共同点
-
都支持组件化
-
都是数据驱动试图
国内使用,首推 vue 。文档更易读、易学、社区够大
如果团队水平较高,推荐使用 React 。组件化和 JSX