vue中的传值

一.父传子和字传父

<template>
  <div>
    <aa :num=" number" />
  </div>
</template>

<script>
import aa from '../aa.vue'
export default {
  name: '',
  components: { aa },
  data() {
    return {
      number: 123
    }
  },
  methods: {
  }
}
</script>

<script>
import aa from '../aa.vue'
export default {
  name: '',
  components: { aa },
  data() {
    return {
      number: 123
    }
  },
  methods: {
  }
}
</script>

<style scoped>

</style>

<template>
  <div>
    {
   
   { num }}
  </div>
</template>

<script>

export default {
  name: '',
  props: {
    num: {
      type: Number,
      default: 20
    }
  },
  methods: {
  }
}
</script>

<style scoped>

</style>

过程在父组上通过定义一个属性然后将数据传递过去。

我们这里绑定的是

 

 收的是:

如果传递的是一个复杂的数据类型呢?

代码:

<template>
  <div>
    <aa :num="obj" />
  </div>
</template>

<script>
import aa from '../aa.vue'
export default {
  name: '',
  components: { aa },
  data() {
    return {
      obj: {
        name: '张三'
      }
    }
  },
  methods: {
  }
}
</script>

<style scoped>

</style>
<template>
  <div>
    {
   
   { num.name }}
  </div>
</template>

<script>

export default {
  name: '',
  props: {
    num: {
      type: Object,
      default: () => {}
    }
  },
  methods: {
  }
}
</script>

<style scoped>

</style>

简单数据类型的修改

<template>
  <div>
    <aa :num=" number" />
  </div>
</template>

<script>
import aa from '../aa.vue'
export default {
  name: '',
  components: { aa },
  data() {
    return {
      number: 123
    }
  },
  methods: {
  }
}
</script>

<script>
import aa from '../aa.vue'
export default {
  name: '',
  components: { aa },
  data() {
    return {
      number: 123
    }
  },
  methods: {
  }
}
</script>

<style scoped>

</style>

<template>
  <div>
    <div>
      {
   
   { num }}

    </div>
    <button @click="fn">
      点击</button>

  </div>

</template>

<script>

export default {
  name: '',
  props: {
    num: {
      type: Number,
      default: 20
    }
  },
  methods: {
    fn() {
      this.num = 456
    }
  }
}
</script>

<style scoped>

</style>

 vue给予了警告

通过this.$emit修改过后呢?

<template>
  <div>
    <aa :num="number" @input="show" />
  </div>
</template>

<script>
import aa from '../aa.vue'
export default {
  name: '',
  components: { aa },
  data() {
    return {
      number: 123
    }
  },
  methods: {
    show(val) {
      console.log(val)
    }
  }
}
</script>

<style scoped>

</style>
<template>
  <div>
    <div>
      {
   
   { num }}

    </div>
    <button @click="fn">
      点击</button>

  </div>

</template>

<script>

export default {
  name: '',
  props: {
    num: {
      type: Number,
      default: 20
    }
  },
  methods: {
    fn() {
      this.$emit('input', 456)
    }
  }
}
</script>

<style scoped>

</style>

可以看到代码并没有发生任何的报错。

为什么官方不建议直接修改呢?

我们来模拟一下这个场景 

父组件的代码:

<template>
  <div>
    <aa :num="number" />
    <button @click="fn">父组件的修改</button>
  </div>
</template>

<script>
import aa from '../aa.vue'
export default {
  name: '',
  components: { aa },
  data() {
    return {
      number: 10
    }
  },
  methods: {
    fn() {
      this.number = 30
    }

  }
}
</script>

<style scoped>

</style>

<template>
  <div>
    <div>
      {
   
   { num }}

    </div>
    <button @click="fn">
      子组件的修改</button>

  </div>

</template>

<script>

export default {
  name: '',
  props: {
    num: {
      type: Number,
      default: 20
    }
  },
  methods: {
    fn() {
      this.num = 20
    }
  }
}
</script>

<style scoped>

</style>

刚开始的值:

子组件修改变量后:

父组件修改变量后:

 

通过this.$emit看下:

<template>
  <div>
    <aa :num="number" @input="show" />
    <button @click="fn">父组件的修改</button>
  </div>
</template>

<script>
import aa from '../aa.vue'
export default {
  name: '',
  components: { aa },
  data() {
    return {
      number: 10
    }
  },
  methods: {
    show(val) {
      this.number = val
    },
    fn() {
      this.number = 30
    }

  }
}
</script>

