Vue学习之组件学习
第二章
组件开发
一、模板分类:使用组件时:为了减少template中html模板的复杂度,使用分离模板的方式:
1、 第一种:把模板写到template标签里面,再加入id属性,组件template:‘#id的名称’ 2、 第二种:创建scriot标签,<script type="text/x-handlebars-template" id="cpn">把模板放到这个标签中再加入id属性,组件template:‘#id的名称;
二、组件不能使用实例中的数据,但可以使用组件本身中的数据
//组件模板
<template id="cpn"> <div> <h2>篮球,跑步,音乐</h2> <p>山东省淄博市临淄区黄橙子</p> <p>{{times}}</p> </div> </template>
//语法糖(全局组件)注册和创建模板合并一起
Vue.component('con', { template: '#cpn', data() { return { times:'2019-10-29' } } });
三、父子组件之间的通讯(相互传递数据)
1、父传子:首先在子组件的标签上把父组件中data的值以<cc v-band:contrt="mmuy"></cc>形式传给子组件,子组件在props:['contrt']接收数据,contrt定义的对象名称,不要看成字符串,接收后可以在子组件的模板应用了!!!
(1)子组件接收数据时:第一种:props:['contrt'];
第二种:props:{ contrt:string} props以对象的形式接收数据
2、 props需要数据格式: (1)、props:{ '参数名':数据类型名称}或者props:{ '参数名':{ type:数据类型名称 } }
(2)、如果支持多个数据类型,使用数组:props:{ '参数名':{ type:[数据类型名称1,数据类型名称2] } }
(3)、数据必填时:props:{ '参数名':{ type:数据类型名称, required:true//设置当前参数为必传值 } }
(4)、默认值:props:{ '参数名':{ type:数据类型名称, default:function(){ return { msg:'默认展示的内容' } } } }
(5)、自定义验证规则:props:{ '参数名':{ validator:function(形参){ 对形参的验证规则 return 验证结果或者布尔值 } } }
3、props数据类型:
(1)、String 字符串
(2)、Number 数字
(3)、Boolean 布尔
(4)、Array 数组
(5)、Object 对象
(6)、Date 日期
(7)、Function 函数
(8)、Symbol 独一无二的值(es6)
父传子的代码实例:
<div id="app"> {{message}} <con></con> <cuu></cuu> <cc :contrt="mmuy"></cc> </div> <template id="cpn">//子组件中的模板 <div> <ul> <li v-for="i in contrt">{{i}}</li> </ul> </div> </template> <script> const cc = {//子组件 template: '#cpn', props:['contrt'] } const app = new Vue({//根组件 el:'#app', data:{ message: '你好吗,hello', mmuy:["海王","宋代足球"] }, components: {//局部组件 cc } }) </script>
当props中接收数据的名称是多个单词组成时,使用驼峰命名法,这里的驼峰命名法是在首字母还是小写,前面加横杠,使用驼峰命名法时只有父组件给子组件赋值时使用,其他地方按照原来的不变
1、子传父:
(1)、子组件模板按钮或者列表中监听自定义的点击事件@click="btnclick(items.id)",items.id是传给父组件的数据
(2)、子组件中定义methods: {btnclick(item) {this.$emit('item-click',item)}},btnclick是自定义的点击事件,this.$emit('item-click',item)传给父组件的方法,'item-click传给父组件的自定义的点击事件名称
(3)、在父模板的自定义标签中监听子集传过来的点击事件<c :mmm="mmuy" @item-click="cclick"></c>,把item参数传给父组件中cclick自定义点击事件
(4)、methods: {cclick(item) {console.log(item);}}
子传父代码实例:
<!--父组件模板--> <div id="app"> <c :mmm="mmuy" @item-click="cclick"></c>//用子组件传出的自定义事件的名称绑定根组件的自定义名称点击事件把传入的id打印 </div> <!--子组件模板---> <template id="muban"> <div> <button v-for="items in mmm" @click="btnclick(items.id)">{{items.name}}</button> </div> </template> <script> const c = { template: '#muban', props: {//接收根组件传来的数据 mmm: { type: Array, default: function () { return { msg: '数据为空,没传过来' } } } }, methods: { btnclick(item) {//子组件的点击事件 this.$emit('item-click',item)//自定义item-click事件的名称传出给子组件 } } } //跟组件 const app = new Vue({ el: "#app", data: { mmuy: [{ id: 1, name: '家用家电' }, { id: 2, name: '热门推荐' }, { id: 3, name: '手机数码' }], }, components: { c }, methods: { cclick(item) {//父组件的点击事件 console.log(item); } } }) </script>
1、 父子组件之间的相互传递(父传子,子组件props:接收,子传父,子组件监听事件中this.$emit自定义事件,父模板自定义标签中绑定自定义事件)
(1)、首先父组件传递给子组件数据后,子组件的数据要改变的时候props:{znum1: Number,znum2: Number}, data(){return {datanum1: this.znum1,datanum2: this.znum2}}首先把props中接收父组件的数据赋值给子组件的data中
(2)、其次<input :value="datanum1" @input="metnum1" />在子组件模板中要改变数据的标签上把data中的数据绑定上,其次监听这个标签!!!
(3)、methods: {metnum1(event) {this.datanum1 = event.target.value;this.$emit('num1chuan', this.datanum1)},event是接收input的value值,把改变后input的value赋给data上,在把data改变后的值传回父组件中!!
(4)、或者子组件中input标签用v-model绑定实现双向绑定,v-model:“datanum1”,子组件中watch代替methods ,时间的名称和data中属性的名称一致,watch: { datanum1 (event) {this.datanum1 = event.target.value;this.$emit('num1chuan', this.datanum1)},
watch是监听属性的改变,比如data中有一个name,监听是否改变,就可以用watch{name(newValue,oldValue){ }} 注意:watch监听那个属性时,函数名称就是属性名称
父子组件之间的相互传递的代码案例:<!---根组件模板-->
<div id="app"> <c :znum1="num1" @num1chuan="num1chu"></c><!----> </div> <!--子组件模板--> <template id="zi"> <div> <p>props:{{znum1}}</p> <p>data:{{datanum1}}</p> <input :value="datanum1" @input="metnum1" /><!cilck是点击事件,input是监听事件,input主要适用于input标签---->
或者
<input v-model="datanum1" @input="metnum1"/> </div> </template> <script> //子组件 const c = { template: '#zi', props: { znum1: Number, }, data(){ return { datanum1: this.znum1, } }, methods: {//如果input中是value的绑定话 metnum1(event) { this.datanum1 = event.target.value; this.$emit('num1chuan', this.datanum1); },
//如果inut是v-model绑定的话,或者metnum1也可以改为watch
metnum1() {
this.$emit('num1chuan', this.datanum1);
},
} } //根组件 const app = new Vue({ el: "#app", data: { num1:1, }, components: { c }, methods: { num1chu(chu) { this.num1 = parseInt(chu);//chu接收后是string类型得转化为int类型,用parseint转换!!!! } } }) </script>
四、父子组件的相互访问(父组件使用子组件中的对象):
1、父组件访问子组件:
(1)、$refs 在父组件模板自定义的标签中加入ref=“aaa”属性,aaa名称随意命名
(2)、$children
代码实例:
<div id=app> <cpn ref="aa"></cpn> <button @click="bintclick">按钮</button> </div> <template id="cpn"> <div>我是子组件</div> </template> <script> const app = new Vue({ el: '#app', data() { return { property: '你好呀', }; }, methods: { bintclick() { console.log(this.$children); console.log(this.$refs); console.log(this.$refs.aa.name); } } </script>
2、子组件访问父组件:
(1)、当父组件是根组件时this.$root访问
(2)、当父组件不是根组件时this.$parent访问
代码实例:
//根组件 <div id=app> <cpn></cpn> </div> //子组件 <template id="cpn"> <ccppnn></ccppnn> </template> //子组件中的子组件 <template id="ccppnn"> <div> <div>我是子组件</div> <button @click="btnclick">按钮</button> </div> </template> const app = new Vue({ el: '#app', data:{ property: '你好呀', }, components:{ cpn:{ template: '#cpn', data() { return { name:'我是第一个子组件' } }, components: { ccppnn: { template: '#ccppnn', methods: { btnclick() { console.log(this.$parent); console.log(this.$parent.name); console.log(this.$root); } } } } } } });
五、solt插槽的使用:(solt插槽解释说明:当使用组件化后,多个页面通同时使用同一个组件时,结构一样,内容不同时,在模板中使用插槽,如果很多内容相同,就有个别内容不同同时在solt标签中加入默认的内容,当自定义标签中有内容传到solt时,把默认内容代替)
代码示例:
<div id="app"> <c></c> <c><button>删除</button></c> <c><button>提交</button></c> <c><button>添加</button></c> </div> <template id="cpt"> <div> <div>傻白甜</div> <slot><button>移除</button></slot> </div> </template> <script> const c = { template: '#cpt', } const app = new Vue({ el: '#app', data: { name:'我是根组件' }, components: { c } }) </script>
六、具名solt插槽的使用:(具名solt插槽解释说明:当使用组件化后,子组建模板中有多个插槽,自定义的标签中只想改其中的一个插槽,在子组建模板的插槽中定义name=“·······san”名称,在自定义标签中的内容里添加solt=“san”寻找相应的插槽)
代码实例:
<div id="app"> <c><span slot="san">青岛人</span></c> </div> <template id="cpt"> <div> <slot name="san"><span>山东</span></slot> <slot><button>移除</button></slot> </div> </template> <script> const c = { template: '#cpt', } const app = new Vue({ el: '#app', data: { name:'我是根组件' }, components: { c } }) </script>
七、作用域solt插槽的使用:(作用域solt插槽解释说明:当使用多次子组件,但是每个组件显示数据的方式不同时,需要使用作用域插槽,获取子组件中的数据来显示不同的显示方式,首先子模板中插槽标签slot中把数据赋值给aa,其次在父模板自定义标签中写入template标签,slot-scope:“slot”作为template标签标签的属性,把slot标签中绑定aa的值赋给自身,循环的话也可以实现,但是最后会有一个---,使用join就不会出现这种结果!!)
代码实例:
<div id="app"> <c> <template slot-scope="slot"> <span>{{slot.aa.join('---')}}</span> </template> </c> </div> <template id="cpt"> <div> <slot :aa="shu"></slot> </div> </template> <script src="js/vue.js"></script> <script> const c = { template: '#cpt', data() { return { shu: ['山东', '安徽', '云南', '浙江'] } } } const app = new Vue({ el: '#app', data: { name:'我是根组件' }, components: { c } }) </script>