VUE-组件以及插槽父子间传递(更新版)
VUE-组件的定义使用以及插槽的使用方式,以及如何进行父传子,子传父的操作、ref的使用
目录
1.在组件中,data需要被定义为一个方法,其目的是为了实现数据隔离
3.通过component标签加is属性的方式来确定显示的是哪个组件
4.transition实现动画,加上mode属性来控制动画进出的先后顺序,不加为同时进行
1. 默认插槽:默认插槽就是指没有名字的插槽,子组件未定义的名字的插槽,父级将会把 未指定插槽的填充的内容填充到默认插槽中。
2.给slot标签加上name属性即为具名插槽,利用template标签配合v-slot:name来把内容添加到对应的插槽里
在Vue.component(){}中,加入与template、data同级的props用来接受传值
一、1.vue组件
1.定义:什么是组件: 组件的出现,就是为了拆分Vue实例的代码量的,能够让我们以不同的组件,来划分不同的功能模块,将来我们需要什么样的功能,就可以去调用对应的组件即可。
组件化和模块化的不同:
模块化:是从代码逻辑的角度进行划分的;方便代码分层开发,保证每个功能模块的职能单一
组件化:是从UI界面的角度进行划分的;前端的组件化,方便UI组件的重用
二、全局组件定义的四种方式
1.使用 Vue.extend 配合Vue.component 方法:
var login = Vue.extend({
template: '<h1>登录</h1>'
});
Vue.component('login', login);
2.直接使用 Vue.component 方法
Vue.component('register', {
template: '<h1>注册</h1>'
});
3.将模板字符串,定义到script标签中:
<script id="tmpl" type="x-template">
<div><a href="#">登录</a> | <a href="#">注册</a></div>
</script>
同时,需要使用 Vue.component 来定义组件:
Vue.component('account', {
template: '#tmpl'
});
但是!我们一般不采用前三种方式,故重点关注和记忆第四种
4.将模板字符串,定义到template标签中:
<template id="tmpl"> <div> <a href="#">登录</a> | <a href="#">注册</a> </div> </template >
注意!!!!!!!template标签中只能有一个根标签
同时,需要使用 Vue.component 来定义组件:
Vue.component('account', { template: '#tmpl' });
注意:不能使用内置或保留的HTML元素作为组件id名称
(1)此时为全局定义,在在所有的vue实例对应的控制区域都可以使用
(2)私有定义:只有在对应的vue实例的控制区域中才能拿到
书写时与vue实力的data,methods等同级书写即可
//私有定义只有在对应的vue实例的控制区域中才能拿到 components:{ xuan:{ template:'#xuan' } },
三、组件中展示数据和响应事件
1.在组件中,data需要被定义为一个方法,其目的是为了实现数据隔离
例如:
<!-- 使用template标签书写组件内容,通过id来实现内容的传递 --> <template id="login"> <!-- 注意template标签只能有一个根标签 --> <div> 登录 <button @click="addn(4)">加4</button> <br> 组件中data方法中的数据在组件中直接通过插值表达式获取: <br> msg:{{msg}} <br> num:{{num}} </div> </template>
Vue.component('account', { template: '#tmpl', data() { return { msg: '大家好!' } }, methods:{ login(){ alert('点击了登录按钮'); } } });
2.在组件中同样拥有生命周期
//在组件中同样拥有生命周期 beforeCreate(){ console.log(1); }, created(){ console.log(2); }, beforeDestroy(){ console.log('beforeDestroy'); }, destroyed(){ console.log('destroyed'); },
3.通过component标签加is属性的方式来确定显示的是哪个组件
<!-- 通过component标签加is属性的方式来确定显示的是哪个组件 --> <component is="mine"></component> <component :is="flag ? 'mine' : 'login'"></component>
4.transition实现动画,加上mode属性来控制动画进出的先后顺序,不加为同时进行
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title></title> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <!-- <script src="https://unpkg.com/vue-router@3.0.0/dist/vue-router.js"></script> --> <script src="https://cdn.staticfile.org/axios/0.18.0/axios.min.js"></script> <style> .v-enter,.v-leave-to { transform: translateX(360px); } .v-enter-active,.v-leave-active { transition: all 1s; } .v-enter-to,.v-leave { transform: translateX(0px); } </style> </head> <body> <div id='app'> <button @click="flag = !flag">点击登录</button> <!-- transition实现动画,加上mode属性来控制动画进出的先后顺序,不加为同时进行 --> <transition mode="out-in"> <!-- 通过component标签加is属性的方式来确定显示的是哪个组件 --> <component :is="flag ? 'mine' : 'login'"></component> </transition> </div> <!-- 使用template标签书写组件内容,通过id来实现内容的传递 --> <template id="login"> <!-- 注意template标签只能有一个根标签 --> <div> 登录 <button @click="addn(4)">加4</button> <br> 组件中data方法中的数据在组件中直接通过插值表达式获取: <br> msg:{{msg}} <br> num:{{num}} </div> </template> <template id="mine"> <div>个人中心</div> </template> <script> Vue.component('mine',{ template:"#mine" }) // Vue.component('login',{ template:'#login', // 注意组件中的data属性必须定义为一个方法并返回一个对象,其目的是为了实现数据隔离 data(){ return { msg:'hello', num:6 } }, //在组件中同样拥有生命周期 beforeCreate(){ console.log(1); }, created(){ console.log(2); }, beforeDestroy(){ console.log('beforeDestroy'); }, destroyed(){ console.log('destroyed'); }, methods:{ addn(n) { this.num += n } } }) const vm = new Vue({ el: '#app', data: { flag:true }, methods: { }, beforeCreate(){ }, created(){ }, beforeMount(){ }, mounted(){ }, beforeUpdate(){ }, updated(){ }, }) </script> </body> </html>
四、插槽的使用(<slot></slot>)
1. 默认插槽:默认插槽就是指没有名字的插槽,子组件未定义的名字的插槽,父级将会把 未指定插槽的填充的内容填充到默认插槽中。
<div id='app'> <h2>免费课程</h2> <!-- 组件标签中书写的内容会被写在默认插槽的位置 --> <course :type="type" page-size="10">免费</course> <h2>精品课程</h2> <course type="boutique">精品</course> <h2>折扣课程</h2> <course type="discount">折扣</course> </div> <!-- 使用template标签书写组件内容,通过id来实现内容的传递 --> <template id="course"> <div> <!-- <slot></slot> 默认插槽:默认插槽就是指没有名字的插槽,子组件未定义的名字的插槽,父级将会把 未指定插槽的填充的内容填充到默认插槽中。 --> <h2><slot></slot>课程</h2> <ul> <li v-for="item in courselist"> <img :src="item.coverFileUrl" alt=""> <div>{{item.courseTitle}} </div> <div> {{item.learningNum}}</div> <div>免费 </div> </li> </ul> </div> </template>
2.给slot标签加上name属性即为具名插槽,利用template标签配合v-slot:name来把内容添加到对应的插槽里
<div id='app'> <!-- <h2>免费课程</h2> --> <!-- 组件标签中书写的内容会被写在默认插槽的位置 --> <course :type="type" page-size="10"> 默认插槽 <!-- 利用template标签配合v-slot:name来把内容添加到对应的插槽里 --> <template v-slot:header> 免费 </template> <template v-slot:footer> 底部 </template> </course> </div> <template id="course"> <div> <!-- <slot></slot> 默认插槽:默认插槽就是指没有名字的插槽,子组件未定义的名字的插槽,父级将会把 未指定插槽的填充的内容填充到默认插槽中。 --> <h1><slot></slot></h1> <!-- 给slot标签加上name属性即为具名插槽 --> <h2><slot name="header"></slot>课程</h2> <ul> <li v-for="item in courselist"> <img :src="item.coverFileUrl" alt=""> <div>{{item.courseTitle}} </div> <div> {{item.learningNum}}</div> <div>免费 </div> </li> </ul> <h2><slot name='footer'></slot></h2> </div> </template>
五.父传子
在Vue.component(){}中,加入与template、data同级的props用来接受传值
//接受传值 利用props props:{ // 自定义接受 //定义数据类型 type : String, size:Number, pageSize:{ //定义多种数据类型,用数组形式 type:[Number,String], //设置默认值,若为基本数据类型不存在深拷贝的问题则可以写成对象的形式 //(也可以写成函数形式),复杂数据类型写为函数形式,目的也是为了数据隔离, default(){ return 5 } } },
然后再vue实例(即父级)控制区内加入组件标签,给标签的属性加冒号(:)即可获取到父级的data中的数据
六.子传父
(一)子组件调用父组件的方法
1.在父组件中给引用的子组件注册一个事件(这个事件的名字是自定义的)
<div id='app'> <div class="container"> <!-- 1.在父组件中给引用的子组件注册一个事件(这个事件的名字是自定义的) --> <!-- 可以传入$event(在这里只能写$event来获取子组件的参数)也可以拿到子组件传递的数据 --> <son @comment="comment($event,'hello')"></son> <ul class="list-group"> <li v-for="(item,index) in list " :key="index" class="list-group-item">{{item.content}} <span class="badge">{{item.name}}</span> </li> </ul> </div> </div> --------------------js中 methods: { // 1.在父组件中给引用的子组件注册一个事件(这个事件的名字是自定义的) // 父组件这个方法没有自定参数,在父组件的方法直接加这个参数就可以拿到子组件给父组件传递的数据 comment(data){ console.log(data); this.list.push(data) sessionStorage.setItem('list',JSON.stringify(this.list)) } },
2.子组件可以触发这个事件$emit('事件名字')
(1)$emit方法第二个参数可以定义子组件给父组件传递的内容
Vue.component('son',{ template:"#son", data(){ return { name:'', content:'' } } , methods:{ issue(){ if(this.name != '' && this.content != '') { // 2.子组件可以触发这个事件$emit('事件名字') // 1.$emit方法第二个参数可以定义子组件给父组件传递的内容 this.$emit('comment',{ name:this.name,content:this.content }) this.name = '' this.content = '' } else { window.alert('请输入评论人及评论内容') } } } })
(二)在父组件中怎么拿到这内容
1.父组件这个方法没有自定参数,在父组件的方法直接加这个参数就可以拿到
const vm = new Vue({ el: '#app', data: { list:[] }, methods: { // 1.在父组件中给引用的子组件注册一个事件(这个事件的名字是自定义的) // 父组件这个方法没有自定参数,在父组件的方法直接加这个参数就可以拿到子组件给父组件传递的数据 comment(data){ //data就是子组件传来的数据 console.log(data); this.list.push(data) sessionStorage.setItem('list',JSON.stringify(this.list)) } }, })
2.父组件有自定义参数,可以传入$event也可以拿到子组件传递的数据。通过$event只能传递第一个参数
<div id='app'> <div class="container"> <!-- 可以传入$event(在这里只能写$event来获取子组件的参数)也可以拿到子组件传递的数据 --> <son @comment="comment($event,'hello')"></son> </div> </div>
data即为标签中的$event,也就是子组件传来的值,data为标签中调用方法时传的参
const vm = new Vue({ el: '#app', data: { list:[] }, methods: { //父组件有自定义参数,可以传入$event也可以拿到子组件传递的数据。通过$event只能传递第一个参数。 comment(data,data2){ //data即为标签中的$event,也就是子组件传来的值,data为标签中调用方法时传的参 console.log(data); console.log(data2); this.list.push(data) sessionStorage.setItem('list',JSON.stringify(this.list)) } }, })
七、ref的使用
(一)获取dom节点
1.给dom节点记上ref属性,可以理解为给dom节点起了个名字。
<!-- 给dom节点记上ref属性,可以理解为给dom节点起了个名字。 -->
<h1 ref="h11" id="h11">h1标签</h1>
2.加上ref之后,在$refs属性中多了这个元素的引用。
3.通过vue实例的$refs属性拿到这个dom元素。
const vm = new Vue({ el: '#app', data: { }, methods: { changeSon(){ this.$refs.myson.sonMsg = '被父组件的按钮改变' } }, mounted(){ console.log(document.getElementById('h11')); console.log(this.$refs); // 加上ref之后,在$refs属性中多了这个元素的引用。 // 通过vue实例的$refs属性拿到这个dom元素,可以对dom元素进行操作 this.$refs.h11.style.color = 'red' }, })
(二)获取组件
1.给组件记上ref属性,可以理解为给组件起了个名字。
<!-- 给组件记上ref属性,可以理解为给组件起了个名字。 -->
<son id="myson" ref="myson"></son>
2.加上ref之后,在$refs属性中多了这个组件的引用。
3.通过vue实例的$refs属性拿到这个组件的引用,之后可以通过这个引用调用子组件的方法,或者获取子组件的数据。
const vm = new Vue({ el: '#app', data: { }, methods: { changeSon(){ this.$refs.myson.sonMsg = '被父组件的按钮改变' } }, mounted(){ // 加上ref之后,在$refs属性中多了这个组件的引用 // 通过vue实例的$refs属性拿到这个组件的引用,之后可以通过这个引用调用子组件的方法,或者获取子组件的数据 // 获取子组件的数据 console.log(this.$refs.myson.sonMsg); //可以通过这个引用调用子组件的方法 console.log(this.$refs.myson.log1()); }, })
更多推荐
所有评论(0)