深入了解MVVM

前言

  • 如何理解 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

  • 模拟

 
  1. // var obj = {

  2. // name: 'zhangsan',

  3. // age: 25

  4. // }

  5. // console.log(obj) // {name: 'zhangsan',age: 25}

  6. // var obj = {}

  7. // var _name = 'shangsan'

  8. // Object.defineProperty(obj, 'name', {

  9. // get: function () {

  10. // console.log('get', _name) // 监听

  11. // return _name

  12. // },

  13. // set: function (newVal) {

  14. // console.log('set', newVal) // 监听

  15. // _name = newVal

  16. // }

  17. // })

  18. // var vm = new Vue({

  19. // el: '#app',

  20. // data: {

  21. // name: 'zhangsan',

  22. // age: 20

  23. // }

  24. // })

  25. var vm = {}

  26. var data = {

  27. name: 'zhangsan',

  28. age: 20

  29. }

  30. var key, value

  31. for (key in data) {

  32. (function (key) { // 保证 key 的独立作用域

  33. Object.defineProperty(vm, key, {

  34. get: function () {

  35. console.log('get', data[key]) // 监听

  36. return data[key]

  37. },

  38. set: function (newVal) {

  39. console.log('set', newVal) // 监听

  40. data[key] = newVal

  41. }

  42. })

  43. })(key)

  44. }

  • 关键是理解 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

 
  1. // jquery

  2. // html

  3. // <div>

  4. // <input type="text" name="" id="txt-title">

  5. // <button id="btn-submit">submit</button>

  6. // </div>

  7. // <div>

  8. // <ul id="ul-list"></ul>

  9. // </div>

  10. var $txtTitle = $('#txt-title')

  11. var $btnSubmit = $('#btn-submit')

  12. var $ulList = $('#ul-list')

  13. $btnSubmit.click(function () {

  14. var title = $txtTitle.val()

  15. if (!title) {

  16. return

  17. }

  18. var $li = $('<li>' + title + '</li>')

  19. $ulList.append($li)

  20. $txtTitle.val('')

  21. })

  22. // vue

  23. // <div id="app">

  24. // <div>

  25. // <input v-model="title">

  26. // <button v-on:click="add">submit</button>

  27. // </div>

  28. // <div>

  29. // <ul>

  30. // <li v-for="item in list">{{item}}</li>

  31. // </ul>

  32. // </div>

  33. // </div>

  34. // data 独立

  35. var data = {

  36. title: '',

  37. list: []

  38. }

  39. // 初始化 Vue 实例

  40. var vm = new Vue({

  41. el: '#app',

  42. data: data,

  43. methods: {

  44. add: function () {

  45. this.list.push(this.title)

  46. this.title = ''

  47. }

  48. }

  49. })

  50. /*

  51. with(this){ // this 就是 vm

  52. return _c(

  53. 'div',

  54. {

  55. attrs:{"id":"app"}

  56. },

  57. [

  58. _c(

  59. 'div',

  60. [

  61. _c(

  62. 'input',

  63. {

  64. directives:[

  65. {

  66. name:"model",

  67. rawName:"v-model",

  68. value:(title),

  69. expression:"title"

  70. }

  71. ],

  72. domProps:{

  73. "value":(title)

  74. },

  75. on:{

  76. "input":function($event){

  77. if($event.target.composing)return;

  78. title=$event.target.value

  79. }

  80. }

  81. }

  82. ),

  83. _v(" "),

  84. _c(

  85. 'button',

  86. {

  87. on:{

  88. "click":add

  89. }

  90. },

  91. [_v("submit")]

  92. )

  93. ]

  94. ),

  95. _v(" "),

  96. _c('div',

  97. [

  98. _c(

  99. 'ul',

  100. _l((list),function(item){return _c('li',[_v(_s(item))])})

  101. )

  102. ]

  103. )

  104. ]

  105. )

  106. }

  107. */

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

可以参考 深入了解virtual dom Script运行机制

原文https://mp.weixin.qq.com/s/0gjnCCDB8SZJjf3jhpgxcg

猜你喜欢

转载自blog.csdn.net/sinat_17775997/article/details/88286336