ホームページ  >  記事  >  ウェブフロントエンド  >  vue 実装の 3 つのステップ (コード付き)

vue 実装の 3 つのステップ (コード付き)

不言
不言転載
2018-10-29 14:11:252209ブラウズ

この記事では、vue の実装を 3 つのステップで説明します (コード付き)。必要な方は参考にしていただければ幸いです。

Vue は現在、双方向のデータ バインディングを実行できるフレームワークとして人気があります。私が知っている理由は次のとおりです。

1. dom 構造を変更する従来の操作は非常に無駄な (つまり、遅い) 操作です。
2. dom 構造を変更するロジックを js 層に置くと、パフォーマンスが向上します。
3. データとビューの分離は、よりオブジェクト指向プログラミングに沿っています。 mvvm

vue の実装も、react と同様に仮想 dom を使用して実装されます。 js を使用してテンプレートを通じてレンダリングされた結果の dom。

vue を実装する手順はおそらく次の 3 つの手順です:

1. 応答性: vue は dota の各属性値の変更をどのように監視しますか?
2. テンプレート エンジン: Vue のテンプレートはどのように解析され、命令はどのように処理されるのでしょうか?
3. テンプレートのレンダリング: data 内のデータをテンプレートに追加して HTML にレンダリングする方法は?

ステップ 1: 応答性

応答性の実装は主にオブジェクトのメソッドに依存します:

Object.defineProperty

このメソッドは、オブジェクト内の属性の変更を監視し、論理的な処理を実行できます。

dome は次のとおりです:

    var obj={}
    var _name ='zhangsan'
    Object.defineProperty(obj,'name',{
        get:function() {
            console.log('get')
            return _name
        },
        set: function(newVal) {
            console.log('set')
            _name=newVal
        }
    })

ここで、name または access の値を変更します。 name の値 情報が出力されます。

そして、vue でのシミュレーションの実装は次のようになります。

        var vm ={}
        var data={name:'张三',age:20}
        var key,value;
        for(key in data) {
            (function(key){
                Object.defineProperty(vm,key,{  //绑定到vm上
                    get:function(){
                        console.log('get')
                        return data[key];
                    },
                    set:function(newVal){
                        console.log('set');
                        data[key]=newVal
                    }
                })
            })(key)  //闭包处理
        }

実際、Java を勉強した学生なら、Get についてよく知っているはずです。 Java クラスで直接生成し、メソッドを設定します。

2 番目のステップ: テンプレートを解析します。

テンプレートは、次の理由から JS コードに変換する必要があります。
#1. -for)、must これは js を使用してのみ実現できます。
2. 仮想 dom のレンダリングは js を使用して実現する必要があります。 (レンダー関数)

テンプレート 1

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

テンプレート 1

           with(this) { //this就是vm
                return _c(
                    'p',
                    {
                        attrs:{'id':'app'}
                    },
                    [
                        // _c是createElement
                        // _v是createTextVNode
                        // _s是toString方法
                        _c('p',[_v(_s(price))])
                    ]
                )
            }

によって変換されたレンダリング テンプレート 2

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

テンプレート 2 によって変換されたレンダリング

           with (this) {
                return _c(
                    'p',
                    { attrs: { "id": "app" } },
                    [
                        _c(
                            'p',
                            [
                                _c(
                                    'input',
                                    {
                                        //指令
                                        directives: [
                                            {
                                                name: "model",
                                                rawName: "v-model",
                                                value: (title),    //vm.title
                                                expression: "title"
                                            }
                                        ],
                                        domProps: {
                                            "value": (title) //vm.title 
                                        },
                                        on: {
                                            "input": function ($event) {
                                                if ($event.target.composing) return;
                                                title = $event.target.value
                                            }
                                        }
                                    }
                                ),
                                _v(" "),
                                _c(
                                    'button',
                                    {
                                        on: { "click": add }  //vm.add
                                    },
                                    [
                                        _v("submit")
                                    ]
                                )
                            ]
                        ),
                        _v(" "),
                        _c(
                            'p',
                            [
                                _c(
                                    'ul',
                                    _l(
                                        (list), function (item) {
                                            return _c(
                                                'li',
                                                [
                                                    _v(_s(item))
                                                ]
                                            )
                                        }
                                    )
                                )
                            ]
                        )
                    ]
                )
                 }

これは、レンダリングに使用されるレンダリング関数です。

3 番目のステップ: テンプレートとデータを html にレンダリングします

vm._update(Vnode) {
    const prevVonde=vm._Vnode
    vm._Vnode=Vnode;
    if(!prevVnode) {  //如果没有之前的vnode,第一次渲染
        vm.$el=vm._patch_(vm.$el,Vnode)
    }else {
        vm.$el=vm._patch_(prevVnode,Vnode)
    }
}
function updataComponent() {
    //vm._reander就是解析模板的rende函数,返回了一个vnode
    vm._update(vm._render())
}

ここの vm_.patch_ には、複雑な diff アルゴリズムが含まれています。レンダリングは DOM の違いに基づいており、多くの再帰呼び出しが使用され、効率の問題が多く発生します。

以上がvue 実装の 3 つのステップ (コード付き)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はsegmentfault.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。