【Vue】3、计算属性、插槽以及自定义事件

it2025-03-24  14

【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>
最新回复(0)