Vue3 常用知识点

522 阅读5分钟

🐜🐜🐜相信很多小伙伴都已经慢慢的接触Vue3.x了吧,Vue2.x近几年都是很多公司经常用的,这次Vue2.x的更新和能很快就会被大多数公司使用,因为Vue3.x的出现提高了运行速度,大大较少了内存等,让我们来了解一下由组合API合成的Vue3.x吧!(^_^)

☀ ☀ ☀

1. 生命周期函数

首先来看一下变化说大不大,说小不小的并且很常用的生命周期函数⬇⬇⬇

Vue2.xVue3
beforeCreatesetup()
createdsetup()
beforeMountonBeforeMount
mountedonMounted
beforeUpdateonBeforeUpdate
updatedonUpdated
beforeDestroyonBeforeUnmount
destroyedonBeforeUnmount
errorCapturedonErrorCaptured

⭐在上面我们可以看到,createdbeforeCreate 这两个生命周期函数在Vue3.x中变成了setup(),在这里我们要注意一点,所有的组合api都要写在setup()这个方法中;beforeDestroy和destroyed变成了onBeforeUnmountonBeforeUnmount用法是相同的,另外新增调试的周期函数onErrorCaptured,在Vue3.x中,这些周期函数都是以组合api的形式出现的,每次使用都要引入,另外也没什么不同的了,使用基本上都是一样的。

image.png image.png

下面我们来看其他组合api的使用方法⬇⬇⬇

2. ref,toRef,reactive,toRefs的区别及使用方法

reactive
  • 根据传入的对象 ,创建返回一个深度响应式对象响应式对象属性值改动,不管层级有多深,都会触发响应式;

  • 并且只能给对象添加响应式,对于值类型,比如StringNumberBooleanSymbol无能为力;

  • return时不可以使用...state方式,否则会变为非响应式对象。 下面我们来看代码:

    <script>
    import { reactive } from 'vue'
    export default {
      name: 'reactivedemo',
      setup () {
    // 响应式对象
    const state = reactive({
      name: '太凉',
      age: 18,
      hobby: ['游泳', '爬山'],
      address: {
        provoince: '北京',
        city: '北京',
        street: '东城区长安街'
      }
    })
    
    // 过3秒后改变
    setTimeout(() => {
      // update1:改变name属性
      state.name = '冰箱太凉'
    
      // update2:深度改变 address属性
      state.address.provoince = '山东省' // 年龄改为30
      state.address.city = '临沂市'
    
      // update3:新增 school属性
      state.school = '清华北大'
    
      // update4:删除 年龄属性
      delete state.age
    
      // update5:数组 添加一项
      state.hobby.push('打豆豆')
    }, 3000)
    return {
     //注意这里不能通过 ...state 方式结构,这样会丢失响应式
      state  
    }
    

    } }

    .demo { text-align: left; width: 600px; margin: 20px auto; }
ref
  • 可以生成 值类型(即基本数据类型) 的响应式数据,对于值类型,比如StringNumberBooleanSymbol等;

  • 给属性绑定可自动获取文本元素;

  • 通过 .value 来修改值(一定要记得加上 .value);若将对象放在ref中则和reactive相同; 下面我们来看代码:

<template>
  <h1>{{ageRef}}</h1>
  <input type="text" ref="inputFous">
</template>

<script lang="ts">
import {defineComponent, ref, onMounted} from 'vue';

export default defineComponent({
  name: 'APP',
  setup() {
    // 生成 `值类型`(即基本数据类型) 的响应式数据
    const ageRef = ref(18)
      setTimeout(() => {
          ageRef.value = 20
      },1500)
    // 特性:可自动获取文本元素
    const inputFous = ref<HTMLElement | null>(null)
    console.log(inputFous)
    onMounted(() => {
      if (inputFous.value) {
        inputFous.value.focus()  //自动获取焦点
      }
    })
    return {
      ageRef,
      inputFous
    }
  }
})
</script>
toRef
  • toRef 可以响应对象 Object ,其针对的是某一个响应式对象( reactive 封装)的属性prop

  • toRef 和对象 Object 两者保持引用关系,即一个改完另外一个也跟着改。

  • toRef 如果用于普通对象(非响应式对象),产出的结果不具备响应式 下面我们来看代码:

