正文:
源码来源于vuejs的commit记录:a5e27b1174e9196dcc9dbb0becc487275ea2e84c
作者在src
下实现了一个简单的指令和过滤器, 下面来看下基本的实现过程(代码有部分删改和伪代码):
-
首先定义了一个
prefix
用来标记自定义的指令,找出所有带有指令的dom节点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
中进行进行数据劫持。;[].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) } }
-
看下劫持的时候做了什么:
-
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 ) }) } }) }
-
具体实现可以参考代码实现,以上只是大体思路
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。