常用 Composition API【VUE3】

二、常用 Composition API

7. 计算属性与监视

7.1 computed函数

  • 与Vue2.x中computed配置功能一致
  • 写法
<template>
    <h1>一个人的信息</h1>
    姓:<input type="text" v-model="person.firstName">
    <br>
    <br>
    名:<input type="text" v-model="person.lastName">
    <br>
    <br>
    <span>全名:{{ person.fullName }}</span>
    <br>
    全名:<input type="text" v-model="person.fullName">
  </template>
  
  <script>
  import {reactive, computed} from 'vue'
  export default {
    name: 'Demo',
    /* computed: {
        fullName(){
            return this.person.firstName + '-' + this.person.lastName
        }
    }, */

    //数据
    setup(){
      //数据
      let person = reactive({
        firstName: '张',
        lastName: '三',
      })

      //计算属性——简写(没有考虑计算属性被修改的情况)
      /* person.fullName = computed(() => {
        return person.firstName + '-' + person.lastName
      }) */

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

      //返回一个对象(常用)
      return {
        person,
      }
    }
  }
  </script>

7.2 watch函数

  • 与Vue2.x中watch配置功能一致
  • 两个小“坑”:
    • 监视reactive定义的响应式数据时:oldValue无法正确获取、强制开启了深度监视(deep配置失效)。
    • 监视reactive定义的响应式数据中某个属性时:deep配置有效。
<template>
    <h2>当前求和为:{{ sum }}</h2>
    <button @click="sum++">点我+1</button>
    <hr>
    <h2>当前的信息为:{{ msg }}</h2>
    <button @click="msg+='!'">修改信息</button>
    <hr>
    <h2>姓名:{{ person.name }}</h2>
    <h2>年龄:{{ person.age }}</h2>
    <h2>薪资:{{ person.job.j1.salary }}</h2>
    <button @click="person.name += '~'">修改姓名</button>
    <button @click="person.age++ ">增长年龄</button>
    <button @click="person.job.j1.salary++">涨薪</button>
  </template>
  
  <script>
  import {ref, reactive ,watch} from 'vue'
  export default {
    name: 'Demo',
    //Vue2
    //watch: {
        //简写
        /* sum(newValue, oldValue){
            console.log('sum的值变化了!', newValue, oldValue);
        } */
        //完整
        /* sum: {
            immediate: true,
            deep: true,
            handler(newValue, oldValue){
                console.log('sum的值变化了!', newValue, oldValue);
            }
        } */

    //},
    //数据
    setup(){
      //数据
      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('person变化了', newValue, oldValue);
      })

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

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

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

7.3 watchEffect函数

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

8. 生命周期

常用 Composition API【VUE3】_第1张图片

  • Vue3.0中可以继续使用Vue2.x中的生命周期钩子,但有有两个被更名:
    • beforeDestroy改名为 beforeUnmount
    • destroyed改名为 unmounted
  • Vue3.0也提供了 Composition API 形式的生命周期钩子,与Vue2.x中钩子对应关系如下:
    • beforeCreate===>setup()
    • created=======>setup()
    • beforeMount ===>onBeforeMount
    • mounted=======>onMounted
    • beforeUpdate===>onBeforeUpdate
    • updated =======>onUpdated
    • beforeUnmount ==>onBeforeUnmount
    • unmounted =====>onUnmounted