toRefs
  • 普通对象里的每一个属性 prop 都对应一个 ref

  • toRefs 和对象 Object 两者保持引用关系,即一个改完另外一个也跟着改 下面我们来看代码:

以上就是处理响应式的数据区别和使用方法。

3. watch和watahEffect区别及使用方法

watch
  • 需要输入监听的数据源,监听多个数据时使用数组‘
  • 只能监听响应式的数据,监听非响应式的数据时使用回调方式;
  • 在监视某个数据属性,对象等时默认第一次不会执行需要;immediate使用
  • 能够获取到新值与旧值(更新前的值)

下面我们来看代码:

<template>
  <fieldset>
    <legend>人员名称</legend>
        姓氏: <input type="text" v-model="obj.surName"/><br>
        名称: <input type="text" v-model="obj.name"/>
  </fieldset>
  <fieldset>
    <legend>人员名称</legend>
    three: <input type="text" v-model="threeNames"/>
  </fieldset>
</template>

<script>
import { defineComponent, reactive, ref, toRefs, watch, watchEffect} from 'vue';
import {defineComponent,onMounted} from 'vue'

export default defineComponent({
  name: 'APP',
  setup() {
    const obj = toRefs({
      surName: 'co',
      name: 'la'
    })

    const threeNames = ref('')

    // 使用回调方式可以监听不是响应式的数据
    // watch([() => obj.surName, () => obj.name, firstNames], {})
    watch(obj, ({surName, name}) => {
      threeNames.value = surName + '_' + name
    }, {
    //默认第一次不会执行
      immediate: true,
      deep: true
    })
    watchEffect(() => {
      const threeName = threeNames.value.split('_')
      obj.surName = threeName[0]
      obj.name = threeName[1]
    })
    return {
      ...obj,
      threeNames
    }
  }
})
</script>
watahEffect
  • 可以监听非响应式的数据,直接使用即可;
  • 在监视某个数据属性,对象等时默认第一次会执行
  • 不能够获取到新值与旧值(更新前的值)

4. computed的使用方法

computed的使用方法和vue2中使用基本相同,除了写法有一点差别,get 和 set 调用也是一样的,下面我们直接来看代码:

    import { ref, computed } from "vue"
    export default{
     setup(){
          const num1 = ref(1)
          const num2 = ref(1)
          let sum = computed(()=>{
               return num1.value + num2.value
          }) 
          let sum = computed(()=>{
              get(){ // num1值改变时触发
                   return this.num1 * 10
              },
              set(value){ // mul值被改变时触发
               this.num1 = value /10
              }
          })
      
    return {
      sum
    }
   }
}

5. props和emit的使用方法

首先,我们来看下父组件传值给子组件,在这里和vue2的很相似,但是接收的时候会有一点差异。

props
父组件:
<template>
<-- 将number传给子组件 -->
   <son :number="number"/>
 </template>

<script lang="ts">
import {defineComponent, ref} from 'vue';
//引入子组件
import son from './son.vue';

export default defineComponent({
  name: 'father',
  //注册组件
  components: {
    son
  },
  setup() {
  //定义 number
    const number = ref(18)

    return {
      number
    }
  }
})
</script>

子组件:
<template>
  <h1>{{ num }}</h1>
</template>

<script lang="ts">
import {defineComponent} from 'vue';

export default defineComponent({
  name: 'son',
  //接收父组件传的number
  // props: ['number'],
  props: {
    number: String
  },
  //注意:在vue3中 setup()方法中会带有两个参数,
  //用来处理props,emits等数据
  setup(props) {
    const num = props.number

    return {
      num
    }
  }
})
</script>

好啦,没有什么太大的差别,接下来让我们看emits的使用方法

emits

