使用场景:自己定义一个confirm函数来替代浏览器自己的confirm,这个confirm执行之后弹出一个弹层,并展示相关提示信息,弹层的dom结构事先由polymer自定义组件定义好,假定组件名为my-confirm,代码如下。
<link rel="import" href="../modal-dialog/modal-dialog.html" /> <dom-module id="my-confirm"> <template> <!--modal-dialog组件实现的是弹层和居中等功能,可不用关注--> <modal-dialog title="{{title}}"> <div style="min-height: 2em;"> <!--此处使用内容分发,接收my-confirm的子节点--> <content></content> </div> <div style="text-align:center;"> <button on-click="ok" style="font-size: inherit;">确定</button> <button on-click="cancel" style="font-size: inherit;">取消</button> </div> </modal-dialog> </template> <script> Polymer({ is: 'my-confirm', properties: { "title": String, "fOk": Object, "fCancel": Object }, ok: function(e) { if("function" === typeof this.fOk){ this.fOk(e); } }, cancel: function(e) { if("function" === typeof this.fCancel){ this.fCancel(e); } } }); </script> </dom-module>
如果不嫌麻烦,可以在每个调用confirm函数的页面的body元素内都写一个<my-confirm></my-confirm>元素引用,confirm函数的作用只是控制my-confirm的显示和隐藏,这样也没什么不可以,但是不完美。我们想要的是<my-confirm></my-confirm>元素部分由confirm函数中的代码来创建,并挂载到body上,如果用户点击了“确定”或者“取消”,还要把它从body上移除。
下面是探索之路遇到的问题:
1.首先my-confirm组件的创建,直接用document.createElement函数就可以了,polymer就是浏览器的扩展,document.createElement可以直接创建polymer定义的元素。polymer也提供了个函数的简单包装Polymer.Base.create。
2.其次是给创建的my-confirm添加子元素,这个遇到问题了。my-confirm的实例appendChild函数可以调用,但不是我需要的效果,我在my-confirm组件里面使用了内容分发功能(即vue的插槽),原本my-confirm是要支持各种各样的弹出内容,不仅仅是文本,让它更具有扩展性,我就让my-confirm的子元素节点分发到my-confirm定义结构的指定位置,通过my-confirm实例的appendChild函数来添加子节点仅仅做了添加子节点的事情,并没有做内容分发,Polymer.Base.create函数也没有在创建的时候提供内容分发的支持。之后又尝试了使用给my-confirm的实例设置innerHTML属性的方式,这个不但不行,反而把my-confirm定义的结构给覆盖了,导致弹出层不展示。后来我发现my-confirm实例的内容在document.createElement的时候就已经把定义的结构给创建好了,意思是之后不管我再怎么操作它的子元素,都无效,除非有专门的api来事后做内容分发的事,但是没有找到。
几乎绝望之际,找到一种变通的方法,用document.createElement来创建一个div元素,而不是直接创建my-confirm,然后给div元素设置innerHTML,内容为<my-confirm>my confirm message</my-confirm>,让浏览器自己来创建my-confirm和它的子元素,这样my confirm message的部分成功的做了内容分发,被分发到了指定的位置。然后把div里面的my-confirm实例提取出来挂载到body上,代码如下。
function confirm(msg, cb, title){ var container = document.createElement("div"); container.innerHTML = "<my-confirm>"+msg+"</my-confirm>"; var dom = container.childNodes[0]; if(title){ dom.title = title; } else { dom.title = "提示"; } dom.fOk = function (){ document.body.removeChild(dom); cb(true); }; dom.fCancel = function (){ document.body.removeChild(dom); cb(false); }; document.body.appendChild(dom); };
polymer做着引领标准的事情,只是做一些浏览器扩展,而不是做一个大而贴心的框架,这是我喜欢它的地方。正因为如此,它做的事情却不多,导致功能弱,这也是我纠结的地方。尤其是用了vue的作用域插槽功能之后,发现polymer上没办法实现同样的功能,让我有放弃使用polymer的冲动,真是不爽。