【Vue】计算属性、插槽与内容分发、自定义事件以及$emit的使用

一、计算属性

计算属性是用来声明式的描述一个值依赖了其它的值。当你在模板里把数据绑定到一个计算属性上时,Vue 会在其依赖的任何值导致该计算属性改变时更新 DOM。这个功能非常强大,它可以让你的代码更加声明式、数据驱动并且易于维护。

上述描述可是使用一句话作为概括:计算属性时具有缓存的,当计算的结果没有发生改变时直接调用缓存,当计算的结果发生改变时,将会重新计算。

计算属性的特点就是将不经常改变的计算结果进行缓存,节约系统的开销。


计算属性的逻辑(方法)是写在computed中的。

methodscomputed中的方法不要重名,如果重名,methods的优先级高于computed


通常情况下,data01和data02的值都会是从服务器端获取,这样的话,只有当服务器返回的data01和data02的值发生改变的时候才会从新结算example,否则直接电泳缓存即可。

    var vm = new Vue({
        el:"#app",

        data: {
            data01:10,
            data02:20
        },
        computed: {
            example: function () {
                return this.data01+this.data02
            }
        }
    })

computed中的方法进行调用的时候的格式:方法名

<div id="app">
    <h3>{{example}}</h3>
</div>

当然我们也是可以使用cache: false手动关闭缓存.

        computed: {
        	cache: false,
            example: function () {
                return this.data01+this.data02
            }
        }

methods中的方法进行调用的时候格式:方法名()

<div id="app">
    <h3>{{example()}}</h3>
</div>
    var vm = new Vue({
        el:"#app",

        data: {
            data01:10,
            data02:20
        },
        methods: {
            example: function () {
                return this.data01+this.data02
            }
        }
    })



二、插槽与内容分发slot

1.插槽

我们在没有接触插槽之前,当我们使用我们自定的组件的时候,可以发现,当我们在自定义的组件的标签体中写入内容的时候,并不会生效。

    Vue.component("my-component",{
        template:`
             <ul>
                 <li>寒江のjava世界</li>
                 <li>寒江のpython世界</li>
             </ul>
            `
    })
    var vm = new Vue({
        el:"#app"
    })
<div id="app">
    <my-component>寒江のC++世界</my-component>
</div>

在这里插入图片描述

如果我们想要是自定义的组件标签中的内容被识别,那么就要使用到< slot>,使用的方法也是很简单,我们只需在我们的模板中的任意的位置插入< slot>< /slot>,,那么组件标签中的内容就会自动的绑定到< slot>< /slot>,。值得注意的是我们可以使用多个< slot>

    Vue.component("my-component",{
        template:`
             <ul>
                 <li>寒江のjava世界</li>
                 <li>
                 	<!--定义插槽的位置-->
                    <slot></slot>
                 </li>
                 <li>寒江のpython世界</li>
             </ul>
            `
    })
    var vm = new Vue({
        el:"#app"
    })
<div id="app">
	<!--“寒江のC++世界”将被绑定到定义的slot中去-->
    <my-component>寒江のC++世界</my-component>
</div>

在这里插入图片描述


2.内容分发slot

为了让组件可以组合,需要一种方式来混合父组件的内容与子组件自己的模板。这个过程被称为 内容分发 (或 “transclusion” )。

我们可以在一个 < template> 元素上使用 “v-slot:插槽名” 指令,用来指定特定组件插入指定的插槽(slot)。

<div id="app">
    <my-component>
        <template v-slot:cli>
            寒江のC++世界
        </template>
    </my-component>
</div>

在这里插入图片描述


当然< template v-slot>的最常使用的方式还是结合其他组件一起使用。

    Vue.component("my-slot",{
        template: `
            <div>
                <slot name="header">标题(默认)</slot>
                <ul>
                    <slot name="list">内容...</slot>
                </ul>
            </div>
            `
    })

    Vue.component("slot-title",{
        props:['title'],
        template: `
            <h3>{{title}}</h3>
        `
    })

    Vue.component("slot-list",{
        props: ['list'],
        template:`
            <li>{{list}}</li>
        `
    })

    var vm = new Vue({
        el:"#app",
        data:{
            head:"寒江のvue世界",
            lists:["什么是vue", "vue的使用", "vue的优点"]
        }
    })

:title:是v-bind:title的简写形式。

title:是"slot-title"组件中的自定义属性

list:是"slot-list"组件中的自定义属性

    <div id="app">
        <my-slot>
            <!--通过templa进行填充名为header的slot-->
            <template v-slot:header>
                <slot-title :title="head"></slot-title>
            </template>
            
			<!--通过templa进行填充名为list的slot-->
            <template v-slot:list>
            	<!--将lists中遍历到的item绑定到“slot-lits”中的list属性上-->
                <slot-list v-for="item in lists" :list="item"></slot-list>
            </template>
        </my-slot>
    </div>

在这里插入图片描述


在插槽中还有一种被废弃掉的slot的使用,我觉得也是有必要讲一下的。

在一个组件中使用slot=""可以将将该组件插入到其父组件的指定的插槽(slot)中去。

