上两篇Mvvm教程的热度超出个人预期,不少码友留言表扬同时但愿我继续出下一篇教程,当时我也半开玩笑说只要点赞超10就兑现承诺,没想到还真破了10,因此就有了今天的文章。css
熟读
【教学向】150行代码教你实现一个低配版的MVVM库(1)- 原理篇
【教学向】150行代码教你实现一个低配版的MVVM库(2)- 代码篇html
本篇是在上两篇的基础之上对代码进行进一步扩展,从而实现web component功能,因此读者务必掌握mvvm的实现机制才能深刻理解本篇的内容(mvvm是web component的基石)。前端
目前市面上各大主流前端框架,凡事带web component功能的,他们的设计水准基本都不入个人法眼,惟一看得上眼的是google的polymer,可是在某些API设计层面也显得略微繁琐(想了解polymer的朋友看一翻一下我专栏里面10篇polymer入门系列教程)web
html提供的原生标签,好比DIV, BUTTON, INPUT家族,Hx家族等等,这些就比如俄罗斯方块里的一块块标准积木,咱们称它们为stand componentsegmentfault
某一天这些积木不能知足你的需求了,被扩展或被组合造成了非基本形状api
这些新形状就是custom component,自定义组件!为何要有component呢,好处是什么呢?前端框架
1. 能够复用 2. 结构清晰 3. 独立开发
你稍微开动下脑筋就能分析出来了,我就不展开了。框架
在座的各位都写过index.html么?很简单
主要就分红3大块内容,style, dom, scriptdom
<!--样式--> <style> </style> <!--DOM UI--> <body> </body> <!--逻辑--> <script> </script>
而后外面用个<html></html>包裹mvvm
因此这期低配版web component库设计目的很简单,做为一个开发人员,我但愿在写一个custom component的时候也能按照index.html的原生风格来写,这是多么的优雅,天然,没有学习成本啊!
这也应该是无数人心目中的web component设计
因此,咱们的SegmentFault.js v2.0的Web Component的设计宗旨就是,尽可能接近原生的html结构和使用习惯,接近原生从而把学习成本降到最低,是我追求的东西
<!-- myComp.html //文件名仍是以.html结尾,天然 --> <sf-component> <style> <!--css--> </style> <template> <!-- any dom--> <template> <script> //js </script> <sf-component>
写个具体的例子
<!-- myComp.html --> <sf-component> <style> button{ color:red; } p{ color:yellow; } </style> <template> <div> <input type="text" sf-value="this.message"/> <button sf-innerText="this.buttonName" onclick="this.clickHandler()"></button> <p sf-innerText="this.message"> </p> </div> </template> <script> this.message = "this is a component"; this.buttonName = "click me"; this.clickHandler = function(){ alert(this.message); }; </script> </sf-component>
一个Component的描述文件定义好了,那么接下去就是如何引入它了。沿用上篇Mvvm中的风格,咱们给SegmentFault这个Class弄个registerComponent(tagName,compPath)方法,好比在index.html中
var sf = new SegmentFault(); sf.registerController("xxx",xxx); ... sf.registerComponent("my-comp","components/myComp.html"); ... sf.init();
而在父组件中咱们就能够经过"my-comp"这个咱们刚刚注册时起的标签名来引入这个组件
<body> <div>...<div> <my-comp></my-comp> </body>
怎么样!四个字:干净利落
1. Mvvm 具有双向绑定功能 2. Shadow Style 具备独立的不污染全局的css功能 3. Communication 具备和父子兄弟组件通信的功能 4. 拥有生命周期 (属于高级功能,本低配版库不涉及)
Mvvm以前已经实现,咱们只要套用以前的实现便可
可能不少人对这个没什么概念,我沿用前文中的内容,好比咱们在component中定义了它的style,如
<!-- myComp.html --> <sf-component> <style> button{ color:red; } p{ color:yellow; } </style> <template> <div> ... </div> </template> <script> ... </script> </sf-component>
这里咱们在<style></style>标签中,定义了css,其中p和button的写法在传统观念中都是会影响html页面中全部的p元素和button元素的,这是咱们不但愿发生的,咱们但愿的是这个<style></style>标签生效的做用域仅仅是在当前的,被定义的component中。这种有独立做用域的css就叫Shadow Style。
要实现Shadow Style,其实有比较简单的作法,本篇设计篇中不会涉及,你能够趁此独立思考下,待下篇看看是否与我不谋而合,或者有比我更加高级的方案。
即组件之间的通信,常常有人在sf中问到这个组件通信问题,其实这个问题是有比较标准的答案的,即3点
1. 父子通信: 父->子 经过 set 属性, 子->父 抛事件 2. 兄弟通信: 大儿子 抛事件给 -> 父 -> set 小儿子 的属性 3. 远亲通信: 走消息总线 (其实就在一个单例上搞事件机制)
要实现通信机制,其实也不复杂,主要就2个功能,1 父组件能够set子组件的属性, 2 组件能够向外层抛事件,外层也能够监听组件抛出的事件,因此,咱们会如此设计这块的内容,觉个例子,代码说话
<body> <div>...<div> <my-comp sf-msg="vm.message" sf-oncustomevent="vm.customEventHandler"></my-comp> </body>
你们注意看,从父组件的角度,我可使用sf- + propertyName(这里是msg) 来实现外部父组件对组件的赋值,并且还能使用sf-on + 自定义事件名称(这里是customevent) 对组件进行监听。
换个角度,从子组件角度出发,我能够被外部赋值,我能够能够向外部dispatch事件。
<sf-component> <style> //... </style> <template> <div> <div class="compClass"> <input type="text" sf-value="this.message" /> <button sf-innerText="this.buttonName" onclick="this.clickHandler()"></button> <my-comp2 sf-msg="this.message"></my-comp2> <p sf-innerText="this.message + ', hi Component1'"> </p> </div> </div> </template> <script> this.buttonName = "click me"; this.clickHandler = function () { alert(this.message); this.dispatchEvent("customevent", "hello world");//为component的vm,内置一个dispatchEvent方法,用法和原生的事件机制一毛同样。 }; Object.defineProperty(this, "msg", { set: function (value) { if (value) { this.message = value; } } }); </script> </sf-component>
使用Object.defineProperty能够很大程度上知足咱们对set property的需求,另外再给component的vm挂载一个内置的函数this.dispatchEvent来发送自定义事件咱们就功德圆满了。
你能够给一个组件:由注册->加载定义->显示到DOM Tree->内容更新->从DOM Tree移除->销毁 等一系时间节点定义他的生命周期,若是是作的比较考究的库,你能够把这这些时间节点的变动都一一贯用户通知,或者提供api供用户控制。本文设计的低配版库阉割了这部分高级功能,咱们就是一教学向的库,不整这些有的没的。
至此,设计篇结束,主要介绍了一下本教学库的设计理念和一些web component的基本概念,欢迎点赞收藏评论,投硬笔投香蕉
若是本文阅读没有问题,请继续服用下一篇
【教学向】150行代码教你实现一个低配版的MVVM库(2)- 代码篇
【教学向】150行代码教你实现一个低配版的MVVM库(1)- 原理篇
【教学向】150行代码教你实现一个低配版的MVVM库(2)- 代码篇
【教学向】再加150行代码教你实现一个低配版的web component库(1) —设计篇
【教学向】再加150行代码教你实现一个低配版的web component库(2) —原理篇