<style scoped>

</style>

<template>
  <div>
    <div>
      {
   
   { num }}

    </div>
    <button @click="fn">
      子组件的修改</button>

  </div>

</template>

<script>

export default {
  name: '',
  props: {
    num: {
      type: Number,
      default: 20
    }
  },
  methods: {
    fn() {
      this.$emit('input', 20)
    }
  }
}
</script>

<style scoped>

</style>

初始值:

需要子组件:

修改父组件:

通过这两次对比:

vue.runtime.esm.js?2b0e:619 [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. Prop being mutated: "num"

found in

---> <Aa> at aa.vue
       <App> at src/App.vue
         <Root>

很好地说明了一点:

我在子组件里面修改了值为20,直接修改。

下次我在父组件里面在去修改相同的值此时的值被覆盖。

通过this.$emit修改没有实现覆盖而是实现同步。

如果是一个复杂的数据类型呢?

父组件:

<template>
  <div>
    <aa :num="obj" />
  </div>
</template>

<script>
import aa from '../aa.vue'
export default {
  name: '',
  components: { aa },
  data() {
    return {
      obj: {
        name: '张三'
      }
    }
  },
  methods: {
  }
}
</script>

<style scoped>

</style>
<template>
  <div>
    {
   
   { num.name }}
  </div>
</template>

<script>

export default {
  name: '',
  props: {
    num: {
      type: Object,
      default: () => {}
    }
  },
  methods: {
  }
}
</script>

<style scoped>

</style>

只修改堆

可以看出实现了同步的更新

 也就是他们指向了同一个地址。

子组件如何修改自己的内容 不影响父组件呢?

重新赋值,在生成一个新的对象。

 fn() {
      this.num = {
        name: '李四'
      }
    }

如果不做修改,赋值组件也是呈现一个双选绑定的状态。

结论:

修改值的话,最好是通过this.$emit去通知父组件进行修改,要不可能会造成覆盖。

有什么好的替代方案呢?

在实际的开发中我们通常是通过ref去进行修改。

代码:

<template>
  <div>
    <aa ref="aa" :num="obj" />
    <button @click="fn">修改子组件里面的值</button>
  </div>
</template>

<script>
import aa from '../aa.vue'
export default {
  name: '',
  components: { aa },
  data() {
    return {
      obj: {
        name: '张三'
      }
    }
  },
  methods: {
    fn() {
      this.$refs.aa.falg = true
      console.log(this.$refs.aa)
    }
  }
}
</script>

<style scoped>

</style>
<template>
  <div>
    <div>
      {
   
   { num.name }}
    </div>
    <button @click="fn">点击</button>

  </div>

</template>

<script>

export default {
  name: '',
  props: {
    num: {
      type: Object,
      default: () => {}
    }
  },
  data() {
    return {
      falg: false
    }
  },
  methods: {
    fn() {
      this.num = {
        name: '李四'
      }
    }
  }
}
</script>

<style scoped>

</style>

二.兄弟传值

在vue的原型链上一个实例化对象

Vue.prototype.$vus = new Vue()

触发:

this.$emit(事件名,值)

接收:

this.$on(事件名,变量)

销毁:

this.$off(事件名)

代码:

<template>
  <div>
    <aa />
    <cc />
  </div>
</template>

<script>
import aa from '../aa.vue'
import cc from '../cc.vue'
export default {
  name: '',
  components: { aa, cc }
}
</script>

<style scoped>

</style>
<template>
  <div class="">
    子组件2
  </div>
</template>

<script>
export default {
  name: '',
  mounted() {
    this.$bus.$emit('aa', 123)
  },
  methods: {

  }
}
</script>

<style scoped>

</style>

<template>
  <div class="">
    子组件1
  </div>
</template>

<script>

export default {
  name: '',
  mounted() {
    this.$bus.$on('aa', (val) => {
      alert(val)
    })
  },
  methods: {
  }
}
</script>

<style scoped>

</style>

关闭

<template>
  <div class="">
    子组件1
  </div>
</template>

<script>

export default {
  name: '',
  mounted() {
    this.$bus.$on('aa', (val) => {
      alert(val)
    })
    this.$bus.$off('aa')
  },
  methods: {
  }
}
</script>

<style scoped>

</style>

猜你喜欢

转载自blog.csdn.net/qq_59076775/article/details/126163798