Vue3学习常用CompositionAPI

目录

1、setup的两个注意点

2、计算属性与监听

3、watch函数

4、watchEffect函数

5、Vue3生命周期

6、自定义hook函数

7、toRef

8、组件基础


1、setup的两个注意点

  • setup执行的时机
    • 在beforeCreate之前执行一次,this是undefine
  • setup的参数
    • props:值为对象,包含:组件外部传递过来,且组件内部声明接受了的属性。
    • context:上下文对象
      • attrs:值为对象,包含:组件外部传递过来,但没有在props配置中声明的属性,相当于this.$attrs
      • slots:收到插槽的内容,相当于this.$slot,使用具名插槽时可用v-slot:名字
      • emit:分发自定义事件的函数,相当于this.$emit

2、计算属性与监听

  • 与Vue2.x中computed配置功能一样
  • 写法
import { reactive,computed } from 'vue';
setup () {
    // 数据
    let person = reactive({
      firstName: '张三',
      lastName: 18
    })
    // 计算属性--简写(没有考虑计算属性被修改的情况)
     person.fullName = computed(() => {
       return person.firstName + '-' + person.lastName
     })

    // 计算属性--完整写法(考虑读和写)
    person.fullName = computed({
      get () {
        return person.firstName + '-' + person.lastName
      },
      set (value) {
        const nameArr = value.split('-')
        person.firstName = nameArr[0]
        person.lastName = nameArr[1]
      }
    })

    // 返回一个对象(常用)
    return {
      person
    }
  }

3、watch函数

  • 与Vue2.x中watch配置功能一致
  • 两个小“坑”
    • 监视reactive定义的响应式数据时:oldValue无法正确获取,强制开启了深度监视(deep配置时效)
    • 监视reactive定义的相应式数据中某个属性时:deep配置有效
// 数据
    let sum = ref(0)
    let msg = ref('你好啊')
    let person = reactive({
      name: '张三',
      age: 18,
      job: {
        j1: {
          salary: 20
        }
      }
    })

// 情况一:监视ref所定义的一个响应式数据,第三个参数配置属性
    watch(sum, (newValue, oldValue) => {
      console.log('sum变了', newValue, oldValue)
    }, { immediate: true })

    // 情况二:监视ref所定义的多个响应式数据
    watch([sum, msg], (newValue, oldValue) => {
      console.log('sum或msg变了', newValue, oldValue)
    }, { immediate: true })

    /* 情况三:监听reactive所定义的一个响应式数据的全部属性
        1、注意:此处无法正确的获得oldValue
        2、注意:强制开启了深度监视(deep配置无效)
    */
    watch(person, (newValue, oldValue) => {
      console.log(newValue, oldValue)
    }, { deep: false })//此处的deep配置无效

    //情况四:监视reactive所定义的一个响应式数据中的某个属性
    watch(() => person.age, (newValue, oldValue) => {
      console.log(newValue, oldValue)
    })

    // 情况五:监视reactive所定义的一个响应式数据中的某些属性
    watch([() => person.name, () => person.age], (newValue, oldValue) => {
      console.log(newValue, oldValue)
    })

    // 特殊情况
    watch(() => person.job, (newValue, oldValue) => {
      console.log('person的job变化了', newValue, oldValue)
    }, { deep: true })//此处由于监视的是reactive定义的对象中的某个属性,所以deep配置有效

如果对象是ref传对象类型,要注意一些差异

ref取值要.value

 let person = ref({
      name: '张三',
      age: 18,
      job: {
        j1: {
          salary: 20
        }
      }
    })

    //针对基础类型
    watch(sum, (newValue, oldValue) => {
      console.log('sum的值变化了', newValue, oldValue)
    })

    //如果不使用deep,可以使用person.value,但是person.value监视的就不再是refImpl,而是person.value下的reactive实例
    watch(person, (newValue, oldValue) => {
      console.log('person的值变化了', newValue, oldValue)
    }, { deep: true })

4、watchEffect函数

  • watch的套路是:既要指明监视的属性,也要指明监视的回调。
  • watchEffect的套路是:不用指明监视哪个属性,监视的回调中用到哪个属性,那就监视哪个属性。
  • watchEffect有点像computed:
    • 但computed注重的计算出来的值(回调函数的返回值),所以必须要写返回值
    • 但watchEffect更注重的是过程(回调函数的函数体),所以不用写返回值
//watchEffect所指定的回调中用到的数据只要发生变化,则直接重新执行回调。
watchEffect(()=>{
    const x1 = sum.value
    const x2 = person.age
    console.log('watchEffect配置的回调执行了')
})

