vue考点 —— MVVM

  • 说一下使用jQuery和框架(vue)的区别
  • 说一下对MVVM的理解
  • vue中如何实现响应式(vue如何检讨到data的每个属性的变化)
  • vue如何解析模板(vue的模板如何被解析,指令如何处理)
  • vue的整个实现流程(vue的模板如何被渲染成html,渲染过程)

一、jQuery实现todo-list

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div>
    <input type="text" name="" id="txt-title">
    <button id="btn-submit">submit</button>
</div>
<div id="ul-list"></div>
<script src="jquery-1.12.4.min.js"></script>
<script type="text/javascript">
    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('')
    })
</script>
</body>
</html>

二、vue实现todo-list

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <div>
        <input type="text" v-model="title">
        <button id="btn-submit" v-on:click="add">submit</button>
    </div>
    <div id="ul-list">
        <ul>
            <li v-for="item in list">{{item}}</li>
        </ul>
    </div>
</div>
<script src="https://cdn.bootcss.com/vue/2.5.17-beta.0/vue.min.js"></script>
<script>
    var vm = new Vue({
        el:'#app',
        data:{
            title:'',
            list:[]
        },
        methods: {
            add: function(){
                this.list.push(this.title)
                this.title = ''
            }
        }
    })
</script>
</body>
</html>

vue实现的时候没有修改DOM结构,而jQuery实现的时候有操作DOM的结构。

三、jQuery和框架的区别

  • 数据和视图的分离,解耦(开放封闭原则)

jQuery中数据处理的逻辑和数据已经混合在一起了。jQuery中数据视图并未分离,而vue数据试图分离了。

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

只改数据,试图怎么变我不管,jQuery完全违背了这个理念。vue用数据驱动了试图的变化。

四、MVC

五、MVVM

MVVM —— Model View ViewModel。ViewMode的理解,联系View和Model。

六、MVVM(vue)框架的三大要素

  • 响应式:vue如何监听到data的每个属性变化
  • 模板引擎:vue的模板如何被解析,指令如何处理
  • 渲染:vue的模板如何被渲染成html,以及渲染过程

1、vue中如何实现响应式

什么是响应式?响应式就是data属性被修改之后,vue立刻监听到。data属性被代理到vm上。

2、Object.defineProperty

var obj = {
        name: 'zhangsan',
        age: 25
    }
    console.log(obj.name)    //获取属性的时候,如何监听到
    obj.age = 26    //赋值属性的时候,如何监听到

我们使用Object.defineProperty来监听

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'      //可以监听到

vue中实现监听的原理(vue响应式模拟)

var vm = {}
    var data = {
        name: 'zhangsan',
        age: 20
    }
    var key, value
    for(key in data){
        (function(key){    //将data里面的值代理到了vm上面
            Object.defineProperty(vm, key ,{
                get: function(){
                    return data[key]
                },
                set:function(newVal){
                    data[key] = newVal
                }
            })
        })(key)
    }

3、模板是什么?

如下就是一个模板,就是上面doto-list里面的:

<div id="app">
    <div>
        <input type="text" v-model="title">
        <button id="btn-submit" v-on:click="add">submit</button>
    </div>
    <div id="ul-list">
        <ul>
            <li v-for="item in list">{{item}}</li>
        </ul>
    </div>
</div>

模板本质上是字符串。但是模板有逻辑,因为它有v-for  v-if等。它与HTML很像,但是有很大区别,因为HTML是静态的,模板是动态的。但是模板最终最转化成HTML来显示。模板是一串字符串,最终必须转化成JS代码,因为有逻辑,必须要JS才能处理逻辑,还有就是最后转换成HTML渲染页面,必须使用JS才能实现。因此,模板最重要的是转换成JS函数(render函数)

4、render函数 —— width的用法

5、render函数

左边的模板,生成右边的render函数,右边是render函数的函数体。右边的this就是vm 。模板中所有信息都包含在render函数中,this即vm,price即this,price即vm.price,即data中的price。

