虽然Vue不提倡也很少需要手动生成DOM,但是有时难免需要手动生成新的标签,此时,手动生成的新标签也像原生JS操作DOM一样,不会绑定事件,如以下例子:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Vue事件委托</title>
<style>
ul,
li {
list-style-type: none;
margin: 0;
padding: 0;
}
li {
width: 50%;
line-height: 2;
background-color: rgba(0, 0, 0, 0.2);
margin-bottom: 2rem;
cursor: pointer;
}
</style>
</head>
<body>
<div id="app">
<ul ref="ul">
<li v-for="(item,index) in arr" :key="index" @click="clickLi(item)">{{item}}</li>
</ul>
</div>
<script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script>
<script>
var vm = new Vue({
el: "#app",
data: {
arr: [1, 2, 3, 4, 5, 6]
},
methods: {
clickLi(item) {
alert(item);
var newLi = document.createElement("li");
var text = "666"
newLi.textContent = text;
console.log(newLi);
this.$nextTick(() => {
this.$refs.ul.appendChild(newLi);
})
console.log(this.$refs.ul);
}
}
})
</script>
</body>
</html>
这就需要在Vue使用事件委托了,通过给其父类添加事件响应,给每个li加上自定义属性以便获取每个item数据,然后通过事件冒泡把事件传递到子li的item元素,通过获取它的自定义属性值即可。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Vue事件委托</title>
<style>
ul,
li {
list-style-type: none;
margin: 0;
padding: 0;
}
li {
width: 50%;
line-height: 2;
background-color: rgba(0, 0, 0, 0.2);
margin-bottom: 2rem;
cursor: pointer;
}
</style>
</head>
<body>
<div id="app">
<ul ref="ul" @click="clickUl">
<li v-for="(item,index) in arr" :key="index" @click="clickLi(item)" :data-item="item">{{item}}</li>
</ul>
</div>
<script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script>
<script>
var vm = new Vue({
el: "#app",
data: {
arr: [1, 2, 3, 4, 5, 6]
},
methods: {
clickLi(item) {
// alert(item);
// var newLi = document.createElement("li");
// var text = "666"
// newLi.textContent = text;
// console.log(newLi);
// this.$nextTick(() => {
// this.$refs.ul.appendChild(newLi);
// })
// console.log(this.$refs.ul);
},
clickUl(e) {
var e = e || window.event;
var target = e.target || e.srcElement;
if (target.nodeName.toLowerCase() === "li") {
console.log(target.getAttribute('data-item'));
}
}
}
})
</script>
</body>
</html>