父子组件之间的传值,父传子,使用props的格式
引用vue3官网
Props声明
export default {
props: ['foo'],
created(){
// props 会暴露到 `this` 上
console.log(this.foo)
}
}
除了使用字符串数组来声明prop外,还可以使用对象的形式
export default {
props: {
title: String,
likes: Number
}
}
传递prop的细节
Prop名字格式
如果一个prop的名字很长,使用camelCase形式,但是通常会将其写为kebab-case形式
//声明
export default {
props: {
greetingMessage: String
}
}
//使用
<span>{{ greetingMessage }}</span>
//父组件传值
<MyComponent greeting-message="hello" />
传值的方式,静态和动态prop
静态
<BlogPost title="My journey with Vue" />
动态,还有使用 v-bind
或缩写 :
来进行动态绑定的 props:
<!-- 根据一个变量的值动态传入 -->
<BlogPost :title="post.title" />
<!-- 根据一个更复杂表达式的值动态传入 -->
<BlogPost :title="post.title + ' by ' + post.author.name" />
传递不同的值类型
任何类型的值都可以作为props的值被传递
Number
<!-- 虽然 `42` 是个常量,我们还是需要使用 v-bind -->
<!-- 因为这是一个 JavaScript 表达式而不是一个字符串 -->
<BlogPost :likes="42" />
<!-- 根据一个变量的值动态传入 -->
<BlogPost :likes="post.likes" />
Boolean
<!-- 仅写上 prop 但不传值,会隐式转换为 `true` -->
<BlogPost is-published />
<!-- 虽然 `false` 是静态的值,我们还是需要使用 v-bind -->
<!-- 因为这是一个 JavaScript 表达式而不是一个字符串 -->
<BlogPost :is-published="false" />
<!-- 根据一个变量的值动态传入 -->
<BlogPost :is-published="post.isPublished" />
Array
<!-- 虽然这个数组是个常量,我们还是需要使用 v-bind -->
<!-- 因为这是一个 JavaScript 表达式而不是一个字符串 -->
<BlogPost :comment-ids="[234, 266, 273]" />
<!-- 根据一个变量的值动态传入 -->
<BlogPost :comment-ids="post.commentIds" />
Object
<!-- 虽然这个对象字面量是个常量,我们还是需要使用 v-bind -->
<!-- 因为这是一个 JavaScript 表达式而不是一个字符串 -->
<BlogPost
:author="{
name: 'Veronica',
company: 'Veridian Dynamics'
}"
/>
<!-- 根据一个变量的值动态传入 -->
<BlogPost :author="post.author" />
使用一个对象绑定多个prop
export default {
data() {
return {
post: {
id: 1,
title: 'My Journey with Vue'
}
}
}
}
//模板
<BlogPost v-bind="post" />
//等价于
<BlogPost :id="post.id" :title="post.title" />
单向数据流
所有的 props 都遵循着单向绑定原则,props 因父组件的更新而变化,自然地将新的状态向下流往子组件,而不会逆向传递。这避免了子组件意外修改父组件的状态的情况,不然应用的数据流将很容易变得混乱而难以理解。不能去改变父组件的值。
如果你想更改prop的需求,你可以使用以下两种情景。
prop 被用于传入初始值;而子组件想在之后将其作为一个局部数据属性。在这种情况下,最好是新定义一个局部数据属性,从 props 上获取初始值即可:
export default {
props: ['initialCounter'],
data() {
return {
// 计数器只是将 this.initialCounter 作为初始值
// 像下面这样做就使 prop 和后续更新无关了
counter: this.initialCounter
}
}
}
需要对传入的 prop 值做进一步的转换。在这种情况中,最好是基于该 prop 值定义一个计算属性:
export default {
props: ['size'],
computed: {
// 该 prop 变更时计算属性也会自动更新
normalizedSize() {
return this.size.trim().toLowerCase()
}
}
}
实际开发中
//drugDisqualificationVisible为Boolean,editform为对象,numberList为数组
<!--父组件-->
<machine-disqualification
:visable-dr="drugDisqualificationVisible"
:form="editform"
:number-list="numberList" />
<script>
//引用
import MachineDisqualification from './machineDisqualification.vue'
export default {
components:{MachineDisqualification}
}
</script>
<!--子组件-->
export default {
name: 'MachineDisqualification',
props: {
visableDr: {
type: Boolean,
default: false
},
form: {
type: Object,
default: function() {}
},
numberList: {
type: Array,
default: function() {}
},
}
}
组件事件
触发与监听事件
可以直接使用 $emit
方法触发自定义事件 (例如:在 v-on
的处理函数中):
<!-- MyComponent -->
<button @click="$emit('someEvent')">click me</button>
$emit()
方法在组件实例上也同样以 this.$emit()
的形式可用:
export default {
methods: {
submit() {
this.$emit('someEvent')
}
}
}
父组件可以通过 v-on
(缩写为 @
) 来监听事件:
<MyComponent @some-event="callback" />
事件参数
有时候我们会需要在触发事件时附带一个特定的值。举例来说,我们想要 <BlogPost>
组件来管理文本会缩放得多大。在这个场景下,我们可以给 $emit
提供一个额外的参数:
<button @click="$emit('increaseBy', 1)">
Increase by 1
</button>
然后我们在父组件中监听事件,我们可以先简单写一个内联的箭头函数作为监听器,此函数会接收到事件附带的参数:
<MyButton @increase-by="(n) => count += n" />
//或者,也可以用一个组件方法来作为事件处理函数:
<MyButton @increase-by="increaseCount" />
methods: {
increaseCount(n) {
this.count += n
}
}
实际使用
//父组件
<machine-disqualification
:visable-dr="drugDisqualificationVisible"
:form="editform"
:number-list="numberList"
:projects-list="projectsList"
@disqualificationCertain="handleDisqualificationCertain"
/>
export default{
methods: {
handleDisqualificationCertain(val) {
}
}
}
//子组件
<el-button type="primary" :loading="confirmLoading" @click="handleCertain('ruleForm')">确 定</el-button>
export default{
methods: {
handleCertain() {
this.$emit('disqualificationCertain', 1)
},
}
}
本文是借鉴vue3和在开发过程中组件的使用