• 实现checkbox组件化(Component)


    之前我写了一篇自定义checkbox的文章,通过css3实现自定义的checkbox,并没有使用当今流行的Reactjs, 或者Vuejs之类的进行组件化。但是很显然,这样封装的checkbox组件复用的时候非常麻烦。如果在新项目中使用的话,可能需要同时拷贝css和html文件进行整合。从html语义角度上讲,代码的易读性也不是很强,显然这样的组件显然不利于维护。

    其实Web Component是前端界一直非常热衷的一个领域,因为原生的HTML在维护复杂网页应用时,实在是太差了。所以才出现了诸如Google的Ploymer、Facebook的Reactjs等等。而且很多MVVM的框架也自带组件化的方案,例如Angularjs的指令,但貌似ng的这个用起来太复杂。用第三方组件化的框架去实现的话,你需要依赖框架本身很多东西,很多时候我们只是简单的几个组件,不是很大,也不是很多,所以为了保证组件的轻量,简单,其实这个时候我们并不想采用第三方的框架。接下来我会介绍使用Shadow DOMregisterElement的方式去实现组件化。

    先看看实现后的调用方式:

    <div class="line">
        <label>checkbox1
        </label>
        <check-box class="mycheck" checked="true" id="ComCheckbox"></check-box>
    </div>
    <div class="line">
        <label>checkbox2
        </label>
        <check-box class="mycheck" checked="false" id="ComCheckbox1" value="2"></check-box>
    </div>

    看起来是不是很简洁,调用自定义的checkbox组件不需要那么多扰乱阅读的元素,只需要一个明确的check-box标签,既可以表示checkbox组件。效果如下:

    Checkbox-Demo

    好了看了效果,我们来看看具体怎么实现的吧。在线demo查看

    组件的组成

    通常情况下,我们一个组件一般是由html模板,css样式,js脚本逻辑三部分组成的。他们的作用我就不多废话了。至于当前组件的css样式自定义方法请看我上一篇文章CSS3实现自定义checkbox,这里我就不重复这部分了。

    • 在项目工作区新建一个component-checkbox.html文件, 这个文件会被当做整个组件,在我们需要引用的页面中通过link标记动态的引入。 component-checkbox.html文件即包含了HTML模板,CSS样式,JS三个部分,他们在组件文件中的分布如下:
    <template>
        <style>// 放CSS样式定义</style>
    // 放HTML标记
    </template>
    <script type="text/javascript">
    // JS脚本逻辑
    </script>

    具体HTML/CSS定义

        <template id="CheckBox">
        <style>
        .slide-checkbox {
            position: relative;
             120px;
            height: 40px;
            line-height: 40px;
            border-radius: 30px;
            background: #4fbe79;
        }
        
        .slide-checkbox input[type=checkbox] {
            visibility: hidden;
        }
        
        .slide-checkbox label {
            position: absolute;
            height: 30px;
             30px;
            left: 5px;
            top: 5px;
            background: #FFFFFF;
            border-radius: 50% 50%;
            -webkit-transition: all .4s ease;
            -moz-transition: all .4s ease;
            -o-transition: all .4s ease;
            -ms-transition: all .4s ease;
            transition: all .4s ease;
        }
        
        .slide-checkbox input[type=checkbox]:checked + label {
            left: 85px;
        }
        </style>
        <div class="slide-checkbox">
            <input type="checkbox" name="checkbox" id="SlideCheck" />
            <label for="SlideCheck"></label>
        </div>
    </template>

    JS的实现

    这种组件实现发方法,重点地方就在JS脚本这个部分,所以请看下面的详细描述。

    1. Shadow DOM说明

    Shadow DOM提供了一种独立封装`html', 'css', 'js'到组件文件的一种方法,这样Shadow DOM内部的样式文件及js等等都与引用页面处于隔离状态,互相独立,所以不必担心他们之间会不会出现样式,js相互乱引用的情况出现。当然调用页面与Shadow DOM的通信则需要通过js来完成。

    2. registerElement说明

    可以在浏览器中实现自定义element, 当然会有人想到说'document.createElement()'方法也可以创建不同的元素,但是很显然registerElement更强大些,具体就不展开了。

    3. 详细JS代码

    // Whether registerElement is supported
    function isCustomElementSupported() {
        return 'registerElement' in document;
    }
    
    (function() {
        "use strict";
        if (isCustomElementSupported()) {
            var objectPrototype = Object.create(HTMLElement.prototype);
            var selfDoc = document.currentScript.ownerDocument;
    
            Object.defineProperty(objectPrototype, 'value', {
                get: function() {
                    return this.getAttribute("value") || null;
                },
                set: function(value) {
                    this.setAttribute("value", value);
                }
            });
    
            Object.defineProperty(objectPrototype, 'checked', {
                get: function() {
                    return this.getAttribute("checked") || false;
                },
                set: function(isChecked) {
                    shadowChecked(this, isChecked);
                    this.setAttribute("checked", isChecked);
                }
            });
    
            objectPrototype.createdCallback = function() {
                var self = this;
                var rootElement = self.createShadowRoot();
                var templateContent = selfDoc.querySelector("#CheckBox").content;
                var nodes = document.importNode(templateContent, true);
                
                // Add template content to shadowRoot element
                rootElement.appendChild(nodes);
                
                var checkbox = rootElement.querySelector("#SlideCheck");
                // init checked value
                if (self.checked == "true") {
                    checkbox.checked = true;
                }
    
                // Add change event to checkbox
                checkbox.addEventListener('change', function() {
                    self.checked = this.checked;
                });
            };
    
            var checkbox = document.registerElement('check-box', {
                prototype: objectPrototype
            });
        }
    
        // update shadow root 
        function shadowChecked(self, isChecked) {
            var shadowCheck = self.shadowRoot.querySelector("#SlideCheck");
            shadowCheck.checked = isChecked;
        }
    })();

    4. 代码描述

    该代码片段先定义了一个registerElement支持情况的检测方法。在匿名函数中先经过支持检测后,通过Object对象创建了有一个HTMLElement的原型对象,用于注册checkbox继承HTMLElement时使用。 同时我们在原型对象上定义了checkedvalue对象,方便调用组件时使用。通过get,set方法我们与其相对应的checkedvalue属性(attribute)产生联系,便于数据通信。

    createdCallback方法在组件被创建后执行。首先将获取到template里的内容添加到rootElement中, 添加完后我们便可以进行一些初始化组件的操作。例如初始化checked的状态值, 模板内置的checkbox添加change的事件绑定,便于实时更新组件当前的checked值。

    组件的使用

    1. 引用组件

    首先我们需要在要使用该组件的HTMl页面中引入组件文件。
    注:由于该文件是用过HTTP读取过来的,所以静态项目可能无法获取组件文件,需要把这些文件放到服务器目录下去访问。 引入方式:

    <link rel="import" href="com-checkbox.html">

    2. 使用

    在需要使用该组件的位置放入组件标签即可:

    <check-box class="mycheck" checked="true" value="1" id="ComCheckbox"></check-box>

    注:class为样式类名,checked为初始化状态, value为checkbox值。

    当然你也可以多次引用组件,例如同时使用4个,实际状况中可能会更多:

    <div class="line">
        <label>checkbox1
        </label>
        <check-box class="mycheck" checked="true" value="1" id="ComCheckbox"></check-box>
    </div>
    <div class="line">
        <label>checkbox2
        </label>
        <check-box class="mycheck" checked="false" value="2" id="ComCheckbox1" value="2"></check-box>
    </div>
    <div class="line">
        <label>checkbox3
        </label>
        <check-box class="mycheck" value="3" checked=false id="ComCheckbox2" value="3"></check-box>
    </div>
    <div class="line">
        <label>checkbox4
        </label>
        <check-box class="mycheck" value="4" checked="true" id="ComCheckbox3" value="4"></check-box>
    </div>

    3. 获取check-box的状态和值

    var checkbox = document.querySelector("#ComCheckbox");
    console.log(checkbox.checked); // output: true
    console.log(checkbox.value); // output: 1

    根据ID获取元素,可通过checkedvalue对象直接访问。

    4. 实现checkbox全选和取消

    var checkboxs = document.querySelectorAll("check-box");
    
    function selectAll() {
        for (i = 0; i < checkboxs.length; i++) {
            checkboxs[i].checked = true;
        }
    }
    
    function cancleSelectAll() {
        for (i = 0; i < checkboxs.length; i++) {
            checkboxs[i].checked = false;
        }
    }

    获取所以的checkbox列表, 然后遍历改变checked的状态。其他复杂操作或者情况可以再组件定义时进行扩展。

    总结

    以上便是整个组件定义的具体方法。当然今天我们自定义的是checkbox组件,我们当然可以通过该方法去实现其他的组件,例如radio,select等等。

    原文地址:http://imziv.com/blog/article/read.htm?id=72

  • 相关阅读:
    Tsql 获取服务器信息
    数据字典生成脚本 【转载】
    c# winform文本框数字,数值校验
    ReentrantLock和AbstractQueuedSynchronizer的分析
    多线程
    前缀和与差分数组
    链表
    堆(优先队列)
    排序算法
    二分查找(递归和非递归)
  • 原文地址:https://www.cnblogs.com/zivxiaowei/p/5509969.html
Copyright © 2020-2023  润新知