5、Vue3生命周期

  •  Vue3.0中可以继续使用Vue2.x中的生命周期钩子,但有两个被更名:
    • beforeDestory改名为beforeUnmount
    • destory改名为unmounted
  • Vue3.0也提供了Composition API 形式的生命周期钩子,与Vue2.x中钩子对应关系如下:
    • beforeCreate======>  setup()
    • created===========>setup()
    • beforeMount=======>onBeforeMount
    • mounted==========>onMounted
    • beforeUpdate======>onBeforeUpdate
    • updated==========>onUpdated
    • beforeUnmount=====>onBeforeUnmount
    • unmounted========>onUnmounted

6、自定义hook函数

  • 什么是hook?——本质是一个函数,把setup函数中使用的Compoistion API进行了封装。
  • 类似于vue2.x中的mixin。
  • 自定义hook的又优势:复用代码,让setup中的逻辑更清楚易懂。

7、toRef

  • 作用:创建一个ref对象,其value值指向另一个对象中的某个属性。
  • 语法:const name = toRef(person,'name')。
  • 应用:要将响应式对象中的某个属性单独提供给外部使用。
  • 扩展:toRefs和toRef功能一致,但可以批量创建多个Ref对象,语法toRefs(person)
  • 实例:
<template>
  <div>
    <h4>{{ person }}</h4>
    <h4>姓名:{{ name }}</h4>
    <h4>年龄:{{ age }}</h4>
    <h4>薪资:{{ job.j1.salary }}</h4>
    <button @click="name += '~'">修改姓名</button>
    <button @click="age++">修改年龄</button>
    <button @click="job.j1.salary++">修改薪资</button>
  </div>
</template>

<script>
import { ref, reactive, toRef, toRefs, shallowReactive } from "vue";
export default {
  name: "Test",
  setup() {
    // let person = shallowReactive({
    let person = reactive({
      name: "张三",
      age: 18,
      job: {
        j1: {
          salary: 20,
        },
      },
    });
    return {
      person,
      ...toRefs(person),
    };
  },
};
</script>

<style>
</style>

8、组件基础

  • props :单项传递,尽量不要直接修改props的属性,最好存到computed下使用
  • $emit :点击子组件触发父组件的方法,可以将子组件的数据传递给父组件

Home.vue(父组件)

<Son @enlarge-text="changeText"
         title="My journey with Vue" />

Son.vue(子组件)

<button @click="$emit('enlargeText',{age:'12',name:'123'})">
      Enlarge text
    </button>
  • emits : 允许我们检查组件抛出的所有事件,事件触发前进行验证
emits: {
    enlargeText: ({ age, name }) => {
      console.log(age, "年龄")
      console.log(name, '姓名')
    }
  },
  • $event :父组件访问子组件抛出的值

父组件

<Son @enlarge-text="postFontSize+=$event"
         title="My journey with Vue" />

子组件

<button @click="$emit('enlargeText',0.1)">
      Enlarge text
    </button>
  • 自定义事件  v-model

默认情况下,组件上的 v-model 使用 modelValue 作为 prop 和 update:modelValue 作为事件。我们可以通过向 v-model 传递参数来修改这些名称:

<my-component v-model:title="bookTitle"></my-component>

在本例中,子组件将需要一个 title prop 并发出 update:title 事件来进行同步:

app.component('my-component', {
  props: {
    title: String
  },
  emits: ['update:title'],
  template: `
    <input
      type="text"
      :value="title"
      @input="$emit('update:title', $event.target.value)">
  `
})
  • 插槽
  1. 具名插槽    ---->  v-slot="name"或者用简写 “#name”,默认是#default或v-slot:default
  • 异步引入组件
 components: {
    Son: defineAsyncComponent(() =>
      import('@/components/Son.vue')
    )
  },

9、自定义指令

  1. 动态指令
<div id="dynamicexample">
  <h3>Scroll down inside this section ↓</h3>
  <p v-pin:[direction]="200">I am pinned onto the page at 200px to the left.</p>
</div>
const app = Vue.createApp({
  data() {
    return {
      direction: 'right'
    }
  }
})

app.directive('pin', {
  mounted(el, binding) {
    el.style.position = 'fixed'
    // binding.arg 是我们传递给指令的参数
    const s = binding.arg || 'top'
    el.style[s] = binding.value + 'px'
  }
})

app.mount('#dynamic-arguments-example')

动态指令的函数简写

app.directive('pin', (el, binding) => {
  el.style.position = 'fixed'
  const s = binding.arg || 'top'
  el.style[s] = binding.value + 'px'
})

vue3后组件可能会有多个根节点。当被应用在一个多根节点的组件上时,指令会被忽略,并且会抛出一个警告。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值