0


【Vue2】组件通信 之 props

Props 声明

  • props 可以是 string[] / Object 的形式

sreing[]

写法

<template><div><!-- 设置自定义属性 (传递数据) --><Sonname="superman"age="21"/></div></template><script>import Son from'./components/Son.vue';exportdefault{name:'App',components:{ Son },};</script>
<template><div><h2>姓名: {{ name }}</h2><h2>年龄: {{ age }}</h2></div></template><script>exportdefault{name:'Son',// 编写 props 配置项 (接收数据)props:['name','age'],};</script>

对象式写法(推荐)

<template><div><!-- 设置自定义属性 (传递数据) --><Sonname="superman":age="21"/><!-- 注意, 这里使用 v-bind 绑定 age, 所以传递的是数值 --></div></template>
<script>exportdefault{name:'Son',// 配置 props 属性 (接收数据)props:{name: String,// 限制 name 的属性值为 string 类型age: Number,// 限制 age 的属性值为 number 类型},};</script>

传递 prop 的细节

  • 可以在父组件中给子组件标签元素设置自定义属性 :prop-name="XXX" / :propName="XXX" 传递数据 即可在子组件中通过 props: ["propName"] 接收数据
  • 可以使用一个对象绑定多个 prop
// 假设有一个 post 对象const post ={id:1,title:'My Journey with Vue',};
<!-- 以下两种写法等效: --><BlogPostv-bind="post"/><BlogPost:id="post.id":title="post.title"/>

单向数据流

  • 每次父组件更新后,所有的子组件中的 props 都会被更新到最新值
  • 因此,我们可以在子组件中修改 props 传递过来的数据。否则: 1. 控制台会发出警告(子组件中显示的数据还是会改变2. 一旦父组件的数据更新,子组件接收的对应数据也会被更新
<template><div><h1>{{ showApp() }}</h1><button@click="num++">修改 age</button><hr/><Son:age="num"/></div></template><script>import Son from'./components/Son.vue';exportdefault{name:'App',components:{ Son },data(){return{num:21};},methods:{showApp(){
                console.log('showApp');return'App';},},};</script>
<template><div><h2>{{ showSon() }}</h2><h2>年龄: {{ age }}</h2><button@click="age++">修改 age</button></div></template><script>exportdefault{name:'Son',props:['age'],methods:{showSon(){
                console.log('showSon');return'Son';},},};</script>

在子组件中 修改父组件传递过来的数据:控制台抛出警告、子组件的数据可以被成功修改、重新渲染子组件
参与子组件数据显示的方法

showSon

,在页面完成时被调用一次;子组件修改数据后,重新渲染子组件,被调用一次

此时我们再在父组件中修改原数据,则子组件的数据也会被修改,就是说,子组件之前修改的数据会被覆盖
参与页面数据显示的方法

showApp

showSon

,在页面完成时依次被调用一次;父组件修改数据后,页面重新渲染,再依次被调用一次

  • 如果非得在子组件中获取并修改父组件传递的数据,我们可以将 props 中的数据赋值到 data 中 此时我们操作的,其实就是子组件自己的数据啦
<template><div><h2>{{ showSon() }}</h2><h2>年龄: {{ sonAge }}</h2><button@click="sonAge++">修改 sonAge</button></div></template><script>exportdefault{name:'Son',data(){return{sonAge:this.age };// 将接收到的数据设置为组件自己的数据},props:['age'],methods:{showSon(){
                console.log('showSon');return'Son';},},};</script>

此时,子组件渲染的是 data 中的数据

sonAge

更新子组件 data 中的数据,子组件会被重新渲染、

showSon

被调用
更新父组件的数据,父组件会被重新渲染、

showApp

被调用;此时子组件不会被重新渲染

注意:自己的数据不要与接收的数据同名,否则会报错(**页面会优先显示

props

的数据**

引用类型数据

  • 因为是赋值处理,所以传递引用类型数据要特别注意,因为引用类型的数据操作的是地址 此时,传递的是父组件的数据的引用;就是说,父子组件操作的是同一数据
  • 在项目中,应该尽可能避免这样的更改,除非父子组件在设计上本来就需要紧密耦合
<template><div><h1>{{ showApp() }}</h1><button@click="sonObj.num++">修改 age</button><hr/><!-- 传入对象数据 --><Son:ageObj="sonObj"/></div></template><script>import Son from'./components/Son.vue';exportdefault{name:'App',components:{ Son },data(){return{sonObj:{num:21}};},methods:{showApp(){
                console.log('showApp');return'App';},},};</script>
<template><div><h2>{{ showSon() }}</h2><h2>年龄: {{ ageObj.num }}</h2><!-- 直接修改对象数据 --><button@click="ageObj.num++">修改 ageObj</button></div></template><script>exportdefault{name:'Son',props:['ageObj'],// 接收对象数据methods:{showSon(){
                console.log('showSon');return'Son';},},};</script>

可以发现,页面初始化时,

showApp

showSon

依次被调用
不论在子组件还是在父组件中修改数据,都能成功修改数据、并重新渲染组件模版,

showSon

被调用

子组件传递数据给父组件

父组件给子组件传递函数,子组件给函数传入参数,从而实现子组件给父组件传递数据

  1. 通过自定义属性,父组件给子组件传递函数
  2. 子组件通过 props 属性接收该函数
  3. 在调用该函数时,传入数据作为参数
  4. 父组件就能 [以参数的形式] 接收到子组件传递过来的数据
<template><div><p>父组件数据:{{ msg }}</p><hr/><!-- 给子组件绑定属性,传递方法 --><Son:parentFun="parentFun"/></div></template><script>import Son from'./components/Son.vue';exportdefault{name:'App',components:{ Son },data(){return{msg:'father'};},methods:{parentFun(val){
                console.log('val', val);this.msg += val;},},};</script>
<template><divclass="son"><!-- 调用方法,传入数据 --><button@click="parentFun(sonMsg)">点击将子组件的数据传递给父组件</button></div></template><script>exportdefault{name:'Son',props:['parentFun'],// 设置 props 属性,接收方法data(){return{sonMsg:'son'};},};</script>

Prop 校验

{// 基础类型检查propA: Number,// 给出 `null` 和 `undefined` 值则会跳过任何类型检查// 多种可能的类型propB:[String, Number],// 必传, 且为 String 类型propC:{type: String,required:true},// Number 类型的默认值propD:{type: Number,default:100},// 对象类型的默认值propE:{type: Object,// [对象] / [数组] 的默认值, 必须从一个工厂函数返回// 该函数接收组件所接收到的原始 prop 作为参数default(rawProps){return{message:'hello'}}},// 自定义类型校验函数propF:{validator(value){// The value must match one of these strings// return false 则抛出警告 (开发模式下)return['success','warning','danger'].includes(value)}},// 函数类型的默认值propG:{type: Function,// 不像对象或数组的默认, 这不是一个工厂函数. 这会是一个用来作为默认值的函数default(){return'Default function'}}}

一些个细节

  • 所有 prop 默认都是可选的,除非声明了 required: true
  • 除 Boolean 外的未传递的可选 prop 将会有一个默认值 undefined;Boolean 类型的未传递 prop 将被转换为 false 这可以通过为它设置 default 来更改 —— eg:设置为 default: undefined 将与非布尔类型的 prop 的行为保持一致
  • 如果声明了 default 值,那么在 prop 的值被解析为 undefined 时,无论 prop 是未被传递还是显式指明的 undefined,都会改为 default 值

prop 的类型

  • 可以传递以下类型的数据:① String、② Number、③ Boolean、④ Symbol、⑤ Date、 ⑥ Array、⑦ Object、⑧ Function
  • 另外,type 也可以是自定义的类或构造函数,Vue 将会通过 instanceof 来检查类型是否匹配
// 假设有 Person 类classPerson{constructor(firstName, lastName){this.firstName = firstName;this.lastName = lastName;}}
defineProps({author: Person,// 使用 Person 类约束类型// Vue 会通过 instanceof Person 来校验 author prop 的值是否是 Person 类的一个实例});

Boolean 类型转换

// 假设组件设置如下 propsdefineProps({disabled: Boolean,});
<!-- 等同于传入 :disabled="true" --><MyComponentdisabled/><!-- 等同于传入 :disabled="false" --><MyComponent/>
  • 当一个 prop 被声明为允许多种类型时,无论声明类型的顺序如何,Boolean 类型的特殊转换规则都会被应用
defineProps({disabled:[Boolean, Number],});

本文转载自: https://blog.csdn.net/Superman_H/article/details/125819343
版权归原作者 JS.Huang 所有, 如有侵权,请联系我们删除。

“【Vue2】组件通信 之 props”的评论:

还没有评论