Home > Article > Web Front-end > Learn and understand vue source code together
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.
Instruction set, such as: text, model, etc.
Data model, and View interactive data
Component support: that is, dynamic update of part of the html code
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:
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)
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:
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
//转换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:
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? ).
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.
//解析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:
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.
//调用所有的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:
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.
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.
<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!