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
    }
}
}

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,542评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,596评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,021评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,682评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,792评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,985评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,107评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,845评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,299评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,612评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,747评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,441评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,072评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,828评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,069评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,545评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,658评论 2 350

推荐阅读更多精彩内容