MVVM

一、说一下对 MVVM 的理解

Model - 模型、数据

View - 视图、模板(视图和模型是分离的)

ViewModel - 连接 Model 和 View

Vue三要素

一、响应式:vue 如何监听到 data 的每个属性变化?

1、什么是响应式

修改 data 属性之后,vue 立刻监听到

data 属性被代理到 vm 上

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

二、模板引擎:vue 的模板如何被解析,指令如何处理?

1、模板是什么

<div id="app">
    <h2>{{ news.title }}</h2>
    <ul>
        <li v-for="(value,index) in news.list">{{ value }}</li>
    </ul>
</div>

本质:字符串

有逻辑,如v-if  v-for等

与html格式很像,但有很大区别

最终还要转换为html来显示

模板最终必须转换成JS代码,因为:

有逻辑(v-if v-for),必须用JS才能实现

转换为html渲染页面,必须用JS才能实现

因此,模板最重要转换成一个JS函数(render函数)

<div id="app">{{ price }}</div>

var vm = new Vue({
    el: '#app',
    data: {
        price: 100
    }
})
function render() {
    with (this) { // this就是vm
        // _c  创建元素 (第一个参数:元素,第二个参数:元素属性,第三个参数:子元素)
        // ƒ (a, b, c, d) { return createElement(vm, a, b, c, d, false); }
        // _v创建一个文本节点
        // ƒ createTextVNode(val) {
        //     return new VNode(undefined, undefined, undefined, String(val))
        // }
        // _s toString  
        // ƒ toString(val) {
        //     return val == null
        //         ? ''
        //         : typeof val === 'object'
        //             ? JSON.stringify(val, null, 2)
        //             : String(val)
        // }
        return _c(
            'div',
            {
                attrs: { 'id': 'app' }
            },
            [
                _c('p', [_v(_s(price))])  // 将price转换成字符串,再创建成p的文本节点
            ]
        )

    }
}

不使用with

function render1() {
    return vm._c(
        'div',
        {
            attrs: { 'id': 'app' }
        },
        [
            vm._c('p', [vm._v(vm._s(price))])
        ]
    )
}

补充:如何查看模板的render方法(vue.js非压缩版本源码)

三、渲染:vue 的模板如何被渲染成 html ?以及渲染过程

 

 

四、vue的整个实现流程

<div id="app">
    <div>
        <input type="text" v-model="title">
            <button @click="add">submit</button>
    </div>
    <ul>
        <li v-for="item in list">{{ item }}</li>
    </ul>
</div>
var vm = new Vue({
    el: '#app',
    data: {
        title: '',
        list: []
    },
    methods: {
        add() {
            this.list.push(this.title)
            this.title = ''
        }
    }
})

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

with (this) {
    return _c(
        'div',
        { attrs: { "id": "app" } },
        [
            _c(
                'div',
                [
                    _c(
                        'input',
                        {
                            directives: [
                                {
                                    name: "model",
                                    rawName: "v-model",
                                    value: (title),
                                    expression: "title"
                                }
                            ],
                            attrs: { "type": "text" },
                            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))]) }) // _l for循环
            )
        ]
    )
}

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属性变化,触发render

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

set 中执行 updateComponent

updateComponent 重新执行 vm._render()

生成的 vnode 和 prevVnode ,通过 patch 进行对比

渲染到 html 中

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值