您的位置:首页 > Web前端 > HTML

HTML中动态生成内容的事件绑定问题

2015-11-04 21:39 429 查看
        在实际开发过程中,有时需要向页面中动态的插入html内容,并在插入的节点中绑定事件处理函数。

        用Javascript向HTML文档中插入内容,有两种方法,一种是JS创建节点,然后插入到html中;另外一种是通过ajax异步加载的方式,从服务器获取数据,然后用js把获取的数据经过处理后插入html中。

<1> JS创建节点插入html中

<div id="a">
<ul>
<li>行1</li>
<li>行2</li>
<li>行3</li>
</ul>
</div>

<script type="text/javascript">
var ele = document.createElement("p");
ele.innerHTML = "这是插入的内容";
document.getElementById("a").appendChild(ele);
var tag = document.getElementById("a").getElementsByTagName("p");
for (var i = 0;i < tag.length;i++)
{
tag[i].onclick=function()
{
console.log("Click Event!");
}
}
</script>

        页面会生成一个p标签并且点击p标签控制台会输出Click Event!毫无疑问js代码和html顺序不可更改,因为页面还没加载到页面内容。可以用以下jquery版本测试:

<script type="text/javascript">
$(function()
{
$("p").click(function()
{
console.log("Click!");
})
$("<p>这是生成的内容</p>").appendTo("#a");
})
</script>        这个时候其实我们已经得出结论了,当需要的内容还没有被插入时,选择器只会选择页面中已经存在的元素,所以事先没有存在元素是绑定不了事件的。

        但是,实际情况是,工作中有可能需要把后来生成的元素绑定上事件,并注册上事件处理函数。例如本网站的留言系统,第一次加载只会显示固定条数的评论,如果评论超过一定数量,剩下的会用ajax的方式进行加载。所有的留言最后都有个回复功能,点击可以恢复相应的留言,也就是说,动态加载上来的留言,也许要绑定click事件,并注册上回复留言的函数。当然偷懒的方法是,为ajax加载上来的内容再注册一个click并再绑定一次相应的函数,但这加大了代码的冗余度,增加系统开销,还会使代码变得难以理解。那么更好的解决办法是什么呢?

留言系统的回复功能

留言系统的回复功能

可以这样理解,无论HTML内容是不是JS生成的,只要没有跨域,所有页面内的元素都属于这个页面,都能够绑定事件,JS中有个非常重要的概念叫事件冒泡,简单来讲,就是子元素产生的事件,会一直冒泡到最顶级父元素,并能够被父元素监测到。请看下图:

事件冒泡

事件冒泡

那么,我能不能在被插入元素的父元素上监测冒泡产生的事件,并回调相应的函数呢?答案是当然是肯定的。来看下面的例子,注意网页面里插入内容是在JS代码的最后。

    $(function(){

        $("body").delegate("p","click",function(){

            console.log("Click Event");

        })    

        $("<p>这是生成的内容</p>").appendTo("body");

    })

这是,发现所有的P元素点击都产生了输出,说明代码运行成功。这里我们用到了jQuery的delegate函数,来看一下官方解释:

    Attach a handler to one or more events for all elements that match the selector, now or in the future, based on a specific set of root elements.

    根据特定的根元素,把一个或者多个事件注册到指定的元素上,不论这个元素现在是否存在。

在jQuery1.7.3以上的版本中,on方法也可以做这件事,官方有示例说明,这里不再赘述。

jQuery提供一个强大的API来解决这个问题,原生的JS怎么去做呢?下面给出一个简单方案,希望能对大家理解冒泡的原理有所帮助。

    <script>

    function gelegate(action,selector,callback){

        document.addEventListener(action,function(e){

            if(selector==e.target.tagName.toLowerCase()||selector==e.target.className){

                console.log("Click Event");

                callback();

            }

        })

    }

    gelegate('click','p',function(){});

    var appendhtml=document.createElement("p");

    appendhtml.innerHTML="这是插入的内容";

    document.body.appendChild(appendhtml);

    </script>

注意,以上代码仅针对chrome,实际项目可能会产生兼容性问题。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: