Vue2&Vue3中的组件传值&自定义v-model语法糖

祖孙组件间传值

Vue3中的祖孙组件间的传值:
①父组件通过使用provide()方法,定义依赖数据。
proviede(名称,传输的数据名)记得返回出去
②子组件通过inject接收:let xx=inject(名称)
③修改的话直接通过事件.value修改数据,比起Vue2修改值少了转换和发送自定义事件步骤

Vue2的祖孙组件间的传值
①父组件通过provide(){return{name:this.name}}函数定义依赖数据
②子组件通过inject:[]接收父组件传递参数
③修改值要写方法,只有父级变了它才会变。所以给父级定义个方法,再通过provide()依赖传递(不仅可以依赖数据,还可以依赖方法),在子孙组件方法中调用父级定义的方法并传实参过去。

父组件
<template>
  <div class="son">
    <h2>Son1</h2>
    <ul>
      <li>车名:{{carName}}</li>
      <li>车价:{{carPrice}}</li>
    </ul>
    <SubSon/>
  </div>
</template>
<script>
import {inject} from 'vue'
import SubSon from "./SubSon.vue";
export default {
  name: "Son",
  setup() {
    let carName = inject('carName')
    let carPrice = inject('carPrice')
    return{
      carName,
      carPrice
    }
  },
  components: {
    SubSon,
  },
  data() {
    return {
      name:'张三',
      age:20
    }
  },

Vue2中的祖孙组件传递数据并更改数据
  // 定义依赖数据
  provide(){
   return{
    name:this.name,
    age:this.age,
    updateData:this.updateData
   }
  },
  methods: {
    // 定义修改数据方法
    updateDate(name,age){
      this.name=name
      this.age=age
    }
  },
};
子孙组件
<template>
  <div class="subSon">
    <h2>SubSon</h2>
    <ul>
        <li>姓名:{{name}}</li>
        <li>年龄:{{age}}</li>
        <li>
            <button @click="update">修改信息</button>
        </li>
    </ul>
  </div>
</template>
<script>
import {inject} from 'vue'
export default {
  name: "SubSon",
  setup() {
      //inject()方法,用于注入父级中依赖的数据
      let name = inject('name')
      let age = inject('age')
      let update = ()=>{
          name.value = '李四'
          age.value = 30
      }
      return {
          name,
          age,
          update
      }
  }

Vue2中的祖孙组件传递数据并更改数据
inject:['name','age','updatedate'],
data() {
    return {
         myName:this.name,
         myAge:this.age
    }
},
methods: {
   update(){
    //    修改自己
       this.myName='李四'
       this.myAge='20'
    //    修改父级
       this.updateData('李四',30)
   }
},
};
</script>

兄弟组件传值

Vue2中Vue是个构造函数,所以兄弟组件传值,用中央事件总线,给vue的实例添加数据。
而在Vue3中Vue是个对象,所以无法再使用给实例添加数据的方式。我们可以把数据都给父级再去修改。
注意:在Vue3中不使用的数据就不需要返回
Vue3的兄弟组件传值 数据提升的方式
①在共同的父级定义数据和方法。父级通过provide(子级接收名,传递的值)方法设置为依赖数据
②子级在inject(子级接收名)方法中接收数据,页面中直接使用,记得return
③另一个子组件在inject()方法中接收修改数据的方法,并绑定点击事件

父级

<template>
  <div class="app">
    <h2>App</h2>
    <ul>
        <li>姓名:{{name}}</li>
        <li>年龄:{{age}}</li>
    </ul>
    <ul>
      <li>飞机名称:{{planeName}}</li>
      <li>飞机价格:{{planePrice}}</li>
      <li>飞机产地:{{planeAddress}}</li>
    </ul>
    <!-- suspense内置组件,用于在渲染异步组件时,添加Loading效果 -->
    <!-- 注意:
    1.异步组件可以不使用suspense组件,但是会失去异步的作用
    2.如果组件中setup的返回值是一个Promise对象,那么该组件在导入时,必须采用异步方式导入;
    并且该组件必须要使用suspense组件-->
    <suspense>
      <!-- default插槽里面放置异步组件 -->
      <template #default>
        <Son4/>
      </template>
      <!-- fallback插槽里面放置组件没有加载完成时显示的内容 -->
      <template #fallback>
        Loading...
      </template>
    </suspense>
    <Son/>
    <Son2/>
    <!-- 在vue3中子定义组件时,v-model可以使用多次,实现对多个数据的双向绑定,
    注意:vue3取消了sync修饰符,它将v-model指令和sync修饰符进行了合并。 -->
    <Son3 v-model:planeName="planeName" 
    v-model:planePrice="planePrice" v-model:planeAddress="planeAddress" />
  </div>
</template>

<script>
import {ref,provide,defineAsyncComponent} from 'vue'

import Son from './components/Son.vue'
import Son2 from './components/Son2.vue'
import Son3 from './components/Son3.vue'

// defineAsyncComponent组合式API,用于定义异步组件
// 异步导入组件
const Son4 = defineAsyncComponent(()=>import('./components/Son4.vue'))

export default {
  name: 'App',
  setup() {
    let name = ref('张三')
    let age = ref(20)

    let carName = ref('保时捷')
    let carPrice = ref(100)
   let updateCar = (name,price)=>{
      carName.value = name
      carPrice.value = price
    }

    //通过provide()方法,定义依赖数据,从此它的子组件,就可以获取这些数据了
    provide('name',name)
    provide('age',age)

    provide('carName',carName)
    provide('carPrice',carPrice)
    provide('updateCar',updateCar)

    //定义飞机的相关数据
    let planeName = ref('波音747')
    let planePrice = ref(100)
    let planeAddress = ref('美国')

    return {
      name,
      age,
      //返回飞机相关信息
      planeName,
      planePrice,
      planeAddress
    }
  },
  components: {
    Son,
    Son2,
    Son3,
    Son4
  }
  /* data() {
    return {
      name:'张三',
      age:20
    }
  },
  methods: {
    //修改数据的方法
    updateData(name,age){
      this.name = name
      this.age = age
    }
  },
  //定义依赖数据
  provide(){
    return {
      name:this.name,
      age:this.age,
      updateData:this.updateData
    }
  }, */
}
</script>
子级

<template>
  <div class="son2">
    <h2>Son2</h2>
    <button @click="updateCar">修改汽车信息</button>
  </div>
</template>
<script>
import {inject} from 'vue'
export default {
  name: "Son2",
  setup() {
      let updateCar = inject('updateCar')
      let update=()=> {
        updateCar('奔奔车',1000)
      }
  }
};
</script>

Vue2和Vue3中的自定义组件

Vue2中
①父级给子组件绑定属性为:value=xx,绑定事件为@input=xx,就可以使用语法糖sync:属性=xx,
②子级通过props接收的值,可直接在页面中使用
③子级修改父级数据自定义事件$emit('update:属性',修改的值)
Vue3中
①父级给子组件绑定属性为:value=xx,绑定事件为@input=xx,就可以使用语法糖v-model:属性=xx,
②子级通过props接收的值可直接在页面使用(父级必须把数据return出去,子级才可使用)。
③子级要修改接收的父级数据,直接通过setup()中第二个参数context的emit方法。emit('update:属性',修改的值)

<div class="son3">
    <h2>Son3</h2>
    <ul>
        <li>飞机名称:{{planeName}}</li>
        <li>飞机价格:{{planePrice}}</li>
        <li>飞机地址:{{planeAddress}}</li>
        <li><button @click="updatePlaneName">修改飞机名称</button></li>
        <li><button @click="updatePlanePrice">修改飞机价格</button></li>
        <li><button @click="updatePlaneAddress">修改飞机产地</button></li>
    </ul>
</div>
</template>
<script>
export default {
name:'Son3',
props:['planeName',"planePrice","planeAddress"],
setup(props,{emit}) {
    let updatePlaneName=()=>{
        // planeName.value="长城1号" //改自己的名称
        // console.log(planeName);
        // 事件方法必须是uptate:prop(属性),如果父组件中采用的是v-model
        // 此时父组件就可以实现对prop的双向数据绑定
        emit('update:planeName','长城1号')
    }
    let updatePlaneAddress=()=>{
    // planeAddress.value="中国" //改自己的名称
        emit('update:planeAddress','中国')
    }
    let updatePlanePrice=()=>{
    // planePrice.value=1000 //改自己的名称
        emit('update:planePrice',1000)
    }
    return{
        updatePlanePrice,
        updatePlaneAddress,
        updatePlaneName
    }
}
}

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容