簡單的指令和過濾器實現

正文:

源碼來源於vuejs的commit記錄:a5e27b1174e9196dcc9dbb0becc487275ea2e84cjavascript

做者在src下實現了一個簡單的指令和過濾器, 下面來看下基本的實現過程(代碼有部分刪改和僞代碼):vue

  1. 首先定義了一個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);
            // ...
        }
  2. 遍歷全部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)
        }
    }
  3. 看下劫持的時候作了什麼: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


clipboard.png

相關文章
相關標籤/搜索