polymer框架在代码中动态创建需要支持内容分发的自定义元素并挂载到文档中

使用场景:自己定义一个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的冲动,真是不爽。

原文地址:https://www.cnblogs.com/omega8/p/9146410.html