vue组件的props属性

Vue组件通过props属性接收父组件传递的值,常见的props定义包括type、default、required和validator。type用于指定prop的数据类型,如String、Number等;default提供默认值;required标记prop是否必需;validator允许自定义验证函数。props数据遵循单向数据流原则,子组件不能直接改变props,但可通过事件通知父组件更新。

VUE组件的props属性


  • vue组件可以通过props属性来从父组件获取值
  • props属性可以有以下几种写法
    // 数组写法
    props: ['title', 'content', 'like']
    // 对象写法 - 1
    props: {
        title: String, // 指定title的类型,设置title只能是String类型的
        content: undefine, // undefine和null表示content可以是任何类型的
        like: [String, Number], // like可以是数组中的任意类型 
    }
    // 对象写法 - 2
    props: {
        title: {
            type: String, // type指定属性类型,用法同上
            default: 'title', // default指定默认值
        },
        content: {
            type: String,
            required: ture, // reuired声明属性是否是必须的,即父组件是否必须传值
        },
        like: {
            type: Number,
            validator: val => { // 自定义验证函数
                return val > 100
            },
        }
    }
    
  • 一般情况下,我们都是使用最后一种写法,即props中的每个属性都是一个对象,我们先称它们为prop对象
  • 每个prop对象都可以有如下属性
    • type
      • 该属性指明prop的类型,type的值可以是下列原生构造函数中的一个
        • [String, Boolean, Number, Array, Object, Date, Function, Symbol]
      • 也可以是null或者undefine,表示prop可以是任何类型的
      • 或者是一个自定义的构造函数,这会通过instanceof的方式来进行比较,来验证prop的值是否是通过new对应的构造函数创建的
        props: {
            user: { // user = new Persion()
                type: Persion
            }
        }
        
    • default
      • 该属性为prop设定一个默认值,父组件传的值将会覆盖该默认值
    • required
      • 该属性的值是一个布尔值,表明prop是否是必须的,即父组件是否必须传值
    • vaildator
      • 该属性的值是一个函数,有一个参数是prop当前的值,返回一个布尔值,使用方式如上
      • 当 prop 验证失败的时候,(开发环境构建版本的) Vue 将会产生一个控制台的警告

      注意那些 prop 会在一个组件实例创建之前进行验证,所以实例的 property (如 data、computed 等) 在 default 或 validator 函数中是不可用的

  • props中的属性是通过单向数据流的方式从父组件传到子组件的
  • 这意味着:
    • props中的属性只能通过父组件来更新
    • 子组件不能直接通过this.prop = xx的方式来更新props中的属性
    • 子组件要更新props中的属性,可以使用如下两种方式
    // 父组件
    <Children :msg.sync="msg" />
    // ...
    data() {
        return {
            msg: 'original'
        }
    }
    // 子组件
    props: {
        msg: {
            type: String,
        }
    }
    methods: {
        handleChange() { // 触发handleChange方法后改变msg
            this.$emit('update:msg', 'change')
        }
    }
    
     --- 子组件
     props: {
       value: {
         type: [Number, String],
       },
       changeMsg: {
         type: Function,
         default: () => { },
       }
     },
     data () {
       return {
         msg: this.value
       }
     },
     methods: {
       handleChangeMsg () {
         this.msg = 'change'
         this.$emit('input', this.msg)
       }
     }
    --- 父组件
    <template>
       {{ msg }}
    </template>
    
    <script>
    export default {
     name: 'Home',
     components: {
       Children
     },
     data () {
       return {
         msg: 'original',
       }
     }
    }
    
Vue 框架中,子组件直接修改传递给它的 `props` 属性是不被推荐的做法,因为这会破坏数据流的单向性,导致调试和维护变得复杂。不过,可以通过一些方式实现类似的效果,同时保持良好的数据管理实践。 ### 通过 `$emit` 事件修改父组件传递的 `props` 值 子组件可以通过触发一个事件来通知父组件更改某个值,然后父组件更新后重新传递新的 `props` 值给子组件。这种方式符合 Vue 的单向数据流设计。 #### 示例代码: ```vue <!-- ParentComponent.vue --> <template> <child-component :message="parentMessage" @update:message="updateMessage" /> </template> <script> import ChildComponent from './ChildComponent.vue'; export default { components: { ChildComponent }, data() { return { parentMessage: 'Hello Vue', }; }, methods: { updateMessage(newMessage) { this.parentMessage = newMessage; }, }, }; </script> ``` ```vue <!-- ChildComponent.vue --> <template> <button @click="changeMessage">Change Message</button> </template> <script> export default { props: ['message'], methods: { changeMessage() { this.$emit('update:message', 'Message Updated'); }, }, }; </script> ``` ### 使用 `.sync` 修饰符(Vue 2.x) 在 Vue 2.x 中,可以使用 `.sync` 修饰符来简化父子组件之间的双向绑定。这种方法实际上是 `$emit` 事件的一个语法糖。 #### 示例代码: ```vue <!-- ParentComponent.vue --> <template> <child-component :message.sync="parentMessage" /> </template> ``` ```vue <!-- ChildComponent.vue --> <template> <button @click="changeMessage">Change Message</button> </template> <script> export default { props: ['message'], methods: { changeMessage() { this.$emit('update:message', 'Message Updated'); }, }, }; </script> ``` ### 使用 `v-model` 实现双向绑定(Vue 3.x) 在 Vue 3.x 中,`v-model` 是 `.sync` 修饰符的一种替代方案,用于创建双向绑定。默认情况下,`v-model` 使用 `modelValue` 和 `update:modelValue` 作为 `prop` 和事件名称。 #### 示例代码: ```vue <!-- ParentComponent.vue --> <template> <child-component v-model="parentMessage" /> </template> ``` ```vue <!-- ChildComponent.vue --> <template> <button @click="changeMessage">Change Message</button> </template> <script> export default { props: ['modelValue'], methods: { changeMessage() { this.$emit('update:modelValue', 'Message Updated'); }, }, }; </script> ``` ### 使用 `provide/inject`(适用于跨层级组件) 如果需要在深层嵌套的组件中修改数据,可以使用 `provide/inject` API 来提供和消费数据。这种方法主要用于祖先组件向其所有子孙组件注入数据,但不推荐用于频繁的数据变更操作。 ### 使用 Vuex/Pinia 状态管理库 对于复杂的应用程序,推荐使用 Vuex 或 Pinia 等状态管理库来集中管理应用的状态。这样可以在任何组件中访问和修改状态,而不必通过 `props` 和 `$emit` 进行繁琐的传递。 ### 使用 `ref` 直接访问子组件的方法(不推荐) 虽然可以通过 `ref` 直接访问子组件的方法和属性,但这通常被认为是反模式,因为它破坏了组件封装性和可测试性。 #### 示例代码: ```vue <!-- ParentComponent.vue --> <template> <child-component ref="childRef" /> <button @click="callChildMethod">Call Child Method</button> </template> <script> import ChildComponent from './ChildComponent.vue'; export default { components: { ChildComponent }, methods: { callChildMethod() { this.$refs.childRef.changeMessage(); }, }, }; </script> ``` ```vue <!-- ChildComponent.vue --> <template> <div>{{ message }}</div> </template> <script> export default { data() { return { message: 'Initial Message', }; }, methods: { changeMessage() { this.message = 'Message Changed via Ref'; }, }, }; </script> ``` 通过上述方法,可以在 Vue 中安全有效地修改子组件接收到的 `props` 值,同时保持良好的数据流管理和组件间通信机制。选择合适的方法取决于具体的应用场景和需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值