MVVM 和 VUE vue調試工具vue-devtools安裝及使用

一,使用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,馬上會被監聽渲染出來css

2,Object.defineProperty:直接在一個對象上定義一個新屬性,或者修改一個對象的現有屬性, 並返回這個對象。
語法:
Object.defineProperty(obj, prop, descriptor)

例子:html

    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

看下控制檯:vue

問題:
從哪裏能夠看到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)得出)node

    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的生命週期 jquery

vue調試工具vue-devtools安裝及使用
相關文章
相關標籤/搜索