Vue入门——Vue组件&插槽slot&自定义事件(详细代码讲解示例)


一、Vue组件

1. 什么是组件

组件系统是 Vue 的另一个重要概念,因为它是一种抽象,允许我们使用小型、独立和通常可复用的组件构建大型应用。

在 Vue 里,一个组件本质上是一个拥有预定义选项的一个 Vue 实例,就是一组可重复使用的模板,与JSTL的自定义标签、Thymeleaf的th:fragment等框架有异曲同工之妙;

几乎任意类型的应用界面都可以抽象为一个组件树
img
例如:CSDN博客有页头、侧边栏、内容区等组件,每个组件又包含了其它的像导航链接、博文分类、博文数量等其他的组件


2. 定义一个组件

格式:第一个参数为组件名,第二个参数为组件对象,对象包含一些属性,如propstemplate

Vue.component("组件名", {
	props: 可接收的参数
	template: 模板
})

代码示例:定义一个名为zsr组件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Vue组件</title>
</head>
<body>

<div id="component">
    <zsr/>
</div>

<!--导入Vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.12"></script>
<script>
    //定义一个组件zsr
    Vue.component("zsr", {
        template: '<li>hello</li>'
    })
    //创建Vue对象
    var vue = new Vue({
        el: "#component"
    })
</script>

</body>
</html>

效果演示
image-20210121215108321


3. 组件传参

像上面那样用组件没有任何意义,所以我们是需要传递参数到组件的,此时就需要使用props属性了

注意:默认规则下props属性里的值不能为大写

代码示例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Vue组件</title>
</head>
<body>

<div id="component">
    <zsr v-for="item in items" v-bind:x="item"></zsr>
</div>

<!--导入Vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.12"></script>
<script>
    //定义一个组件
    Vue.component("zsr", {
        props: ['x'],
        template: '<li>{{x}}</li>'
    })
    //创建Vue对象
    var vue = new Vue({
        el: "#component",
        data: {
            items: ["Java", "Python", "C++"]
        }
    })
</script>

</body>
</html>

说明

  • v-for="item in items":遍历Vue的实例中定义名为items的数组,并创建同等数量的组件
  • v-bind:x="item":将遍历的item项绑定到组件对象属性props定义的名为x的属性上;

效果演示
image-20210121215118628



二、内容分发:插槽slot

Vue.js中,我们使用<slot>元素作为承载分发内容的出口,作者称之为 插槽 ,可以用在组合组件的场景中

代码测试:比如准备一个待做清单组件todo,该组件由标题组件todo-title和列表组件todo-list组成,这三个组件相互独立,我们可以用插槽将他们组合起来

第一步:定义待做清单组件

  • 这里留两个插槽slot,并指定名称分别为todo-titletodo-list
//待做清单组件
Vue.component("todo", {
    template: '<div>\
                    <slot name="todo-title"></slot>\
                    <ul>\
                         <slot name="todo-list"></slot>\
                    </ul>\
               </div>'
});

第二步:定义标题组件todo-title

  • 利用props属性定义接收的参数为title
//标题组件
Vue.component("todo-title", {
    props: ['title'],
    template: '<div>{{title}}</div>'
});

第三步:定义列表组件todo-list

  • 利用props属性定义接收的参数为listindex
//列表组件
Vue.component("todo-list", {
    props: ['list','index'],
    template: '<li>{{index}--}{{list}}</li>'
});

第四步:实例化Vue并初始化数据

  • 初始化title数据和todoLists数据
//定义一个vue对象
var vue = new Vue({
    el: "#slot",
    data: {
        title: "待做清单",
        todoLists: ['Java', 'C++', 'Python']
    }
});

第五步:通过插槽插入组件并绑定初始值

  • todo组件内插入todo-titletodo-list组件
  • 并对组件设置插槽名,与todo组件中的插槽名对应,实现对应位置插入
  • 绑定元素值:title绑定到vue对象中data中的title值,list绑定到vue对象中data中的todoLists遍历出来的每个值todoList
<div id="slot">
    <todo>
        <todo-title slot="todo-title" v-bind:title="title"></todo-title>
        <todo-list slot="todo-list" v-for="(todoList,index) in todoLists" v-bind:list="todoList" v-bind:index="index"></todo-list>
    </todo>
</div>

完整代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>slot</title>
</head>
<body>

<div id="slot">
    <todo>
        <todo-title slot="todo-title" v-bind:title="title"></todo-title>
        <todo-list slot="todo-list" v-for="(todoList,index) in todoLists" v-bind:list="todoList"
                   v-bind:index="index"></todo-list>
    </todo>
</div>

<!--导入Vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.12"></script>
<script>
    //待做清单组件
    Vue.component("todo", {
        template: '<div>\
                        <slot name="todo-title"></slot>\
                        <ul>\
                             <slot name="todo-list"></slot>\
                        </ul>\
                   </div>'
    });

    //标题组件
    Vue.component("todo-title", {
        props: ['title'],
        template: '<div>{{title}}</div>'
    });

    //列表组件
    Vue.component("todo-list", {
        props: ['list', "index"],
        template: '<li>{{index}}--{{list}}</li>'
    });

    //定义一个vue对象
    var vue = new Vue({
        el: "#slot",
        data: {
            title: "待做清单",
            todoLists: ['Java', 'C++', 'Python']
        }
    });
</script>
</body>
</html>

效果演示
image-20210120211316250



三、自定义事件

继上述示例,如果我们在每行列表后加一个删除按钮

//列表组件
Vue.component("todo-list", {
    props: ['list'],
    template: '<li>{{index}}--{{list}}<button v-on:click="remove">删除</button></li>'
});

image-20210120211332090
如果想要实现点击删除按钮删除对应的行,该怎么实现呢?

我们首先可以在vue示例的定义中加入一个删除方法

//定义一个vue对象
var vue = new Vue({
    el: "#slot",
    data: {
        title: "待做清单",
        todoLists: ['Java', 'C++', 'Python']
    },
    methods: {
        deleteList: function (index) {
            alert("删除了第" + index + "行")
            this.todoLists.splice(index, 1);//删除index行
        }
    }
});

这是我们打开浏览器在控制台调用deleteList方法即可删除指定行

image-20210120213025863
image-20210120213033772
image-20210120213041305

这样在控制台实现了删除行,那么怎么实现点击按钮删除行呢?

我们可以自定义事件remove绑定到deleteList()方法实现删除

<div id="slot">
    <todo>
        <todo-title slot="todo-title" v-bind:title="title"></todo-title>
        <todo-list slot="todo-list" v-for="(todoList,index) in todoLists" v-bind:list="todoList" v-bind:index="index"
                   v-on:remove="deleteList(index)"></todo-list>
    </todo>
</div>

然后在todo-list组件中添加一个删除方法remove()绑定上述remove事件使其生效

//列表组件
Vue.component("todo-list", {
    props: ['list', "index"],
    template: '<li>{{index}}--{{list}}<button v-on:click="remove">删除</button></li>',
    methods: {
        remove: function () {
            this.$emit('remove')
        }
    }
});

再测试,点击对应行按钮即可实现删除

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页