实现checkbox组件化(Component)

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

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

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

<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组件。效果以下:html

 

Checkbox-Demo

 

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

组件的组成

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

  • 在项目工做区新建一个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脚本这个部分,因此请看下面的详细描述。node

1. Shadow DOM说明

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

2. registerElement说明

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

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)产生联系,便于数据通讯。github

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

组件的使用

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