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

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

一、计算属性

当我们需要执行开销很大的一个function,比如说遍历一个超级长的数组啥的,如果这时候我们使用vue中的methods多次执行这个方法,那想必开销是相当大的!Vue中给我们提供了计算属性,来使得我们函数的结果保存在缓存中,直到数据发生变化之后才再次执行。这就大大减少了系统的开销。

我们在vue中使用computed标签定义计算属性,与methods非常相似。

<script>
    var dirty = new Vue({
        // 拿到id为dirty的对象
        el : '#dirty',
      
        computed:{
            getNowTime2:function () {
                //返回当前时间
             return  Date.now();
            }
        }
        }
    )
</script>

这时我们在页面上显示当前的时间戳。

image-20201019164405801

但是我们过一段时间在浏览器中再使用以下getNowTime2

image-20201019164643578

发现一直都没有改变,这是因为其是存储在了缓存中,如果这时候我们在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中插入一行话

试一下发现可以的!

image-20201019190711870

但是如果把插槽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>

最后运行下!

image-20201021154013025

三、自定义事件

我们在上一个插槽的例子中在添加一些东西。

首先我们在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>

绑定完成!没有问题!

image-20201021195535963

这时候我们再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;
                }
            }

        }
    )

通过浏览器控制台测试一下:

发现删除成功哈!

image-20201021195809668

但是这时候我们怎么将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!我们这回点击尝试一下!

image-20201021200826132

可以正常删除!

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
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值