Avalon 的 ms-duplex 的問題

轉:https://segmentfault.com/a/1190000005362826前端

前端框架 Avalon 有一個問題,即 在使用 ms-duplex 後,此 input 在 Windows 8.1 的 IE11 下沒法正常使用輸入法輸入中文,這個問題在 Avalon 1.5.X 中一直存在且被複現。segmentfault

既然沒法直接修復,那麼就使用 avalon.directive 自定義一個新的指令來簡單地處理雙向數據綁定。起名爲 ms-model,名字來源於 Angular.數組

avalon.directive("model", {
    init: function (binding) {
        // binding 爲指令初始化時注入對象.
        init(binding)();
    },

    // 此方法相似 Get / Set, 在控制器使用 $watch 監視 (binding.expr, 即 ms-model="expr") 時觸發, 可在此作一些雜七雜八的事情.
    update: function (newVal, oldVal) {
        // this 爲 init 中的 bingding 對象.
        this.element.value = newVal;
    }
});


// Definition: ms-model.
function init (binding) {

    var thisElement = binding.element;  // 指令所在的節點.
    var directiveValue = binding.expr;  // 指令綁定的屬性.
    var imeIgnored = false;  // 輸入法忽略控制標識.

    // 初始化賦值. 必須推入任務隊列才生效.
    setTimeout(function () {
        thisElement.value = binding.oldValue !== undefined ? binding.oldValue : "";  // 未賦值進行清空, 防止 IE / Edge 緩存.
    }, 1);

    // Definition: Input 事件.
    var inputEvent = function (event) {
        if (imeIgnored) { return; }
        // vmodels 是指令所在的控制器的數組, 看起來是按照 [孫, 子, 父] 的冒泡順序排序, 但未確定.
        // ms-duplex 只處理了指令所在的最近的控制器的數值, 在此也只處理 vmodels[0].
        eval('binding.vmodels[0].' + directiveValue + ' = thisElement.value;');   // 使用 eval 解決多層嵌套問題.
    };


    return function () {
        // 在使用輸入法的時候不進行數據同步.
        // 進入輸入法狀態時鎖定控制標識.
        avalon.bind(thisElement, "compositionstart", function () {
            imeIgnored = true;
        });

        // 輸入法恢復時釋放控制標識.
        avalon.bind(thisElement, "compositionend", function () {
            imeIgnored = false;
            inputEvent();  // Fixing for Edge, Edge 的日語輸入法的 input 事件在 compositionend 以前執行, 而其餘瀏覽器包括 IE11 全是 compositionend 以後, 須要手動觸發一次.
        });

        // 設置 Input 事件.
        avalon.bind(thisElement, "input", inputEvent, false);

        // 修復 IE 問題.
        if (window.ScriptEngine && window.ScriptEngine()) {

            // 修復 IE9 的 Backspace / Delete 剪切不觸發 Input 事件的問題.
            if (navigator.appVersion.indexOf("MSIE 9.0") > -1) {
                avalon.bind(thisElement, "cut", function () {
                    setTimeout(inputEvent, 1);  // 必須推入任務隊列中執行才生效.
                });
            }

            // IE 額外註冊 KeyUp 進行數據綁定來避免輸入法無效的問題.
            avalon.bind(thisElement, "keyup", function (event) {
                event = event || window.event;
                if (event.keyCode === 17 || event.keyCode === 18 || event.ctrlKey || event.shiftKey || event.altKey) { return; }
                inputEvent();
            });

        }
    }
}
相關文章
相關標籤/搜索