作用: 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 中数据:

  1. Prop 作为初始值传入后,子组件想把它当作局部数据来用;
  2. 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>

效果:

Logo

前往低代码交流专区

更多推荐