【Vue】三、计算属性、插槽以及自定义事件
一、计算属性
当我们需要执行开销很大的一个function,比如说遍历一个超级长的数组啥的,如果这时候我们使用vue中的methods多次执行这个方法,那想必开销是相当大的!Vue中给我们提供了计算属性,来使得我们函数的结果保存在缓存中,直到数据发生变化之后才再次执行。这就大大减少了系统的开销。
我们在vue中使用computed标签定义计算属性,与methods非常相似。
<script>
var dirty = new Vue({
// 拿到id为dirty的对象
el : '#dirty',
computed:{
getNowTime2:function () {
//返回当前时间
return Date.now();
}
}
}
)
</script>
这时我们在页面上显示当前的时间戳。
但是我们过一段时间在浏览器中再使用以下getNowTime2
发现一直都没有改变,这是因为其是存储在了缓存中,如果这时候我们在getNowTime2中定义一个message,然后在浏览器中修改这个message,那这个getNowTime2就会重新执行,更新相关的值.
二、插槽Slot
Vue 实现了一套内容分发的 API,这套 API 的设计灵感源自 Web Components 规范草案,将 <slot>
元素作为承载分发内容的出口。
插槽就有点像啥啊,有点像java中一个可复用的库?或者说一个可复用的方法,你可以先给他占上地儿,之后再把值赋给他。
比如说我们先定义一个组件,组件中加入slot
Vue.component("zhanassi",{
template: "<div>" +
"<slot></slot>"+
"</div>"
});
var dirty = new Vue({
// 拿到id为dirty的对象
el : '#dirty'
}
)
然后我们试一下
<div id="dirty" >
<zhanassi>
jjnb!
</zhanassi>
</div>
在zhanassi中插入一行话
试一下发现可以的!
但是如果把插槽slot标签去掉,jjnb!就不会显示了。
也就是说:
如果 <zhanassi>
的 template
中没有包含一个 <slot>
元素,则该组件起始标签和结束标签之间的任何内容都会被抛弃。
所以说这里面相当于给占了一个地儿。
这里面也可以放html标签或者其他组件。
ok,这里我们可不可以动态的绑定插槽呢?
当然可!
这里我们还是新建两个component,里面分别定义一些参数
Vue.component("biaoti",{
//定义属性叫做title
props:['title'],
//动态获取item的值
template: "<div>{{title}}</div>"
});
Vue.component("liebiao",{
//定义属性叫做item
props:['item'],
//动态获取item的值
template: "<li>{{item}}</li>"
});
这里我们修改一下插槽,使得插槽后面的name为我们新定义两个组件的名称
Vue.component("zhanassi",{
template: "<div>" +
"<slot name='biaoti'></slot>"+
"<ul>" +
"<slot name='liebiao'>" +
"</slot>"+
"</ul>"+
"</div>"
});
之后我们在vue对象中定义一下数据
var dirty = new Vue({
// 拿到id为dirty的对象
el : '#dirty',
data:{
tit : "jj说Java",
todo :["nihao","wohao","dajiahao"]
}
}
)
然后html中的代码也要稍微修改一下
这里我们在标签中加入slot属性,属性值为你component的值,然后在使用v:bind命令使组件中的属性与我们vue对象中的属性进行绑定
<div id="dirty" >
<zhanassi>
<biaoti slot="biaoti" v-bind:title="tit"></biaoti>
<!-- 循环从TODO中获取itm-->
<liebiao slot="liebiao" v-for="itm in todo" v-bind:item="itm" ></liebiao>
</zhanassi>
</div>
最后运行下!
三、自定义事件
我们在上一个插槽的例子中在添加一些东西。
首先我们在liebiao组件中的template中定义一个按钮,其作用是为了将相关元素删除,然后我们在liebiao组件中定义一个index属性,用于记录数组中的下标位置。再定义一个remove空方法,button进行事件绑定,这里的@click 是 v-on:click的缩写,用于将按钮的点击事件与remove方法进行绑定。
Vue.component("liebiao",{
props:['item','index'],
template: "<li>{{index}}-----------{{item}}<button @click='remove'>删除</button></li>",
methods :
{
remove : function() {
//测试用
alert("jj!")
}
}
});
这里我们要与前端代码进行一个数据绑定,使用v:bind 将item与实际数组item绑定
<liebiao slot="liebiao" v-for="(itm,inx) in todo" v-bind:item="itm" v-bind:index="inx" ></liebiao>
绑定完成!没有问题!
这时候我们再vue对象dirty中定义一个method 用于删除数组中相关的元素
var dirty = new Vue({
// 拿到id为dirty的对象
el : '#dirty',
data:{
tit : "jj说Java",
todo :["nihao","wohao","dajiahao"]
},
methods: {
//传入一个index,删除index的元素
removeAttribute: function (index) {
var arr = this.todo.splice(index,1);
return arr;
}
}
}
)
通过浏览器控制台测试一下:
发现删除成功哈!
但是这时候我们怎么将vue对象中的function与组件中的这个删除按钮的点击事件绑定再一起呢?
首先我们要在前端html中通过v-on绑定事件
<!-- 通过v-on将组件中的remove方法绑定到vue对象中的removeAttribute方法,传入inx-->
<liebiao slot="liebiao" v-for="(itm,inx) in todo" v-bind:item="itm" v-bind:index="inx" v-on:remove="removeAttribute(inx)"></liebiao>
绑定了就完事儿了额?大错特错!我们还需要在组件中的remove方法定义自定义方法。
这里的第一个参数是组件内的方法名,第二个是要传递的参数
this.$emit('remove',index);
ok!我们这回点击尝试一下!
可以正常删除!
demo完整代码:
<!DOCTYPE html>
<html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--拿message,有点像el表达式-->
<div id="dirty" >
<zhanassi>
<biaoti slot="biaoti" v-bind:title="tit"></biaoti>
<!-- 循环获取itm-->
<liebiao slot="liebiao" v-for="(itm,inx) in todo" v-bind:item="itm" v-bind:index="inx" v-on:remove="removeAttribute(inx)"></liebiao>
</zhanassi>
</div>
<script src="https://cdn.bootcss.com/vue/2.5.16/vue.min.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
Vue.component("zhanassi",{
template: "<div>" +
"<slot name='biaoti'></slot>"+
"<ul>" +
"<slot name='liebiao'>" +
"</slot>"+
"</ul>"+
"</div>"
});
Vue.component("biaoti",{
props:['title'],
template: "<div>{{title}}</div>"
});
Vue.component("liebiao",{
props:['item','index'],
template: "<li>{{index}}-----------{{item}}<button v-on:click='remove'>删除</button></li>",
methods :
{
remove : function(index) {
this.$emit('remove',index);
}
}
});
var dirty = new Vue({
// 拿到id为dirty的对象
el : '#dirty',
data:{
tit : "jj说Java",
todo :["nihao","wohao","dajiahao"]
},
methods: {
removeAttribute: function (index) {
var arr = this.todo.splice(index,1);
return arr;
}
}
}
)
</script>
</body>
</html>