<template>
    <h2>当前求和为:{{ sum }}</h2>
    <button @click="sum++">点我+1</button>
  </template>
  
  <script>
  import {onBeforeMount, ref, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted} from 'vue'
  export default {
    name: 'Demo',
    //通过配置项的形式使用生命周期钩子
    beforeCreate(){
      console.log('---beforeCreate---');
    },
    created(){
      console.log('---created---');
    },
    beforeMount(){
      console.log('---beforeMount---');
    },
    mounted(){
      console.log('---mounted---');
    },
    beforeUpdate(){
      console.log('---beforeUpdate---');
    },
    updated(){
      console.log('---updated---');
    },
    beforeUnmount() {
      console.log('---beforeUnmount---');
    },
    unmounted(){
      console.log('---unmounted---');
    },
    //数据
    setup(){
      console.log('---setup---');
      //数据
      let sum = ref(0)

      //通过组合式API的形式去使用生命周期钩子
      onBeforeMount(() => {
        console.log('---onBeforeMount---');
      })
      onMounted(() => {
        console.log('---onMounted---');
      })
      onBeforeUpdate(() => {
        console.log('---onBeforeUpdate---');
      })
      onUpdated(() => {
        console.log('---onUpdated---');
      })
      onBeforeUnmount(() => {
        console.log('---onBeforeUnmount---');
      })
      onUnmounted(() => {
        console.log('---onUnmounted---');
      })
      
      //返回一个对象(常用)
      return {
        sum,
      }
    }
  }
  </script>
  
  

9. 自定义hook函数

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

usePoint.js

import { reactive, onMounted, onBeforeUnmount } from 'vue'

export default function (){
    //实现鼠标打点的相关数据
    let point = reactive({
        x: 0,
        y: 0
      })
      
    //实现鼠标打点的方法
      function savePoint(e){
          point.x = e.pageX
          point.y = e.pageY
          console.log(e.pageX, e.pageY);
        }
    //实现鼠标打点的相关的生命周期钩子
      onMounted(() => {
        window.addEventListener('click', savePoint)
      })

      onBeforeUnmount(() => {
        window.removeEventListener('click', savePoint)
      })

      return point

}

App.vue

<template>
  <button @click="isShowDemo = !isShowDemo">切换隐藏/显示</button>
  <Demo v-if="isShowDemo"></Demo>
  <hr>
  <Test></Test>
</template>

<script>
import {ref} from 'vue'
import Demo from './components/Demo.vue'
import Test from './components/Test.vue'
export default {
  name: 'App',
  components: {Demo, Test},
  setup(){
    let isShowDemo = ref(true)
    return {isShowDemo}
  }
}
</script>

components/Demo.vue

<template>
    <h2>当前求和为:{{ sum }}</h2>
    <button @click="sum++">点我+1</button>
    <hr>
    <h2>当前点击时鼠标的坐标为: x: {{point.x}}, y: {{point.y}}</h2>
  </template>
  
  <script>
  import { ref } from 'vue'
  import usePoint from '../hooks/usePoint'
  export default {
    name: 'Demo',

    //数据
    setup(){
      //数据
      let sum = ref(0)
      let point = usePoint()
      
      //返回一个对象(常用)
      return {
        sum,
        point
      }
    }
  }
  </script>

10. toRef

  • 作用:创建一个 ref 对象,其value值指向另一个对象中的某个属性。

  • 语法:const name = toRef(person,'name')

  • 应用: 要将响应式对象中的某个属性单独提供给外部使用时。

  • 扩展:toRefstoRef功能一致,但可以批量创建多个 ref 对象,语法:toRefs(person)

APP.vue

<template>
  <h2>姓名:{{ name }}</h2>
  <h2>年龄:{{ age }}</h2>
  <h2>薪资:{{ job.j1.salary }}</h2>
  <button @click="name += '~'">修改姓名</button>
  <button @click="age++ ">增长年龄</button>
  <button @click="job.j1.salary++">涨薪</button>
</template>

<script>
import {ref, reactive, toRef, toRefs} from 'vue'
export default {
  name: 'Demo',
  //数据
  setup(){
    //数据
    let person = reactive({
      name: '张三',
      age: 18,
      job: {
          j1: {
              salary: 20
          }
      }
    })
    
    // const name1 = person.name
    // console.log('%%%', name1);

    // const name2 = toRef(person, 'name')
    // console.log('###', name2);

    const x = toRefs(person)
    console.log('@@@', x);

    //返回一个对象(常用)
    return {
      // name: toRef(person, 'name'),
      // age: toRef(person, 'age'),
      // salary: toRef(person.job.j1, 'salary')
      ...toRefs(person)
    }
  }
}
</script>

你可能感兴趣的:(javascript,前端,vue.js)