翻译的很差,轻拍css
Polymer是google的一款前端开发框架,其基于Shadow DOM、Custom Elements、MDV等最新浏览器特性构建,表明了下一代Web框架的方向:一切皆组件、尽可能减小代码量、尽可能减小框架限制。html
Web components标准主要由如下3个部分组成:前端
Polymer的核心是Custom Elements,定义一个Polymer元素和定义一个普通的Custom Elements是差很少的。主要的区别就是Polymer使用polymer-element
标签进行声明。node
<polymer-element name="tag-name" constructor="TagName"> <template> <!-- 在这里放置shadow DOM --> </template> <script>Polymer('tag-name');</script> </polymer-element>
Polymer在polymer-element
标签上预留了一些特殊的attribute。数组
Attribute | 必要 | 描述 |
name | 是 | Polymer元素名,名称中须要包含"-" |
attributes | 否 | 指定元素的Published properties |
extends | 否 | 指定元素继承其它元素 |
noscript | 否 | 不须要调用Polymer()的简单元素 |
constuctor | 否 | 放置在全局对象(如window )中的元素构造器名,容许用户经过new 来新建此元素.(如: var tagName = new TagName() ) |
你在polymer-elemnet
上设置的其余 attribute 将会自动添加到元素实例上。例如:浏览器
<polymer-element name="tag-name" class="active" mycustomattr> <template>...</template> <script>Polymer('tag-name');</script> </polymer-element>
当一个tag-name
实例被建立的时候,它就会自带两个默认 attribute : class="active"
和mycustomattr
。闭包
<tag-name class="active" mycustomattr></tag-name>
HTML解析器对 attribute 大小写敏感是没有必要的,可是Javascript却对大小写敏感。app
书写时你能够忽略属性名的大小写,可是当你运行并查看元素的属性列表时,属性名永远都是小写的,Polymer会谨慎的将* property* 和 attribute 一一配对。例如:框架
<name-tag nameColor="blue" name="Blue Name"></name-tag>
在DOM中nameColor
是小写的,而且一般都会被忽略不处理。dom
下面例子也都会正常工做:
<name-tag NaMeCoLoR="blue" name="Blue Name"></name-tag> <name-tag NAMECOLOR="red" name="Red Name"></name-tag> <name-tag NAMEcolor="green" name="Green Name"></name-tag>
考虑到重构的须要,咱们有时候不会将脚本放置在元素标签里,而是独立成一个文件。Polymer元素也能够经过外部脚本中调用Polymer('tag-name')
来建立。
<!-- 1. 在元素声明内部添加外部脚本 --> <polymer-element name="tag-name"> <template>...</template> <script src="path/to/tagname.js"></script> </polymer-element> <!-- 2. 在元素声明以前添加外部脚本 --> <script src="path/to/tagname.js"></script> <polymer-element name="tag-name"> <template>...</template> </polymer-element> <!-- 3. 没有脚本 --> <polymer-element name="tag-name" constructor="TagName" noscript> <template> <!-- shadow DOM here --> </template> </polymer-element>
元素也能够只经过JS来注册:
<script> Polymer('name-tag', {nameColor: 'red'}); var el = document.createElement('div'); el.innerHTML = '\ <polymer-element name="name-tag" attributes="name">\ <template>\ Hello <span style="color:{{nameColor}}">{{name}}</span>\ </template>\ </polymer-element>'; //若是不将这个元素声明放入DOM内的话,custom elements的polyfill就找不到它。 document.body.appendChild(el); </script> <name-tag name="John"></name-tag>
须要注意的是,要将polymer-element
放入DOM中,这样custom element
的polyfill才能找到它。
若是你想要定义一些方法或者 property 时(可选),在Polymer()的第二个参数中传递包含定义信息的对象便可。
下面这个例子中,定义了一个property: message
, 一个使用到了ES5 getter特性的property: greeting
, 还有一个方法:foo
。
<polymer-element name="tag-name"> <template></template> <script> Polymer('tag-name', { message: "Hello!", get greeting() { return this.message + ' there!'; }, foo: function() {...} }); </script> </polymer-element>
注释: this是这个Polymer元素在本身内部他自己的引用。例如:this.localName == 'tag-name'.
注意: 当元素的property是一个js对象或者数组时须要注意,因为prototype
的一些特性,你可能会在同一类元素的不一样实体中,陷入shared state
问题。若是你想初始化一个property为对象或者数组的时候,不要在prototype
中赋值,而应该在created
回调中赋值。
// 正确 Polymer('x-foo', { created: function() { this.list = []; // Initialize and hint type to be array. this.person = {}; // Initialize and hint type to an object. } }); // 错误 Polymer('x-foo', { list: [], // Don't initialize array or objects on the prototype. person: {} });
若是须要私有对象的话,将Polymer()放置在匿名自调函数里便可。
<polymer-element name="tag-name"> <template>...</template> <script> (function() { // 只会运行一次 var foo_ = new Foo(); // 每个实例建立时都会运行 Polymer('tag-name', { get foo() { return foo_; } }); })(); </script> </polymer-element>
有时候你但愿定义一个全局变量,而且在不一样的元素中使用它。好比你会定义一个配置信息,而后在其它部件中引用这个配置。或者一个运动曲线用于处理不一样的动画效果,或者一个变量用于保存当前登陆用户的信息。
你可使用MonoState Pattern来实现这个目标。当定义一个Polymer元素时,定义一个闭包,将须要的变量放入进去,而后在元素的prototype
上设置访问器,或者在构造器里把他们赋值到不一样的实例上。
<polymer-element name="app-globals"> <script> (function() { var firstName = 'John'; var lastName = 'Smith'; Polymer('app-globals', { ready: function() { this.firstName = firstName; this.lastName = lastName; } }); })(); </script> </polymer-element>
而后像使用其余元素同样把它放置到另外一个元素声明里,将须要的property绑定到实例上,这样就可使用Polymer的数据绑定技术来访问它了。
<polymer-element name="my-component"> <template> <app-globals id="globals"></app-globals> <div id="firstname"></div> <div id="lastname"></div> </template> <script> Polymer('my-component', { ready: function() { this.globals = this.$.globals; } }); </script> </polymer-element>
只要作一些轻微的调整,就能够在外部配置全局变量的值了。
<polymer-element name="app-globals"> <script> (function() { var values = {}; Polymer('app-globals', { ready: function() { for (var i = 0; i < this.attributes.length; ++i) { var attr = this.attributes[i]; values[attr.nodeName] = attr.nodeValue; } } }); })(); </script> </polymer-element>
在主页中,专递 attribute 就能够配置全局变量了。
<app-globals firstName="Addy" lastName="Osmani"></app-globals>
Polymer对于元素声明周期回调有着一流的支持,为了方便,回调函数都用了简短的名称。
全部这些回调都是可选的:
Polymer('tag-name', { created: function() { ... }, ready: function() { ... }, attached: function () { ... }, domReady: function() { ... }, detached: function() { ... }, attributeChanged: function(attrName, oldVal, newVal) { //var newVal = this.getAttribute(attrName); console.log(attrName, 'old: ' + oldVal, 'new:', newVal); }, });
下面是custom elements和Polymer元素的生命周期方法的对照表:
Custom Elements | Polymer | 触发条件 |
createdCallback | created | 一个元素的实例被建立 |
- | ready | polymer-element 已经彻底准备好。(例如:shadow DOM建立完成,事件已绑定等等) |
attachedCallback | attached | 当一个元素的实例被插入到DOM中 |
- | domReady | Called when the element’s initial set of children are guaranteed to exist. This is an appropriate time to poke at the element’s parent or light DOM children. Another use is when you have sibling custom elements (e.g. they’re .innerHTML‘d together, at the same time). Before element A can use B’s API/properties, element B needs to be upgraded. The domReady callback ensures both elements exist. |
detachedCallback | detached | 当实例从DOM中移除 |
attributeChangedCallback | attributeChanged | attribute被添加移除或者改变。注意: 要监听一个公开的property,应该使用 changed watchers |
Polymer经过异步的方式来处理自定义元素定义和升级。若是你在元素尚未升级的时候,就经过DOM来获取它,你只会获得一个HTMLUnknownElement
。Polymer元素有时还会使用外部元素,例如css,若是他们尚未彻底加载完毕,就可能引发FOUC的问题。为了不FOUC,Polymer只有在css等资源所有加载完毕以后才会注册元素。
经过polymer-ready事件就能够得知元素什么时候注册/升级完。
<head> <link rel="import" href="path/to/x-foo.html"> </head> <body> <x-foo></x-foo> <script> window.addEventListener('polymer-ready', function(e) { var xFoo = document.querySelector('x-foo'); xFoo.barProperty = 'baz'; }); </script> </body>