手记

MVVM MVC vue 与react

jQuery跟mvvm的区别:


通过一个todolist来对比下。




很明显,jQuery是直接操控dom的,而且视图跟model操作是没有分开的,而且操控的是实际的dom,并非是数据驱动。


而Vue是数据跟视图分离开的,然后由数据驱动视图的更新。


1.数据跟视图的分离,解耦

2.数据驱动视图,只关心数据变化,DOM操作被封装


MVC:view model controller



MVVM:view model viewModel




那么使用mvvm框架中,vue改变model中data的值,会反映到视图的改变,那么vue的响应式是如何实现的呢?

核心api:Object.defineProperty;将data的属性代理到vm上。

下面是模拟实现:

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('get', data[key]) // 监听
                        return data[key]
                    },
                    set: function (newVal) {
                        console.log('set', newVal) // 监听
                        data[key] = newVal
                    }
                })
            })(key)
        }

我们在vue中书写的vue文件模板是没法直接运行的,那么怎么解析模版到最后渲染成正常的html代码呢?

首先我们应该知道模板的本质是什么,模板是一整串有逻辑的字符串。

模板最后必须转换成js代码,因为里面有逻辑(v-if v-for)

,必须使用js才能实现(图灵完备),需要转换成html渲染页面,必须用js才能实现。

因此模板最重要的要能转换成一个js函数返回vnode(render函数)


下面render函数简单模拟实现:

var vm = new Vue({
            el: '#app',
            data: {
                price: 100
            }
           })
      // 以下是模拟的 render 函数
        function render() {
            with(this) {  // this 就是 vm
                return _c(
                    'div',
                    {
                        attrs: {'id': 'app'}
                    },
                    [
                        _c('p', [_v(_s(price))])
                    ]
                )
            }
        }
        function render1() {
            return vm._c(
                'div',
                {
                    attrs: {'id': 'app'}
                },
                [
                    vm._c('p', [vm._v(vm._s(vm.price))])
                ]
            )
        }

vm._c是创建元素节点,vm._v是创建文本节点,vm._s是toString,vm.price 是把data属性代理到vm,然后返回data.price

那么在vue的生命周期里,render函数是怎么起作用的呢?



下面总结一下vue的整个实现流程

第一步:解析模板成render函数

1.with的用法

2.模板中的信息都被render函数包含

3.模板中用到的data中的属性,都变成了js变量

4.模板中的v-model v-for v-on都变成了js逻辑

5.render函数返回vnode




第二步:响应式开始监听

1.Object.defineProperty

2.将data的属性代理到vm上


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('get', data[key]) // 监听
                        return data[key]
                    },
                    set: function (newVal) {
                        console.log('set', newVal) // 监听
                        data[key] = newVal
                    }
                })
            })(key)
        }

第三部:首次渲染,显示页面,且绑定依赖

1.初次渲染,执行updateComponent,执行vm._render(),也就是第一步返回的render函数

2.执行render函数,会访问到vm.list 和vm.title

3.会被响应式的get方法监听到

4.执行updateComponent,会走到vdom的patch方法,

5.patch将vnode渲染成dom,初次渲染完成


第四部:data属性变化,触发rerender

有了之前第二步的监听属性的set跟get之后


 Object.defineProperty(vm, key, {
                    get: function () {
                        console.log('get', data[key]) // 监听
                        return data[key]
                    },
                    set: function (newVal) {
                        console.log('set', newVal) // 监听
                        data[key] = newVal
                }
          })

接下来就是第四步的内容了。

1.修改属性被响应式的set监听到

2.set中执行updateComponent,这一步是异步的,所以vue的属性的修改也是异步的

3.updateComponent重新执行vm._render()

4.生成的vnode跟prevVnode,通过patch进行对比


React

组件化的理解:

1.组件的封装:封装组件的视图,数据,变化逻辑

2.组件的复用:props传递,复用

JSX是什么?

JSX其实是语法糖

开发环境将JSX编译成JS代码

JSX的写法大大降低了学习成本跟编码的工作量

JSX和vdom的关系:

1.jsx为什么需要vdom:jsx需要渲染成html,数据驱动视图

React.createElement和h,都生成vnode,createElement需要考虑自定义组件的名称,然后将其解析为自定义组件的render函数。

何时patch:ReactDom.render() 这个方法是在初次渲染的时候,执行了patch($el,Vnode)

setState在数据更新rerender的时候,执行了patch(preVnode,newVnode)

自定义组件的解析:初始化实例,然后执行render

例如List组件,
会经过类似这样的过程:
var list =new List({data:this.state.listData})
var vnode=list.render()

React setState的过程

setState是异步的,vue修改属性也是异步的

setState的过程步骤:

1.每个组件的示例,都有renderComponent方法,

2.执行renderComponent会重新执行实例的render

3.render函数返回newVnode,然后拿到preVnode,

4.执行patch(preVnode,newVnode)


模拟代码
renderComponent(){
const prevVnode=this._vnode;
const newVnode=this.render();
patch(prevVnode,newVnode);
this._vnode=newVnode;
}

为什么要异步,提高效率,如果用户多次setState,只要最终效果,渲染一遍。

React 与 Vue 的本质区别

1.vue 本质是MVVM框架,由MVC发展而来。React 本质是前端组件化框架,由后端组件化发展而来

2.vue使用模板,React使用JSX

3.React本身就是组件化,没有组件化就不是React。vue也支持组件化,不过是在MVVM上的扩展

React 与 Vue 共同点

支持组件化,数据驱动视图


5人推荐
随时随地看视频
慕课网APP