< slot-title slot=“header”>:将slot-title组件插入到name为header的插槽中。

< slot-list slot=“list”>:将slot-list 组件插入到name为list的插槽中。

    <div id="app">
        <my-slot>
             <!--通过其他组件进行填充slot-->
             <slot-title slot="header" :title="head"></slot-title>
             
             <!--将lists中遍历到的item绑定到“slot-lits”中的list属性上-->
             <slot-list slot="list" v-for="item in lists" :list="item"></slot-list>
        </my-slot>
    </div>

在这里插入图片描述


注意:

父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。

v-slot 只能添加在 <template> 上 (只有一种例外情况:独占默认插槽的缩写语法),这一点和已经废弃的 slot attribute 不同。



三、自定义事件以及$emit的使用

在介绍自定义事件之前,我们先来介绍一下组件中自定义方法以及方法的绑定

methods:和vue实例中的methods的性质是一样的。

@click=“remove”:等价于v-on:click=“remove”。值得注意的是,组件中只能调用组价中methods中的方法,是无法调用到vue实例中的methods中的方法的。

    Vue.component("slot-list",{
        props: ['list'],
        template:`
            <li>{{list}} <button @click="remove">删除</button></li>
        `,
        methods:{
            remove:function () {
                alert("good")
            }
        }
    })

在这里插入图片描述


现在,我们有这么一个需求(A):当我们点击删除按钮时,对应的前面的文本就被删除掉。

很明显,这个是不好实现的,因为文本是vue实例中data的数据,实例中数据的删除需要通过实例中的方法,但是删除按钮是在组件(component)中定义的,无法调到vue实例中的方法。

为了解决组件调用不到vue实例中方法的问题,我们引入自定义事件和$emit.。


我们可以通过 @自定义事件名=“动作/方法”来实现自定义事件。在组件中我们可以通过$emit(“自定义事件名”, 参数)来调用自定义事件。

<my-component @my-remove="removeItem(index)"></my-component>
this.$emit("my-remove",index)

在这里插入图片描述
至此,我们就实现了component中调用vue实例中的函数进而操作vue实例中的数据。


在实现 需求(A) 之前,我们还要解决一个问题:在js中,怎么能够做到灵活的操作数组中的元素。答案很简单,使用 splice() 方法。

splice() 方法向/从数组中添加/删除项目,然后返回被删除的项目。该方法会改变原始数组。

语法:

arrayObject.splice(index, howmany, item1,…,itemX)
参数描述
index必需。整数,规定添加/删除项目的位置,使用负数可从数组结尾处规定位置。
howmany必需。要删除的项目数量。如果设置为 0,则不会删除项目。
item1, …, itemX可选。向数组添加的新项目。

说明
splice() 方法可删除从 index 处开始的零个或多个元素,并且用参数列表中声明的一个或多个值来替换那些被删除的元素。

如果从 arrayObject 中删除了元素,则返回的是含有被删除的元素的数组。


至此,我们具备了实现 需求(A) 的所有条件,下面我们就来实现一下。

vue实例

function (index):index是需要调用者给传递的

    var vm = new Vue({
        el:"#app",
        data:{
            head:"寒江のvue世界",
            lists:["什么是vue", "vue的使用", "vue的优点"]
        },
        methods: {
            removeItem:function (index) {
                let info = this.lists.splice(index,1)
                 console.log(info+" 被删除了...")
            }
        }
    })

父组件

    Vue.component("my-slot",{
        template: `
            <div>
                <slot name="header">标题(默认)</slot>
                <ul>
                    <slot name="list">内容...</slot>
                </ul>
            </div>
            `
    })

子组件

    Vue.component("slot-title",{
        props:['title'],
        template: `
            <h3>{{title}}</h3>
        `
    })

@click=“remove”:调用component中的remove方法

    Vue.component("slot-list",{
        props: ['list',"index"],
        template:`
            <li>{{list}} <button @click="remove">删除</button></li>
        `,
        methods:{
            remove:function (index) {
                this.$emit("my-remove",index)
            }
        }
    })

视图层

v-for="(item,index) in lists":遍历lists中的元素以及元素对应的索引。

:list=“item”:绑定到slot-list中的list属性。:是v-bind:的缩写

:index=“index”:绑定到slot-list中的index属性。:是v-bind:的缩写。

@my-remove=“removeItem(index)”:自定义事件my-remove,该事件调用vue实例中的removeItem(index) 方法,index(item,index) in lists中的index。@是v-on:的缩写。

<div id="app">
    <my-slot>
        <!--通过templa进行填充slot-->
        <template v-slot:header>
            <slot-title :title="head"></slot-title>
        </template>

        <template v-slot:list>
            <slot-list v-for="(item,index) in lists"
                       :list="item"
                       :index="index"
                       @my-remove="removeItem(index)"

            ></slot-list>
        </template>
    </my-slot>
</div>

在这里插入图片描述
在这里插入图片描述


至此,我的介绍就结束了,但vue永远在你进步的路上等你…
请添加图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值