实现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组件。效果如下:

好了看了效果,我们来看看具体怎么实现的吧。在线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;
        width: 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;
        width: 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

时间: 2024-08-07 17:53:23

实现checkbox组件化(Component)的相关文章

IBM特别开发出一套全新的企业模型-- 组件化商业模式(Component Business Model,CBM)

我有一个想法:EOM 我今天在对解决方案作领域分解(domain decomposition)的时候,想到从企业运营的角度出发,能不能提出一个企业运营图EOM(Enterprise Operation Map)的这么一个概念.EOM是一种业务过程模型或者框架,它为企业提供所要求的企业过程,它从企业的业务视图出发来描述需求,对业务过程进行分析和设计:再经过系统分析和设计,形成解决方案的分析和设计,最终建立系统并投入使用.EOM的重点在于对企业开展业务所涉及的过程单元和业务活动进行分类,并通过多种方

vue框架下的组件化的购物车实现

最近在学习vue,然后了解到这个框架的一个突出特点就是组件化,所以用这种形式实现了一个购物车,因为在实际项目中,数量加减可能不只在购物车里用到,所以把这个小的效果也提取出来了,在实现过程中形成了很多坑,这里记录一下,希望对大家能有所帮助. tip1: 这里会用到使用的组件库是vux,  需要先安装(npm insatall vux --save   npm install vux-loader --save-dev),然后具体怎么使用,如果不清楚请去看vux官网. 我把列表和底部的全选计数分别写

App 组件化/模块化之路——Android 框架组件(Android Architecture Components)使用指南

面对越来越复杂的 App 需求,Google 官方发布了Android 框架组件库(Android Architecture Components ).为开发者更好的开发 App 提供了非常好的样本.这个框架里的组件是配合 Android 组件生命周期的,所以它能够很好的规避组件生命周期管理的问题.今天我们就来看看这个库的使用. 通用的框架准则 官方建议在架构 App 的时候遵循以下两个准则: 关注分离 其中早期开发 App 最常见的做法是在 Activity 或者 Fragment 中写了大量

客户端高性能组件化框架React简介、特点、环境搭建及常用语法

明天就是春节了 预祝大家新春快乐 [ ]~( ̄▽ ̄)~* 天天饭局搞得我是身心疲惫= = 所以更新比较慢 今天想跟大家分享的就是这个大名鼎鼎的React框架 简介 React是这两年非常流行的框架 并不难,还是挺容易上手的 起源于Facebook内部项目(一个广告系统) 传统页面从服务器获取数据,显示到浏览器上,用户输入数据传入服务器 但随着数据量增大,越来越难以维护了 Facebook觉得MVC不能满足他们的扩展需求了(巨大的代码库和庞大的组织) 每当需要添加一项新的功能或特性时,系统复杂度就

Ques前端组件化体系

Ques是一套组件化系统,解决如何定义.嵌套.扩展.使用组件. 传统开发模式的痛点 无法方便的引用一个组件,需要分别引用其Javascript.Template.CSS文件 我们期望能以MV*的方式去写代码,结果发现只有Javascript是MV* UI库打包成一坨(类似Bootstrap),但是实际上UI库伴随产品迭代在反复变更,每次打开网站,用户依然反复下载UI库 CSS没有命名空间导致两个组件容易冲突 组件无法嵌套或者无法扩展,所以实际上组件根本无法复用 组件无法复制后可用,在组件无法嵌套

CSS组件化思考

为什么组件化? 分层设计,代码复用,减少冗余: 维护方便,弹性好: 如何组件化? 目前代码分成三级: 第一级粒度最细,是基础,主要包含字体配置,颜色配置,UI框架(比如MUI或者pure.css): 第二级是组件层,项目中出现两次及以上的样式单独抽离成一个组件,如果组件小于15个,单独放到一个component.less文件中,大于15个(界限自己把握),考虑放到几个不同的less文件中.因为样有些样式依赖于一定的DOM,所以需要针对less文件写一个HTML文件一一对应后于组件对应的DOM:

谈谈我对前端组件化中“组件”的理解,顺带写个Vue与React的demo

前言 前端已经过了单兵作战的时代了,现在一个稍微复杂一点的项目都需要几个人协同开发,一个战略级别的APP的话分工会更细,比如携程: 携程app = 机票频道 + 酒店频道 + 旅游频道 + ...... 每个频道有独立的团队去维护这些代码,具体到某一个频道的话有会由数十个不等的页面组成,在各个页面开发过程中,会产生很多重复的功能,比如弹出层提示框,像这种纯粹非业务的UI,便成了我们所谓的UI组件,最初的前端组件也就仅仅指的是UI组件. 而由于移动端的兴起,前端页面的逻辑已经变得很重了,一个页面的

谈笑风生组件化

在当今的前端开发领域,大红大紫的组件化开发如万人空巷,前端技术圈中关于组件化讨论的文章亦如汗牛充栋.然而别人的理解终归是别人的,作为一个胸存小志的开发者,我还是希望能够根据自己的理解和实际工作,总结自己对组件和组件化开发的认知. 在我第一次接触组件化概念时,一时迷迷糊糊,如坠云雾深处.组件是什么?组件化开发是什么?为什么大牛们知道这么多而我不知道?这应该并不是我个人的疑问,每一个除此接触概念的新手,都会有此疑惑. 为什么大牛们知道这么多而我不知道? 我曾经无数次为类似的问题而烦恼,也曾感到急躁难

从零开始的Android新项目11 - 组件化实践(1)

最近更新不太频繁,一方面工作上比较忙,除了 Android 也在负责前端,另外周末和深夜也在帮人做 Go 后台.设计技术方案.管进度的事情(因为报酬不错没忍心拒绝,而且确实对个人成长还有帮助),所以实在对不住. 另外,文章最底下有捐款啊,最近真是都没钱吃饭了... 前言 这里的组件化,指的是 MDCC 2016 上冯森林提出的<回归初心,从容器化到组件化>. 我个人一直是比较反感黑科技的,其中首当其冲的就是 插件化 以及 保活.作为一个开发者,除了研究技术,提高自己以外,是否应该考虑些其他东西