差别不大,直接用代码讲解了哈... (^_^) 看下面⬇⬇⬇

父组件:
<template>
  <son @red="red"/>
  <h1 :class="{afx:begin}">我将会变色!!!</h1>
</template>

<script lang="ts">
import {defineComponent, ref, watch} from 'vue';
import son from './son.vue';

export default defineComponent({
  name: 'father',
  components: {
    son
  },
  setup(props, emits) {
    const begin = ref(false)

    const red = (val: boolean) => {
      begin.value = val
    }

    return {
      begin,
      red,
    }
  }
})
</script>

<style lang="less" scoped>
.afx {
  color: #42b983;
}
</style>

子组件:
<template>
  <button @click="open()">变红</button>
</template>

<script lang="ts">
import {defineComponent, ref} from 'vue';

export default defineComponent({
  name: 'son',
  setup(props, emits) {
    let flag = ref(false)

    const open = () => {
      emits.emit('red', flag)
    }

    return {
      open
    }
  }
})
</script>

好啦,以上就是父子之间传值最基本的啦,接下来让我们继续往下看 ☺ ☺ ☺

6. 自定义hook函数

  • Vue3hook函数 相当于 vue2mixin, 不同在与 hooks 是函数
  • Vue3hook函数 可以帮助我们提高代码的复用性, 让我们能在不同的组件中都利用 hooks 函数

hooks函数是单独的文件夹,里面专门存放各种hook函数,项目中用到是直接引用即可 (●ˇ∀ˇ●)。

下面我们来用一个请求接口数据的例子来看下具体使用方法⬇⬇⬇

封装hooks函数实现axious请求

import axios from 'axios'
import {ref} from 'vue';

export default function <T>(url: string) {
    // 加载状态
    const loading = ref(true)
    // 请求成功的数组
    const data = ref<T | null>(null)    //判断类型
    // 错误信息
    const errorMeg = ref('')
    axios.get(url).then(response => {
        loading.value = false
        data.value = response.data
    }).catch(error => {
        loading.value = false
        errorMeg.value = error.message || '请求地址无效 !'
    })
    return {
        loading,
        data,
        errorMeg
    }
}

调用hooks库

<template>
  <h1>成员信息</h1>
  <h1 v-if="loading">正在加载中...</h1>
  <h1 v-else-if="errorMeg">加载失败:{{errorMeg}}</h1>
  <!--  <ul v-else>-->
  <!--    <li>{{ data.id }}</li>-->
  <!--    <li>{{ data.name }}</li>-->
  <!--    <li>{{ data.gender }}</li>-->
  <!--  </ul>-->
  <ul v-for="item in data" v-else>
    <li>id:{{ item.id }}</li>
    <li>name:{{ item.name }}</li>
    <li>gender:{{ item.gender }}</li>
  </ul>
</template>

<script lang="ts">
import {defineComponent, watch} from 'vue';
import useData from '@/hooks/encapsulat_ajax'

interface Address {
  id: number,
  name: string,
  gender: string
}

interface Person {
  id: number,
  name: string,
  gender: string
}

export default defineComponent({
  name: 'index',
  setup() {
    //对象数据  接口自己造的数据(如下图)
    // const {loading, data, errorMeg} = useData<Address>('/data/address.json')
    //数组对象数据  接口自己造的数据(如下图)
    const {loading, data, errorMeg} = useData<Person[]>('/data/person.json')
    watch(data, () => {
      if (data.value) {
        console.log(data.value.length)
      }
    })
    return {
      loading,
      data,
      errorMeg
    }
  }
})
</script>

image.png

image.png

=> 总结:总得来说,新引入的setup语法糖的 目的是简化使用Composition API时冗长的模板代码,也就是让代码更加简洁,阅读性也越高。而在组件中引入并使用自定义hook 自定义hook的作用类似于vue2中的mixin技术 自定义Hook的优势: 很清楚复用功能代码的来源, 更清楚易懂!!!

学习完记得休息一下 O! 😊😊😊