🐜🐜🐜相信很多小伙伴都已经慢慢的接触Vue3.x了吧,Vue2.x近几年都是很多公司经常用的,这次Vue2.x的更新和能很快就会被大多数公司使用,因为Vue3.x的出现提高了运行速度,大大较少了内存等,让我们来了解一下由组合API合成的Vue3.x吧!(^_^)
☀ ☀ ☀
1. 生命周期函数
首先来看一下变化说大不大,说小不小的并且很常用的生命周期函数⬇⬇⬇
| Vue2.x | Vue3 |
|---|---|
| beforeCreate | setup() |
| created | setup() |
| beforeMount | onBeforeMount |
| mounted | onMounted |
| beforeUpdate | onBeforeUpdate |
| updated | onUpdated |
| beforeDestroy | onBeforeUnmount |
| destroyed | onBeforeUnmount |
| errorCaptured | onErrorCaptured |
⭐在上面我们可以看到,created和beforeCreate 这两个生命周期函数在Vue3.x中变成了setup(),在这里我们要注意一点,所有的组合api都要写在setup()这个方法中;beforeDestroy和destroyed变成了onBeforeUnmount和onBeforeUnmount用法是相同的,另外新增调试的周期函数onErrorCaptured,在Vue3.x中,这些周期函数都是以组合api的形式出现的,每次使用都要引入,另外也没什么不同的了,使用基本上都是一样的。
下面我们来看其他组合api的使用方法⬇⬇⬇
2. ref,toRef,reactive,toRefs的区别及使用方法
reactive
-
根据传入的对象 ,创建返回一个深度响应式对象。响应式对象属性值改动,不管层级有多深,都会触发响应式;
-
并且只能给对象添加响应式,对于值类型,比如
String,Number,Boolean,Symbol无能为力; -
在
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
-
可以生成
值类型(即基本数据类型) 的响应式数据,对于值类型,比如String,Number,Boolean,Symbol等; -
给属性绑定可自动获取文本元素;
-
通过
.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函数
Vue3的hook函数相当于vue2的mixin, 不同在与hooks是函数Vue3的hook函数可以帮助我们提高代码的复用性, 让我们能在不同的组件中都利用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>
=> 总结:总得来说,新引入的setup语法糖的 目的是简化使用Composition API时冗长的模板代码,也就是让代码更加简洁,阅读性也越高。而在组件中引入并使用自定义hook 自定义hook的作用类似于vue2中的mixin技术 自定义Hook的优势: 很清楚复用功能代码的来源, 更清楚易懂!!!
学习完记得休息一下 O! 😊😊😊