在Vue中,prop是能够接受由父组件传递给子组件的属性,但prop没法进行修改的(因此我加了引号,嘿嘿)。html
若是prop被强制修改,会有警告⚠️vue
❝[Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value.markdown
❞
「因此,咱们只能“变相”地修改prop~」ide
固然,若是你对以上的话一脸懵逼能够看看官网文档关于Prop的内容函数
上面的警告大概意思说:单独在子组件中修改数值,在父组件从新渲染更新的时候仍是传同样的值进去,形成一个重写的状况。oop
说得白话一点:哪一个组件定义数值,应该哪一个组件定义方法(函数)进行修改。ui
和Vuex的状态管理相似,为何state中的数值只能由mutation进行修改操做,最核心的缘由——可回溯。this
只由一个“管理员”进行修改操做,避免多个不一样身份进行修改操做,这样就不会“乱套”了,而在状态追溯时候只要看mutation作了什么操做,这样就会一目了然。spa
那天然,若是传递给子组件的prop数据是在父组件上定义,那修改的prop的数据的方法(函数)能够在父组件中定义。双向绑定
<!--父组件-->
<template> <div> <Child :propNum="num" @propFun="changeNum"/> </div> </template> <script> // 引入 src/components/Child // 引入要根据文件目录进行修改 import Child from '@/components/Child' export default { components: { // 注册组件 Child }, data () { return { // 定义num数值 num: 0 } }, methods: { // 定义修改数值方法 changeNum () { this.num = this.num + 1 } } } </script> 复制代码
<!--子组件-->
<template> <div> <span> {{propNum}} </span> <button type="button" @click="onClick"> add </button> </div> </template> <script> export default { props: { propNum: { // 接受父子组件传递的属性 type: Number, default: 0 } }, methods: { onClick () { // 在点击按钮触发,父组件传递给子组件的方法 this.$emit('propFun') } } } </script> 复制代码
「注意!是vue 2.30以上才能使用,由于刚开始的vue2.0废除的这个修饰符 官网文档」
这里也写一个和上述相似的例子
<!--父组件-->
<template> <div> <Child :propNum.sync="num"/> </div> </template> <script> // 引入 src/components/Child // 引入要根据文件目录进行修改 import Child from '@/components/Child' export default { components: { Child }, data () { return { num: 0 } } } </script> 复制代码
<!--子组件-->
<template> <div> <span> {{propNum}} </span> <button type="button" @click="onClick"> add </button> </div> </template> <script> export default { props: { propNum: { type: Number, default: 0 } }, methods: { onClick () { const num = this.propNum + 1 // 定义num数值 this.$emit('update:propNum', num) // 传递更新数值 } } } </script> 复制代码
和vue封装好v-mode的不一样,如下使用的是自定义组件的v-model
「固然仍是要注意使用版本:2.20+」
<!--父组件-->
<template> <div> <Child v-model="num"/> </div> </template> <script> // 引入 src/components/Child // 引入要根据文件目录进行修改 import Child from '@/components/Child' export default { components: { Child }, data () { return { num: 0 } } } </script> 复制代码
<!--子组件-->
<template> <div> <span> {{propNum}} </span> <button type="button" @click="onClick"> add </button> </div> </template> <script> export default { model: { prop: 'propNum', // v-model选择prop中传递名 event: 'changeNum' // 定义事件 }, props: { propNum: { type: Number, default: 0 } }, methods: { onClick () { const num = this.propNum + 1 this.$emit('changeNum', num) // 使用$emit触发事件并传值 } } } </script> 复制代码
以上三种方法均可以“变相修改”props,其中使用父子组件传值是引用“定义状态同时定义修改状态方法”,然后两中.sync和v-model则是使用“双向绑定”。
彷佛第一种好像还能够理解,但后两种又怎么验证呢?,其实只在父和子组件加上使用watch,如在使用.sync修饰符上加watch:
<!--父组件-->
<template> <div> <Child :propNum.sync="num"/> </div> </template> <script> // 引入 src/components/Child // 引入要根据文件目录进行修改 import Child from '@/components/Child' export default { components: { Child }, data () { return { num: 0 } }, watch: { // 监听父组件num属性 num: { handler () { console.log('父组件num', this.num) } } } } </script> 复制代码
<!--子组件-->
<template> <div> <span> {{propNum}} </span> <button type="button" @click="onClick"> add </button> </div> </template> <script> export default { props: { propNum: { type: Number, default: 0 } }, methods: { onClick () { const num = this.propNum + 1 // 定义num数值 this.$emit('update:propNum', num) // 传递更新数值 } }, watch: { // 监听子组件propNum属性 propNum: { handler () { console.log('子组件propNum', this.propNum) } } } } </script> 复制代码
运行,点击add按钮就有如下结果
相似使用自定义组件但v-model,也能够使用这种方法验证,你们能够自行验证,就再也不赘述~
感谢阅读