Vue3——组件传值 & v-model & 异步组件 & teleport组件

一、父子组件传值

父组件通过props向子组件传值,子组件通过emit触发自定义事件传递新值给父组件。
props:setup函数中第一个参数props用于接收父组件传递进来的参数。注意:props参数中,只会接收props选项中接收的参数 。
context参数:setup函数中的第二个参数是一个上下文对象context。context参数里面有三个对象:attrs,emit,slots。

  • attrs:用于获取没有采用props选项接收的参数。
  • emit:用于触发自定义事件。
  • slots:返回的是插槽里面的虚拟DOM信息。

虚拟DOM:就是vue实例所能识别的一个DOM信息对象。

父组件

父组件

姓名:{{ name }}
年龄:{{ age }}
年龄:{{ sex }}
import {ref} from 'vue'
import Son1 from "./Son1.vue";
export default {
  name: "Parent",
  setup() {
      let name = ref('张三')
      let age = ref(20)
      let sex = ref('男')
      let updateData = (e)=>{   
          name.value = e.myName
          age.value = e.myAge
          sex.value = e.mySex
      }
      return {
          name,
          age,
          sex,
          updateData
      }
  },
  /* data() {
      return {
          name:'张三',
          age:20
      }
  },
  methods: {
      updateData(e){
          this.name = e.myName
          this.age = e.myAge
      }
  }, */
  components: {
    Son1,
  },
};

子组件

Son1

姓名:{{ myName }}
年龄:{{ myAge }}
性别:{{ mySex }}
import {ref,reactive} from 'vue';
export default {
  name: "Son1",
  //接收父组件的传值
  props: ["name", "age"],
  // setup的第一个参数,用于获取父组件的传值
  // 注意:props选项接收了几个参数,setup函数的第一个参数就只能获取几个参数。
  // setup的第二个参数,是一个上下文对象;它里面一个方法是emit,用于触发自定义事件
  // props选项没有接收的传值,在setup里面通过上下文对象的attrs属性接收
  setup(props,{emit,attrs,slots}) {
      // slots对象返回的是插槽里面的虚拟DOM信息
      console.log(slots.top());
      // 中转props里面的数据,因为props是只读的
      let myName = ref(props.name)
      let myAge = ref(props.age)
      let mySex = ref(attrs.sex)
      let car = reactive({
        name:'奔驰',
        price:20
      })
      let updateData = ()=>{
          myName.value = '李四'
          myAge.value = 30
          mySex.value = '女'
          // 触发自定义事件
          emit('updateData',{myName:myName.value,myAge:myAge.value,mySex:mySex.value})
      }
      return {
          myName,
          myAge,
          mySex,
          updateData,
          car
      }
  }
  /* data() {
      return {
          myName:this.name,
          myAge:this.age
      }
  },
  methods: {
      updateData(){
          this.myName = '李四'
          this.myAge = 30
          this.$emit('updateData',{myName:this.myName,myAge:this.myAge})
      }
  }, */
};

二、祖孙组件传值

祖级组件通过provide将指定的数据添加为依赖数据,让后代组件可以直接使用。孙代组件通过inject注入祖级组件中设置为依赖的数据。

祖级组件

import {ref,provide} from 'vue'
import Son from './components/Son.vue'
export default {
  name: 'App',
  setup() {
    let name = ref('张三')
    let age = ref(20)
    // 通过provide()方法,定义依赖数据,从此它的子组件,就可以获取这些数据了
    provide('name',name)
    provide('age',age)
    return {
      name,
      age
    }
  },
  components: {
    Son
  }
  /* 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
    }
  }, */
}

孙级组件

SubSon

  • 姓名:{{name}}
  • 年龄:{{age}}
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
      }
  }
  /* inject:['name','age','updateData'],
  data() {
      return {
          myName:this.name,
          myAge:this.age
      }
  },
  methods: {
      update(){
          this.myName = '李四'
          this.myAge = 30
          this.updateData('李四',30)
      }
  }, */
};

三、v-model

在Vue3中,父组件中可以通过v-model指令实现对多个数据的双向绑定。注意:vue3取消了sync修饰符,它将v-model指令和sync修饰符进行了合并。
子组件中,自定义事件名称必须命名为update:属性名,就可以实现对父组件中指定属性的双向绑定。

父级组件

App

import {ref,provide} from 'vue'
import Son3 from './components/Son3.vue'
export default {
  name: 'App',
  setup() {
    //定义飞机的相关数据
    let planeName = ref('波音747')
    let planePrice = ref(100)
    let planeAddress = ref('美国')

    return {
      // 返回飞机相关信息
      planeName,
      planePrice,
      planeAddress
    }
  },
  components: {
    Son3
  }

子级组件

Son3

  • 飞机名称:{{ planeName }}
  • 飞机价格:{{ planePrice }}
  • 飞机产地:{{ planeAddress }}
export default {
  name: "Son3",
  //接收父组件传递过来的数据
  props: ["planeName", "planePrice", "planeAddress"],
  setup(props, { emit }) {
    let updatePlaneName = () => {
      // 注意:事件方法必须是update:prop,如果父组件中采用的是v-model:prop
      // 此时,父组件就可以实现对prop的双向数据绑定。
      emit("update:planeName", "长城1号");
    };
    let updatePlanePrice = () => {
      emit("update:planePrice", 200);
    };
    let updatePlaneAddress = () => {
      emit("update:planeAddress", "中国");
    };
    return {
      updatePlaneName,
      updatePlanePrice,
      updatePlaneAddress,
    };
  },
};

四、异步组件

suspense内置组件:用于在渲染异步组件时,添加Loading效果。
使用 包裹所有异步组件相关代码。
插槽包裹异步组件。
插槽包裹渲染异步组件之前的内容。
注意:异步加载的组件可以用suspense,也可以不用。不用suspense组件,会失去异步的作用;但是,如果组件中setup的返回值是一个Promise对象,该组件必须要用suspense。

定义组件

Son4

  • 商品名称:{{ goodsName }}
  • 商品价格:{{ goodsPrice }}
import { ref } from "vue";
export default {
  name: "Son4",
  setup() {
    let goodsName = ref("小米电视");
    let goodsPrice = ref(2000);
    //setup方法的返回值,可以是一个Promise对象
    return new Promise((resolve,reject)=>{
        setTimeout(() => {
            resolve({
                goodsName,
                goodsPrice,
                show
            })
        }, 2000);
    })

    // return {
    //     goodsName,
    //     goodsPrice,
    // }
  },
};

使用

App

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

五、teleport组件

Vue 3.0 新增了一个内置组件 teleport ,主要是为了解决以下场景:有时组件模板的一部分逻辑上属于该组件,而从技术角度来看,最好将模板的这一部分移动到 DOM 中 Vue app 之外的其他位置。
teleport组件:瞬移。通过to属性确定里面的元素移动到哪。to属性的属性值是指定的选择器。

例如:在下面的案例中,box盒子逻辑上属于son4盒子,但是为了使box盒子设置的相对定位,不受其他父级元素的影响,我们将box盒子瞬移到body下。

Son4

  • 商品名称:{{ goodsName }}
  • 商品价格:{{ goodsPrice }}
.box{
    width: 200px;
    height: 200px;
    border: 1px solid black;
    padding: 10px;
    background: lightblue;
    /* 绝对定位 */
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    margin: auto;
}

使用teleport瞬移后,box盒子的结构是在body下,与#app平级。

你可能感兴趣的:(Vue3——组件传值 & v-model & 异步组件 & teleport组件)