一. 组件使用v-model双数据绑定:
默认情况下,在组件上使用v-model
绑定的是modelValue属性
,数据改变触发的是 update:modelValue 事件
;
组件使用v-model的原理就是:父组件传值给子组件,并且父组件与传递的值双向绑定,子组件接收传递过来的值,并且通过监听表单控件的input事件触发自定义事件 update:modelValue,并传递当前值作为参数返回父组件;
子组件:
const input ={
props:['modelValue'],
template:`
<input type='text':value='modelValue'@input='$emit("update:modelValue",$event.target.value)'>
`
父组件使用子组件:
<my-input v-model='test'></my-input>
默认传递的属性名称是可以改变的:
<my-input v-model:age='test'></my-input>
那么对应的:
const input = {
props:['age'],
template:`
<input type='text' :value='age' @input='$emit("update:age",$event.target.value)'>
`
}
一个组件也可以使用多个数据绑定:
<user-name
V-model:first-name="firstName"
V-model:last-name="lastName
></user-name>
二. 处理 v-model 修饰符:
如果直接在组件上使用v-model内置的修饰符,修饰符不会生效;vue3.X版本提供了组件自定义修饰符功能。
添加到组件 v-model 的修饰符将通过 modelModifiers 属性提供给组件的prop;
<my-component v-model.capitalize="bar"></my-component>
props:{
modelValue:String.
modelModifiers:{
default:()=>({1})
}
},
传递到子组件的 modelModifiers 属性会在实例创建好时,生成一个包含验证规则为true的对象;
modelModifiers => {capitalize:true}
methods:{
emitValue(e){
let value =e.target.value
if (this.modelModifiers.capitalize){
value =value.charAt(0).toUpperCase()+value.slice(1)
}
this.$emit('update:modelValue",value)
}
},
template:`<input
type="text
:value="modelvalue"
@input="eitValue">
`
有了这些关键信息,就可以在组件中触发input事件时,根据修饰的true、false处理相关的业务逻辑
对于带参数的 v-model 绑定,生成的 prop 名称将为 arg + "Modifiers" 例: v-model:age.number = 'age'; props:[age,ageModifiers]
三. 插槽内容
Vue 实现了一套内容分发的 API,将 元素作为承载分发内容的出口。
当使用组件时,可能更希望的是在组件标签中写入内容,实现动态展示不同内容的功能;
例:
<my-button>提交</my-button>
<br>
<my-button>重置</my-button>
<br>
<my-button>按钮</my-button>
默认情况下,如果组件标签中没有包含一个 元素,则该组件起始标签和结束标签之间的任何内容都会被抛弃。
所以,可以通过在组件中添加标签实现分发内容的目的。
例:
vm.component('my-button',{
template:`
<button><slot></slot></button>
`
})
1.通过插槽,可以插入字符串内容
<my-button>
增加
<i class="fa fa-plus"></i>
</my-button>
2.通过插槽,可以插入任何模板代码
<my-main>
<my-button>
增加
</my-button>
</my-main>
3.插槽可以定义默认值
我们可能希望 内绝大多数情况下都渲染文本“Submit”。为了将“Submit”作为后备内容,我们可以将它放在 标签内;
vm.component('my-button',{
template:`
<button>
<slot>Subit</slot>
</button>
`
})
<my-button></my-button>
<br>
<my-button>Reset</my-button>
四. 具名插槽:
普通插槽只可以在一个插槽中分发内容,如果想实现分发不同的内容到不同的插槽,就必须使用具名插槽了。
1.给标签添加name属性,以声明当前插槽的名称;
例:
<div class="container">
<header>
<slot name="header"×/slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
2.在向具名插槽提供内容的时候,我们可以在一个 元素上使用 v-slot 指令,并以 v-slot 的参数的形式提供其名称:
例:
<base-layout>
<template v-slot:header>
<h1>Here might be a page title</h1>
</template>
<template v-slot:default>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
</template>
<template v-slot:footer>
<p>Here's some contact info</p>
</template>
</base-layout>
现在 <template> 元素中的所有内容都将会被传入相应的插槽。
注意:在使用具名插槽时,其分发内容的指令v-slot必须写在template标签上;
跟 v-on 和 v-bind 一样,v-slot 也有缩写,即把参数之前的所有内容 (v-slot:) 替换为字符 #;
五. 深层组件传值
prop把my-main的值传递到my-btn
通过上例可以发现,如果组件嵌套层数越多,传值将变得越困难,所以对于这种情况,我们可以使用 provide 和 inject 属性解决此问题。
父组件:
provide(){
return {
name:this.mainMsg
}
},
子组件:
inject:['name']
六.动态组件
有的时候,在不同组件之间进行动态切换是非常有用的,比如在一个多标签的界面里;有点类似tab切换,但不严格是tab切换,因为这个案例是组件之间的切换;
动态可以通过 Vue 的 元素加一个特殊的 is 来实现;
<component :is="currentTabComponent"></component>
//is属性指向的是组件的名称
如果在某一个组件中定义一个文本框,输入内容之后,如果发生切换行为,会发现文本框中的内容消失了,这是因为你每次切换组件的时候,Vue 都创建了一个新的组件实例。
每次都创建新的组件是非常有用的,比如每次切换都需要获取新的新闻内容,但是,有的时候是需要记录上次状态的,如果有这样的需求,可以通过完成
<keep-alive>
<component:is="currentTabComponent"></component>
</keep-alive>