Home >Web Front-end >JS Tutorial >Learn and understand vue source code together

Learn and understand vue source code together

零下一度
零下一度Original
2017-06-26 09:50:481432browse

According to the official website of vue, we can know that vue is an mvvm framework and is responsive. In order to have a deeper understanding of its connotation, I implemented a simple mvvm learning demo. Share it with everyone below and welcome everyone to discuss it together.

1. At least the content of mvvm

  1. Instruction set, such as: text, model, etc.

  2. Data model, and View interactive data

  3. Component support: that is, dynamic update of part of the html code

2. My implementation

1. Definition of variables and implementation of watch

var directives = {}; //指令集合var vNodes = new Array(); //解析的Dom集合var dataModel = {
    name:"name",
    title: "title"}; //数据Modelvar Watch = {
    isInit: false,
    watchs: new Array(),
    run: function(newValue, expOrfn){ var self = this;if(!self.isInit){
            expOrfn.call(vModel);
        }this.watchs.map(function(data,index){
            data.nodes.map(function(d,i){if(self.isInit){
                    d.directive.init(newValue, d, data); //绑定初始化值, 以及初始化一些事件}else{
                    d.directive.update(newValue, d, data); //只更新值,此时run的调用来值value-set                }
            });
        });
        
        self.watchs = [];
    },
    push:function(watch){this.watchs.push(watch);
    }
} //任务管理

Description:

  1. Watch push method , used to add dependencies, and then run to execute all dependencies. After the execution is completed, the current dependency collection needs to be cleaned up. The collection of dependencies in vue is completed in dep, and the task management provided by watch (I don’t know if I understand it correctly)

2. Definition of instructions

directives.text = { 
    init: function(value, vNode){
        vNode.elm.textContent = value;
    },
    update: function(value, vNode){
        vNode.elm.textContent = value;
    }
}//需要响应事件的怎么办directives.model ={ 
    init: function(value, vNode, _watch){
        vNode.elm.value = value; //判断自己发生的改变,不应该再改变自己 vNode.elm.addEventListener('keyup',function(evt){
            vNode.model[_watch.key] = vNode.elm.value;
        }); 
    },
    update:function(){

    }   
}

Description:

  1. Since it is a demo learning example, only two simple text and model specifications are defined. , text: used for data display, and model used for input (input box) response

3. Generation of vModel

//转换vModel,暂支持一级var properties = Object.getOwnPropertyNames(dataModel);var vModel = {}, formSetting = false;for( var index in properties){ 
    (function refreshData(_index){var key = properties[_index];var property = Object.getOwnPropertyDescriptor(dataModel, key);var setter = property.set;var getter = property.get;var _val = property.value;var _getter = function(){var val = getter ? getter.call(vModel) : _val;//收集依赖,与watch要分开            Watch.push({
                key: key,
                nodes: vNodes.filter(function(data,index){return data.modelKey == key ? true : false;
                }),
                getter: _getter
            });return val;
        };
        Object.defineProperty(vModel, key, {
            configurable: true,
            enumerable: true,
            set: function(value){if(setter){
                    setter.call(vModel, value);
                } //处理依赖                Watch.run(value, _getter);//this.value = value;            },
            get: _getter

        })
    })(index);
}

Note:

  1. vModel is generated based on dataModel, that is, the get and set methods of each attribute are customized. It can also be implemented using proxy in es6 ( Is it correct? ).

  2. When setting an attribute, the get method will be called first to collect dependencies. After the convenience value is changed, all the affected content can be modified.

4. Parse dom as vNode

//解析vNodesvar app = document.getElementById('app');
app.childNodes.forEach(function(data,index){if(data.nodeType != 1) return;var hv = data.getAttribute('data-hv');var hvs = hv.split(',');
    hvs.forEach(function(item,row){var keyValue = item.split(':'); //vNode对象上一定要有model,这是方便vNode相应时候的找vModel        vNodes.push({
            directive: directives[keyValue[0]],
            modelKey: keyValue[1],
            model: vModel,
            elm: data
        });
    });
});

Instructions:

  1. Here it is parsed as vNode It is very far-fetched, because this only collects the instructions specified by data-hv on the dom, and stores the corresponding instructions, elements, vModel, etc. into an object in vNodes for reference when the get method of each attribute of the vModel collects dependencies.

5. First initialization

//调用所有的get一次Watch.isInit = true;var _keys = Object.getOwnPropertyNames(vModel);
_keys.map(function(key,data){var data = vModel[key];
    Watch.run(data); 
});
Watch.isInit = false;

Instructions:

  1. The vModel that will be initialized The value is rendered to the Dom. Here, each get is actively executed, and then the watch.run method is run.

  2. I feel that the design and implementation here are not consistent with vue’s ideas. If anyone sees this, please give me some advice and guidance.

6. Parsed dom

<div id="app"><span data-hv="text:title"></span><span data-hv="text:title"></span><input data-hv="model:title" /></div>

The above is the detailed content of Learn and understand vue source code together. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn