Vue.js中props的使用
父组件通过 props 向下传递数据给子组件;子组件通过 events 给父组件发送消息。
作用: props是用于Vue中 父组件 向 子组件 传值的时候使用。
- props的传递是单向的。
- 不要在子组件改变props的值。
一、props的定义
props 需要使用 props 选项来定义:
export default {
props: ['foo'],
created() {
// props 会暴露到 `this` 上
console.log(this.foo)
}
}
除了使用字符串数组来声明 prop 外,还可以使用对象的形式:
export default {
props: {
title: String,
likes: Number
}
}
对于以对象形式声明中的每个属性,key 是 prop 的名称,而值则是该 prop 预期类型的构造函数。比如,如果要求一个 prop 的值是 number
类型,则可使用 Number
构造函数作为其声明的值。
对象形式的 props 声明不仅可以一定程度上作为组件的文档,而且如果其他开发者在使用你的组件时传递了错误的类型,也会在浏览器控制台中抛出警告。
二、父子组件
看一下官方文档:
组件实例的作用域是孤立的。这意味着不能 (也不应该) 在子组件的模板内直接引用父组件的数据。父组件的数据需要通过 prop 才能下发到子组件中。
也就是props
是子组件访问父组件数据的唯一接口。
详细一点解释就是:
- 一个组件可以直接在模板里面渲染data里面的数据(双大括号)。
- 子组件不能直接在模板里面渲染父元素的数据。
- 如果子组件想要引用父元素的数据,那么就在prop里面声明一个变量(比如a),这个变量就可以引用父元素的数据。然后在模板里渲染这个变量(前面的a),这时候渲染出来的就是父元素里面的数据。
在 Vue 中,注册 props 的方式有两种:
- 第一种方式是,以字符串数组的方式列出 props,数组中的每个实体对应一个 prop 名称。
- 第二种方法是将 props 定义为一个对象,每个 key 对应于 prop 名称。
<div id="app1">
<!-- hello引用父元素的hello,它也可以引用message,greet,world等 -->
<child :hello='hello'></child>
</div>
<script>
var com1 = Vue.component('child',{
// 声明在prop中的变量可以引用父元素的数据
props:['hello'],
// 这里渲染props中声明的那个hello
template:'<div><p>{{ hello }}</p></div>',
})
var app1 = new Vue ({
el: '#app1',
data: {
greet: {
hello:'hello,',
world: 'world',
},
message: 'message1',
}
})
</script>
组件接受的选项之一 props 是 Vue 中非常重要的一个选项。父子组件的关系可以总结为:
props down, events up
父组件通过 props 向下传递数据给子组件;子组件通过 events 给父组件发送消息。
总之,我们使用 props 将数据从父组件传递给子组件。子组件还会向父组件发出事件,以防您需要从子组件向父组件发送数据/事件。
三、Prop 名字格式
如果一个 prop 的名字很长,应使用 camelCase 形式,因为它们是合法的 JavaScript 标识符,可以直接在模板的表达式中使用,也可以避免在作为属性 key 名时必须加上引号。
export default {
props: {
greetingMessage: String
}
}
<span>{{ greetingMessage }}</span>
虽然理论上你也可以在向子组件传递 props 时使用 camelCase 形式 (使用 DOM 模板时例外),但实际上为了和 HTML attribute 对齐,我们通常会将其写为 kebab-case 形式:
<MyComponent greeting-message="hello" />
对于组件名我们推荐使用 PascalCase,因为这提高了模板的可读性,能帮助我们区分 Vue 组件和原生 HTML 元素。然而对于传递 props 来说,使用 camelCase 并没有太多优势,因此我们推荐更贴近 HTML 的书写风格。
四、props 是一种单向数据绑定
当父组件的属性变化时,将传导给子组件,但是反过来不会。
每次父组件更新时,子组件的所有 prop 都会更新为最新值。
不要在子组件内部改变 prop。如果你这么做了,Vue 会在控制台给出警告。
在两种情况下,我们很容易忍不住想去修改 prop 中数据:
- Prop 作为初始值传入后,子组件想把它当作局部数据来用;
- Prop 作为原始数据传入,由子组件处理成其它数据输出。
props 是一种单向数据绑定,组件永远不该改变自己的 props 的值,这点很重要。坚守这点的原因有很多。其一是,组件修改 props 会造成程序调试困难。如果一个值被传递进多个子组件,将很难定位这个值是在哪里被修改的。此外,修改 props 会造成组件重新渲染。所以,一个组件里突变的 props 会触发组件重新渲染,这可能会反过来再次触发 props 突变。
五、例子参考
例子1
使用 props 的主要目标是传递数据/信息。您可以使用 v-bind 将您的值作为数据属性传递。
流程:从子组件props: ['data1', 'data2'] ,在父组件中 查找data1,data2的对应的name、age值
Parent.vue(父组件)
<template>
<div class="outer">
<h3>父组件</h3>
名字:<input v-model="name"><br>
年龄:<input v-model="age"><br>
<child v-bind:data1="name" v-bind:data2="age"></child>
</div>
</template>
<script>
import Child from "./Child";
export default {
name: 'Parent',
components: {Child},
data() {
return {
name: "Tony",
age: 20
}
}
}
</script>
<style scoped>
.outer {
margin: 20px;
border: 2px solid red;
padding: 20px;
}
</style>
Child.vue(子组件)
<template>
<div class="outer">
<h3>子组件</h3>
<div>父组件传过来的data1:{{data1}}</div>
<div>父组件传过来的data2:{{data2}}</div>
</div>
</template>
<script>
export default {
props: ['data1', 'data2']
}
</script>
<style scoped>
.outer {
margin: 20px;
border: 2px solid blue;
padding: 20px;
}
</style>
路由(store/index.js)
import Vue from 'vue'
import Router from 'vue-router'
import Parent from "../components/Parent";
Vue.use(Router)
export default new Router({
routes: [
{
path: '/parent',
name: 'Parent',
component: Parent,
}
],
})
结果:
修改父组件的值,可以看到,父组件修改了值之后,子组件立刻同步更新。
例子2
父子组件可以利用pros直接传值,在子组件中定义props,并可规定传值类型,当父组件使用子组件时传入相应参数,即可把父组件的数值传递到子组件中。
父组件App.vue
<template>
<div id="app">
{{msg}}
<hellochange :msgchange=msgdata></hellochange>
</div>
</template>
<script>
import HelloChange from './components/HelloChange.vue'
export default {
components:{
hellochange:HelloChange
},
data () {
return {
msg:'你好vue',
msgdata:'我是父组件传值'
}
}
}
</script>
子组件HelloChange.vue
<template>
<!-- 所有的内容要被根节点包含起来 -->
<div id="hellochange">
{{msg}}
<br>
{{msgchange}}
</div>
</template>
<script>
export default{
data(){
return {
msg:'我是一个home组件'
}
},
props:{
msgchange:{
type:String
}
}
}
</script>
效果:
更多推荐
所有评论(0)