下面是一个例子:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="vue.js"></script>
</head>
<body>
    <div id="app">
        <p>{{price}}</p>
    </div>
    <script>
        var vm = new Vue({
            el:'#app',
            data: {
                price: 10
            }
        })
        //以下是手写的ppt中的render函数
        //使用width
        function render() {
            with(this){  //这里的with就是vm
                _c(
                    'div',
                    {
                        attrs:{'id': 'app'}
                    },
                    [
                        _c('p',[_v(_s(price))])
                    ]
                )
            }
        }

        //不使用with
        function render1() {
               return vm._c(
                    'div',
                    {
                        attrs:{'id': 'app'}
                    },
                    [
                        vm._c('p',[vm._v(vm._s(vm.price))])
                    ]
                )
        }
    </script>
</body>
</html>

5、todo-list的模板的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',
                        {
                            attrs:{"id":"btn-submit"},
                            on:{
                                "click":add
                            }
                        },
                        [_v("submit")]
                    )
                ]
            ),
            _v(" "),
            _c(
                'div',
                {attrs:{"id":"ul-list"}},
                [
                    _c(
                        'ul',
                        _l((list), function(item){return _c('li',[_v(_s(item))])})
                    )
                ]
            )
        ]
    )
}

v-modele是怎么实现的:双向数据绑定,既有get,又有set

v-click是怎么实现的:绑定click事件

v-for是怎么实现的:for循环遍历

6、模板生成html,也就是render函数和html之前的关系。

render函数返回vnode,_c和h函数是一样的,返回vnode。

7、题目解答

  • 模板:字符串,有逻辑,嵌入JS变量
  • 模板必须转换为JS代码(有逻辑,渲染html,JS变量)
  • render函数是什么样子的
  • render函数执行返回vnode
  • updataComponent

七、vue的整个实现流程

  • 第一步:解析模板成render函数
  1. with的函数
  2. 模板中的所有信息都被render函数包含
  3. 模板中用到的data中的属性,都变成了JS变量
  4. 模板中的v-model  v-for  v-on都变成了JS逻辑
  5. render函数返回vnode
  • 第二步:响应式开始监听
  1. Object.definePrototype
  2. 将data的属性代理到vm上
  • 第三步:首次渲染,显示页面,且绑定依赖
  1. 初次渲染,执行updateComponent,在执行vm._render()
  2. 执行render函数,会访问到vm.list和vm.title
  3. 会被响应式的get方法监听到(为何监听get,直接监听set不行吗?因为data中有很多属性,有些会被用到,有些可能不被用到,被用到的会走到get,不被用到的不会走get。未走到get中的属性,set的时候我们也无需关心。目的是避免不必要的重复渲染)
  4. 执行updateComponent,会走到vdom的patch方法
  5. patch将vnode渲染成DOM,初次渲染完成
  • 第四步:data属性变化,触发rerender
  1. 修改属性,被响应式的set监听到
  2. set中执行updateComponent
  3. updateComponent重新执行vm._render()
  4. 生成的vnode和prevVnode,通过patch进行对比
  5. 渲染到HTML中

八、题目解答

  • 说一下使用jQuery和使用框架的区别

解答:(1)数据视图的分离,解耦。(2)以数据驱动试图,只关心数据变化,DOM操作被封装。

  • 说一下对MVVM的理解

解答:(1)Model  View  ViewModel。(2)三者之间的联系,以及如何对应到隔断代码。(3)ViewModel的理解,联系View和Model。

  • vue中如何实现响应式

解答:(1)关键是理解Object.definePrototype。(2)将data的属性代理到vm上

  • vue中如何解析模板

解答:(1)模板:字符串,有逻辑,嵌入JS变量。(2)模板必须转化为JS代码(有逻辑、渲染HTML、JS变量)。(3)render函数是什么样子。(4)render函数执行是返回vnode。(4)updateComponent。

  • vue的整体实现流程

解答:(1)解析模板成render函数。(2)响应式开始监听。(3)首席渲染,显示页面,且绑定依赖。(4)data属性变化,触发rerender

猜你喜欢

转载自blog.csdn.net/zhanghuali0210/article/details/82287544