props理解
props是使用这个组件时外部传送过来的,而需要用到它的组件再通过props接受到这个值, 它的方式有以下几种: 1.props可以静态传值:
//父组件<child message="hello"></child> //子组件props:['message'] //输出hello
2.动态传值:使用v-bind进行动态绑定
<my-title v-bind:title="post.title"></my-title>
3.传值类型:
props里面可以传的类型包括: {String, Number, Boolean,Array,Object, Function, Promise }
同时它的类型检查方式:props: { propOne: Number},
必填类型:propTwo: { type: Number, required: true },
带有默认值的:propThr: { type: Number, default: 100 }
propsThr:{type:Object,default:()=> ({}) },
event理解
1.$emit用于子组件向父组件抛出事件,事件绑定v-on可以简写做@,用于父组件监听抛出的事件;v-on还可以监听DOM上的事件
2.自定义事件中:<div @click="$emit('event',val)">
组件的事件名就是$emit的第一个参数
三种通信方式
1.父子通信:父控制子,通过子组件的props,抛出子组件自定义标签属性,来接收父组件的操作状态,
父组件向子组件发送了一个props是一个字符串,子组件拿到了这个字符串之后通过click事件改变了字符串的值,然后通关$emit xx将这个值抛出。父组件通过@xx 监听到事件
child
<template>
</template>
同时还有子父通信:子控制父,子组件绑定自定义事件,来处理父组件的方法函数,通过.$emit('event',val)来触发属于自己的自定义事件
2.兄弟通信:拥有一个相同的父组件,结合父子props 传参和自定义事件
A页面 通过this.$emit抛出事件,index页面监听。然后通过this.$refs操作B页面。
子(A页面)->父,父->子(B页面)
//index页面
<template>
<div>
<brotherA @brotherAclick="click"></brotherA>
<brotherB ref="brotherBref"></brotherB>
</div>
</template>
methods: {
click(){
this.$refs.brotherBref.funb();
}
}
}
//A页面
<div>
<button @click="funa">点击</button>
</div>
methods: {
funa(){
this.$emit('brotherAclick')
}
}
}
//B页面
<div> </div>
methods: {
funb(){
console.log('brotherB方法被调用');
}
}
3.堂兄弟通信:通过向上找最近的两个组件共同的父组件作为委托组件进行通信。
为什么组件的data必须是一个函数
如果data是个对象当多个实例同时引用这个对象,那么修改其中一个属性的时候,另外一个实例也会跟着改变;而在js中只有函数构成作用域,对象不构成作用域,data是一个函数时,每个组件实例都有自己的作用域,每个实例相互独立,不会相互影响。
provide 有哪些优点和缺点
首先provide和inject一起用的,用于父组件向子孙组件传递数据,那么当孙组件想访问祖先组件的时候就必须一层一层往上访问比较麻烦和困难,这个时候provide的优点就是可以轻松实现跨级访问父组件的数据。
那么它的缺点就是因为任意层级都能访问到,所以有时候不知道那一层级声明了provide又或是哪些层级使用了inject,维护起来很麻烦。
插槽传值
匿名插槽:
// 父组件
<son> hello </son>
// 子组件
<div>
<slot></slot>
</div>
\
具名插槽:
<h1>父组件</h1>
<index2>
<div slot="1">我是一</div>
<div slot="2">我是二</div>
</index2>
//子组件 index2
<div>
<p>子组件</p>
<slot name="1"></slot>
<slot name="2"></slot>
</div>
作用域插槽:
<h1>父组件</h1>
<index2>
<div slot-scope="rec">
<p> <span>姓名:</span> {{rec.name}} </p>
<p> <span>年龄:</span> {{rec.age}} </p>
</div>
</index2>
<h1>子组件</h1>
<slot b="xiaowang" age="18"></slot>
//显示的是子组件里的数据
双向绑定组件
1.input-text输入框的双向绑定
text文本框默认使用prop:value和event:input来双向绑定,如果需要在一个组件中绑定多个输入框需要使用:update.prop 和 :prop.sync 来绑定其它输入框
子组件代码
<template>
<div class="myslot">
<input v-model="syncValue">{{syncValue}}
<input v-model="syncCount">{{syncCount}}
</div>
</template>
<script>
export default {
name:'myslot',
props:['value','count'],
computed:{
syncValue:{
get(){
return this.value
},
set(val){
this.$emit('input',val)
}
},
syncCount:{
get(){
return this.count
},
set(val){
this.$emit('update:count',val)
}
}
}
}
</script>
复制代码
父组件代码
<template>
<div id="app">
<MyInput v-model="val" :count.sync="count"></MyInput>
</div>
</template>
<script>
import MyInput from "./components/my-input.vue"
export default {
name: 'App',
components: {
MyInput
},
data(){
return{
val:'',
count:''
}
}
}
</script>
复制代码
2.input-radio单选框的双向绑定
APP组件代码
<template>
<div id="app">
<MyRadio v-model="radio" :data="data"></MyRadio>
</div>
</template>
<script>
import MyRadio from "./components/my-radio.vue"
export default {
name: 'App',
components: {
MyRadio,
},
data(){
return{
radio:'',
data:[
{id:'1',value:'apple',text:'苹果'},
{id:'2',value:'banana',text:'香蕉'},
{id:'3',value:'orange',text:'橘子'},
],
}
},
}
</script>
复制代码
my-radio组件代码
<template>
<div class="myradio">
<RadioItem :key="index" :value="item.value" :label="item.text" v-for="(item,index) in data"></RadioItem>
</div>
</template>
<script>
import RadioItem from "./radio-item.vue"
export default {
name:'Myradio',
props:['data','value'],
components:{
RadioItem,
},
provide(){
return{
$myradio: this
}
}
}
</script>
复制代码
radio-item组件代码
<template>
<div class="radio-item">
<input type="radio" :id="label" :value="value" v-model="syncRadio">
<label :for="label">
{{label}}
</label>
</div>
</template>
<script>
export default {
props:['label','value'],
inject:['$myradio'],
computed:{
syncRadio:{
get(){
return this.$myradio.value
},
set(val){
return this.$myradio.$emit('input', val)
}
}
}
}
</script>