zoukankan      html  css  js  c++  java
  • MVVM 和 VUE

    一,使用jquery和使用vue的区别
    二,对MVVM的理解
    三,vue中如何实现响应式
    四,vue如何解析模版
    五,vue整个实现流程
     
    一,使用jquery和使用vue的区别
    jquery实现todo-list
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <title>todo-list-jquery</title>
    </head>
    
    <body>
        <div>
            <input type="text" id="txt-title">
            <button id="btn-submit">submit</button>
        </div>
        <ul id="ul-list"></ul>
        <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
        <script>
        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>todo-list-vue</title>
        <script src="./vue-2.5.13.js"></script>
    </head>
    
    <body>
        <div id="app">
            <div>
                <input v-model="title">
                <button v-on:click="add">submit</button>
            </div>
            <ul>
                <li v-for="item in list">{{item}}</li>
            </ul>
        </div>
        <script>
        var vm = new Vue({
            el: "#app",
            data: {
                title: '',
                list: [],
            },
            methods: {
                add: function() {
                    if (this.title) {
                        this.list.push(this.title);
                        this.title = '';
                    }
                }
            }
        })
        </script>
    </body>
    
    </html> 
    jquery和vue两者的区别:
    数据和视图的分离-解耦(开放封闭原则)
    以数据驱动视图-只关心数据变化,DOM操作被封装
     
    二,对MVVM的理解
    1,先说下MVC:
    M-Model 数据
    V-VIew 视图、界面
    C-Controller 控制器、逻辑处理
    两种场景:
    2,MVVM
    Model-模型、数据
    View-视图、模版(视图和模型是分离的)
    ViewModel-连接Model和View,“桥”
     
    3,关于ViewModel
    MVVM不算是一种创新-是微创新
    但其中的ViewModel是一种创新
    真正结合前端场景应用的创建
     
     
     
    4,MVVM框架的三大要素(实现的三要素)
    响应式:vue如何间听到data的每个属性变化?
    模版引擎:vue的模版如何被解析,指令如何处理?
    渲染:vue的模版如何被渲染成html?以及渲染过程
     
    三,vue中如何实现响应式
    1,什么是响应式
    修改data属性之后,vue立刻监听到
    data属性被代理到vm(this)上,data的属性,同时也变成了this的属性
    例:
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <title>vue-demo</title>
        <script src="https://cdn.bootcss.com/vue/2.5.16/vue.min.js"></script>
    </head>
    
    <body>
        <div id="app">
            <p>{{name}}</p>
            <p>{{age}}</p>
        </div>
        <script>
            var vm = new Vue({
                el:'#app',
                data:{
                    name:'zs',
                    age:20
                }
            })
            console.log(vm.age)
        </script>
    </body>
    
    </html>

     在控制台修改vm.age  或者vm.name,立刻会被监听渲染出来

    2,Object.defineProperty:直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象。
    语法:
    Object.defineProperty(obj, prop, descriptor)

    例子:

        var obj = {};
        var _name = 'zs';
        Object.defineProperty(obj,'name',{
            get:function(){
                console.log('get',_name);//监听
                return _name;
            },
            set:function(newVal){
                console.log('set',newVal);//监听
                _name = newVal;
            }
        });
    3,模拟实现(监听+代理)
        var vm = {};
        var data = {
            name: 'zs',
            age: 20
        };
        var key, value;
        for (key in data) {
            // 命中闭包,新建一个函数,保证key的独立的作用域
            (function(key) {
                Object.defineProperty(vm, key, { //data属性代理到vm上
                    get: function() {
                        console.log('get', data[key]); //监听
                        return data[key];
                    },
                    set: function(newVal) {
                        console.log('set', newVal); //监听
                        data[key] = newVal;
                    }
                })
            })(key)
        }
    看下控制台中,此时打印的vm
     
    四,vue如何解析模版
    1,模版是什么
    本质:字符串
    有逻辑,如v-if,v-for等
    与html格式很像,但有很大区别(html静态的,没有逻辑)
    要转换为html来显示
     
    模版最终必须要转换成js代码,原因如下:
    有逻辑(v-if,v-for),前端必须用js才能实现(图灵完备)
    转换为html渲染页面,前端必须用js才能实现
    因此,模版最终要转换成一个js函数(render函数,即渲染函数)
     
    2,render函数
    render函数-with的用法(with可以了解下实现,但是实际开发中最好不要用,问题比较多)
    先看下with的简单用法:
        var obj = {
            name: 'xx',
            age:20,
            getAddress:function(){
                console.log('bj');
            }
        }
        // 不用with
        function fn(){
            console.log(obj.name);
            console.log(obj.age);
            obj.getAddress();
        }
        fn()
    
        // 使用with
        function fn1(){
            with(obj) {
                console.log(name);
                console.log(age);
                getAddress();
            }
        }
        fn1()
    3,render函数
    模版:
        <div id="app">
            <p>{{price}}</p>
        </div>
        <script>
            var vm = new Vue({
                el:'#app',
                data:{
                    price:100
                }
            })
        </script>

    render函数如下:

        // 以下是手写的 render 函数 使用 with ,代码简洁一些
        function render() {
            with(this) {
                return _c(
                    'div', {
                        attrs: { "id", "app" }
                    }, [
                        _c('p', [_v(_s(price))])
                    ]
                )
            }
        }
        // 不用 with 的改写的 render 函数
        function render1() {
            return vm._c(
                'div', {
                    attrs: { "id", "app" }
                }, [
                    vm._c('p', [_vm.v(vm._s(vm.price))])
                ]
            )
        }
    
        // 模版中所有信息都包含在了 render 函数中
        // this === vm
        // price 即 this.price 即vm.price, 即 data 中的 price
        // _c 即 this._c , 即 vm._c

    看下控制台:

    问题:
    从哪里可以看到render函数?
    复杂一点的例子,render函数是什么样子的?
    v-if, v-for, v-on都是怎么处理的?
     
    回顾之前的demo
    <div id="app">
            <div>
                <input v-model="title">
                <button v-on:click="add">submit</button>
            </div>
            <ul>
                <li v-for="item in list">{{item}}</li>
            </ul>
        </div>

     对应的render函数:(通过在vue-2.5.13.js源码中 console.log(code.render)得出)

        with(this){
                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(
                        'ul',
                            _l(
                                (list),function(item){
                                    return _c(
                                        'li',
                                        [
                                            _v(
                                                _s(item)
                                            )   
                                        ]
                                    )
                                }
                            )
                        )   
                    ]
                )
            }
    根据todo-list demo的render函数:
    v-model是怎么实现的?:双向数据绑定,既有get,又有set
    v-on:click是怎么实现的?:渲染时绑定click事件
    v-for是怎么实现的?:对数组进行遍历,li标签,最后归结为数组,作为ul的子元素
     
    模版生成html  
    vm.c其实就相当于snabbdom中的h函数
    render函数执行之后,返回的是vnode
    vm._update(vnode) {
            const prevVnode = vm._vnode;
            vm._vnode = vnode;
            if (!prevVnode) {
                // 初次渲染
                vm.$el = vm.__patch__(vm.$el, vnode);
            } else {
                // re-render
                vm.$el = vm.__patch__(prevVnode, vnode);
            }
    
        }
    
        function updateComponent() {
            // vm._render即上面的render函数,返回vnode
            vm._update(vm._render())
        }
    
        // updateComponent实现了vdom的patch
        // 页面首次渲染执行updateComponent(执行第一个patch)
        // data中每次修改属性,执行updateComponent,修改data,set中可以执行updateComponent
    vue如何解析模版:
    模版:字符串(本质),有逻辑,嵌入js变量...
    模版必须转换为js代码(有逻辑,渲染html,js变量)前端中,只有js才能处理逻辑和渲染html等
    render函数: with语法,就是snabbdom里h函数的样子
    render函数执行是返回vnode
    updateComponent 首次渲染,非首次渲染(data属性修改)
     
    五,vue的整个实现流程
    第一步:解析模版成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,初次渲染完成
    疑问:
    为何要监听get,直接监听set不行吗?
    data中有很多属性,有些被用到,有些可能不被用到
    被用到的会走到get,不被用到的不会走到get
    未走到get中的属性,set的时候我们也无须关心
    避免不必要的重复渲染
     
    第四步:data属性变化,触发rerender
    修改属性,被响应式的set监听到
    set中执行updateComponent (这里是异步的)
    updateComponent重新执行vm._render()
    生成的vnode和prevVnode,通过patch进行对比
    渲染到html中

    附:Vue的生命周期 

    vue调试工具vue-devtools安装及使用

  • 相关阅读:
    2020面试有感(1)
    多线程与异步
    GP-荧光免疫分析仪SDK 协议
    FastReport模板设计和调用
    EF的多线程与分库架构设计实现(2)
    HTML页面转化为带有水印的PDF文件
    利用 html2canvas+jsPDF 把 HTML元素 转化为PDF文件,以及遇到的坑
    前端json数据格式化显示
    单元测试——引入Vuex
    单元测试——引入vue-router和APP.vue文件
  • 原文地址:https://www.cnblogs.com/iceflorence/p/8949788.html
Copyright © 2011-2022 走看看