源碼來源於vuejs的commit記錄:a5e27b1174e9196dcc9dbb0becc487275ea2e84cjavascript
做者在src
下實現了一個簡單的指令和過濾器, 下面來看下基本的實現過程(代碼有部分刪改和僞代碼):vue
首先定義了一個prefix
用來標記自定義的指令,找出全部帶有指令的dom節點java
var prefix = 'sd', selector = Object.keys(Directives).map(function (d) { return '[' + prefix + '-' + d + ']' }).join() function Seed (opts) { var self = this, root = this.el = document.getElementById(opts.id), // els即爲全部帶有sd前綴指令的dom els = root.querySelectorAll(selector); // ... }
遍歷全部dom節點和自定義指令,而後所有記錄在bindings
中,最後在 bindAccessors
中進行進行數據劫持。git
;[].forEach.call(els, processNode) function processNode (el) { cloneAttributes(el.attributes).forEach(function (attr) { var directive = parseDirective(attr) if (directive) { bindDirective(self, el, bindings, directive) } }) } function bindDirective (seed, el, bindings, directive) { el.removeAttribute(directive.attr.name) var key = directive.key, binding = bindings[key] if (!binding) { bindings[key] = binding = { value: undefined, directives: [] } } directive.el = el binding.directives.push(directive) if (!seed.scope.hasOwnProperty(key)) { bindAccessors(seed, key, binding) } }
看下劫持的時候作了什麼:github
get
: 和初版同樣,從binding
中取值set
: 在bingding
中設置新值,遍歷binding
中存儲的自定義指令並進行綁定和更新function bindAccessors (seed, key, binding) { Object.defineProperty(seed.scope, key, { get: function () { return binding.value }, set: function (value) { binding.value = value binding.directives.forEach(function (directive) { if (value && directive.filters) { value = applyFilters(value, directive) } directive.update( directive.el, value, directive.argument, directive, seed ) }) } }) }
具體實現能夠參考代碼實現,以上只是大致思路app