【14.0】Vue3之函数
【一】setup函数
setup
函数是用来替代Vue 2中的data
、methods
等选项的。- 它是一个特殊的函数,它会在组件实例创建之前被调用,用于初始化组件的状态和行为
setup
函数可以定义变量和函数,并且可以使用ES6的let
和const
语法来声明变量。- 在
setup
函数内部定义的变量和函数都是局部的,不会暴露给模板或其他组件 - 可以定义函数,可以定义匿名函数
- 在
- 如果想要在模板中使用
setup
函数内部定义的变量,必须将其通过return
语句返回,才可以在模板中使用它们 - 在
setup
函数内部定义的变量默认不具有响应性。如果希望某个变量具有响应性,需要使用ref()
函数将其包裹起来。- 在示例代码中,
age
没有使用ref()
包裹,因此在addAge
函数中对age
的修改不会触发组件重新渲染
- 在示例代码中,
setup
函数内部可以使用data
、methods
等选项中定义的属性和方法- 但是
setup
函数会先于这些选项执行,所以如果在data
中定义了与setup
中相同的变量,setup
中的定义会覆盖它。 - 同样地,如果在模板中使用某个变量或方法,优先使用
setup
中的定义
- 但是
setup
函数是在组件实例创建之前执行的- 因此在
setup
函数内部无法访问到this
,也不能使用this
关键字。 - 如果需要获取组件实例,请使用
getCurrentInstance()
函数
- 因此在
<script>
export default {
// Vue2中的写法
name: "HomeView",
// Vue2在 data 中定义变量
data() {
return {}
},
methods: {},
// Vue3将所有内容写在 setup 函数内
setup() {
// var: ES5老语法(不建议使用) let: ES6新语法 const: 定义常量
// (1)定义变量和函数 ----(不会触发响应式)
let name = "dream"
let age = 19
const addAge = () => {
age += 1;
alert(age)
}
// setup 必须将变量 return 出去才能看到定义的 值
return {name, age, addAge}
}
}
</script>
【二】ref函数
- 在Vue 3中,
ref
函数是用来包裹变量,以实现响应式的效果。- 它可以使普通的JavaScript变量变成响应式的数据,并且可以通过
.value
来访问和修改内部的值
- 它可以使普通的JavaScript变量变成响应式的数据,并且可以通过
- 导入
ref
函数:- 在使用
ref
函数之前,需要从Vue库中导入它。 - 在示例代码中使用了
import {ref} from "vue"
来导入ref
函数。
- 在使用
- 使用
ref
函数包裹变量:- 在示例代码中,
name
和age
都被用ref
函数包裹起来,变成了响应式的数据。 - 包裹后的变量在
ref
函数内部由一个对象进行包装,该对象具有一个.value
属性,用于访问和修改包裹的变量值。
- 在示例代码中,
- 访问响应式变量的值:
- 在模板中,可以直接访问
name
和age
这样的响应式变量。 - 在示例代码中,可以在模板中直接使用
{{ name }}
和{{ age }}
来渲染它们的值。
- 在模板中,可以直接访问
- 修改响应式变量的值:
- 在示例代码中,
addAge
函数用于增加age
的值。 - 由于
age
是通过ref
函数包裹的,所以在修改它的值时,需要使用age.value
来访问和修改其内部的真实值。
- 在示例代码中,
- 注意事项:
- 在使用
ref
函数包裹变量时,尽量在组件的setup
函数内部进行。- 这样可以确保变量的响应式特性在组件的整个生命周期中有效。
ref
函数只会对变量的值进行响应式处理,并不会将变量的所有属性都变为响应式。- 如果需要将对象、数组等复杂类型的属性也变为响应式,可以使用
reactive
函数。
- 如果需要将对象、数组等复杂类型的属性也变为响应式,可以使用
- 在使用
<script>
// 导入ref函数
import {ref} from "vue";
export default {
// Vue3将所有内容写在 setup 函数内
setup() {
// var: ES5老语法(不建议使用) let: ES6新语法 const: 定义常量
// (2)定义变量和函数 ----(会触发响应式)
// 用 ref 函数将变量值包裹起来
let name = ref("dream")
let age = ref(19)
const addAge = () => {
// 如果修改变量的值,需要对象.value才能修改
age.value += 1;
}
const clickChange = () => {
name.value = "baby"
}
// setup 必须将变量 return 出去才能看到定义的 值
return {name, age, addAge,clickChange}
}
}
</script>
【三】data/methods
setup
函数内部可以使用data
、methods
等选项中定义的属性和方法
- 但是
setup
函数会先于这些选项执行,所以如果在data
中定义了与setup
中相同的变量,setup
中的定义会覆盖它。 - 同样地,如果在模板中使用某个变量或方法,优先使用
setup
中的定义
【四】reactive函数
-
reactive函数是Vue框架中的一个响应式函数,用于定义对象(或数组)类型的数据。
- 与ref函数不同,ref函数用于定义基本类型数据。
-
从定义数据角度对比:
- ref用来定义:基本类型数据
- reactive用来定义:对象(或数组)类型数据
-
从原理角度对比:
- ref通过Object.defineProperty()的get与set来实现响应式(数据劫持)。
- reactive通过使用Proxy来实现响应式(数据劫持), 并通过Reflect操作源对象内部的数据。
-
从使用角度对比:
- ref定义的数据:操作数据需要.value,读取数据时模板中直接读取不需要.value。
- reactive定义的数据:操作数据与读取数据:均不需要.value。
<script>
// 导入ref函数
import {ref} from "vue";
// 导入reactive函数
import {reactive} from "vue";
export default {
name: "HomeView",
setup() {
// (1)要想让变量有响应式,要用 ref 包裹,包裹的都是字符串/数字/布尔
// 使用ref定义基本类型数据
let count = ref(0);
// (2)如果要想让对象有响应式,需要用 reactive
// 使用reactive定义对象类型数据
let userInfo = reactive({"name": "dream", "age": 18, "hobby": "music"});
const addCount = () => {
// 在操作基本类型数据时,需要使用.value来获取或修改数据
count.value += 1;
}
const addAge = () => {
// 在操作reactive定义的对象时,可以直接当做对象使用
userInfo.age += 1;
}
return {count, userInfo, addCount, addAge};
}
}
</script>
【五】计算/监听属性
- 属性是响应式的变量,可以在组件中被使用和观察变化。
- Vue 3提供了不同类型的属性,包括普通变量、对象和多个变量
【1】监听属性
- 监听属性之普通变量
<script>
// 导入ref函数
import {ref, reactive, watch} from "vue";
// 导入reactive函数
export default {
name: "HomeView",
setup() {
// 原来的计算属性和监听属性,通过配置项api配置
// 现在使用组合式api后都写在 setup 内
// (1)监听属性之普通变量
let name = ref("蚩梦")
const clickChange = () => {
name.value = "晓萌"
}
watch(name, (newValue, oldValue) => {
// 原来的值
console.log(oldValue)
// 修改后的新值
console.log(newValue)
console.log('name 真的变了 ... ')
})
return {name, clickChange}
}
}
</script>
- 监听属性之对象
<script>
// 导入ref函数
import {ref, reactive, watch} from "vue";
// 导入reactive函数
export default {
name: "HomeView",
setup() {
// 原来的计算属性和监听属性,通过配置项api配置
// 现在使用组合式api后都写在 setup 内
// (2)监听属性之对象
let info = reactive({"name": "dream", "age": 18, "hobby": "music"})
const clickChangeInfo = () => {
info.name = "萌萌"
}
// 要写成函数形式
watch(() => info.name, (newValue, oldValue) => {
// 原来的值
console.log(oldValue)
// 修改后的新值
console.log(newValue)
console.log('info中的name变了')
})
return {info,clickChangeInfo}
}
}
</script>
- 监听属性之监听多个变量
<script>
// 导入ref函数
import {ref, reactive, watch} from "vue";
// 导入reactive函数
export default {
name: "HomeView",
setup() {
// 原来的计算属性和监听属性,通过配置项api配置
// 现在使用组合式api后都写在 setup 内
// (3)监听属性之监听多个变量
let width = ref(100)
let height_name = ref('高度')
const clickChangeWidth = () => {
width.value = 9999
}
const clickChangeHeight_name = () => {
height_name.value = "新高度"
}
watch([width, height_name], (newValue, oldValue) => {
console.log('旧值',oldValue)
console.log('新值',newValue)
console.log('width/height_name发生了变化')
})
return {width, height_name, clickChangeWidth, clickChangeHeight_name}
}
}
- 页面展示
<template>
<div>
<h1>这是一个首页</h1>
名字是:>>>>{{ name }}
<br>
<button @click="clickChange">点我换名字</button>
<br>
对象中的名字是:>>>>{{ info.name }}
<br>
<button @click="clickChangeInfo">点我换名字</button>
<br>
宽度是:>>>>{{ width }}
高度是:>>>>{{ height_name }}
<br>
<button @click="clickChangeWidth">点我换宽度</button>
<br>
<button @click="clickChangeHeight_name">点我换高度</button>
<br>
</div>
</template>
【2】计算属性
- 计算属性 使用computed ,只有取值触发或取值赋值触发函数
- 计算属性可以取值
<script>
// 导入ref函数
import {ref, reactive, watch, computed} from "vue";
// 导入reactive函数
export default {
name: "HomeView",
setup() {
// 原来的计算属性和监听属性,通过配置项api配置
// 现在使用组合式api后都写在 setup 内
let name = ref("蚩梦")
// 计算属性可以取值
let newName = computed(() => {
return name.value + "NB"
})
return {name, newName}
}
}
</script>
- 计算属性可以修改值
<script>
// 导入ref函数
import {ref, reactive, watch, computed} from "vue";
// 导入reactive函数
export default {
name: "HomeView",
setup() {
// 原来的计算属性和监听属性,通过配置项api配置
// 现在使用组合式api后都写在 setup 内
let name = ref("蚩梦")
// 计算属性可以修改值
let newName = computed({
get() {
// 只要计算属性 取值就会触发
return name.value + '_dr'
},
set(value) {
// 只要计算属性 值发生变化就会触发
// 只要 newName 发生变化 , name 也应该变化
console.log('旧值:>>>', name.value)
let result = value.split('_')
name.value = result[0]
console.log('新值:>>>', newName.value)
}
})
return {name, newName}
}
}
</script>
- 页面展示
<template>
<div>
<h1>这是一个首页</h1>
<br>
旧值:>>><input type="text" v-model="name">
<br>
<h2>输入的值 ----> {{ name }}</h2>
<br>
<h2>监听到的新值 ----> {{ newName }}</h2>
<br>
新输入的新值:>>><input type="text" v-model="newName">
</div>
</template>
【六】生命周期钩子
【一】介绍
- vue3不建议使用 配置项api,把所有代码都写在setup函数中
- 以后没有:destory这俩了,换成了unmounted
- 可以写配置项api
beforeCreate
created
beforeMoun
mounted
beforeUpdate
updated
beforeUnmount
unmounted
- 组合式api
beforeCreate===>setup()
created=======>setup()
beforeMount ===>onBeforeMount
mounted=======>onMounted
beforeUpdate===>onBeforeUpdate
updated =======>onUpdated
beforeUnmount ==>onBeforeUnmount
unmounted =====>onUnmounted
-
beforeCreate -> setup函数:
- 在Vue 2中,beforeCreate钩子用于在实例被创建之前执行逻辑。
- 在Vue 3中,可以将beforeCreate钩子中的代码移到setup函数中执行。setup函数会在组件实例创建之前执行,并且返回响应式状态和事件处理函数等。
-
created -> setup函数:
- 在Vue 2中,created钩子用于在实例创建完成后执行逻辑。
- 在Vue 3中,可以将created钩子中的代码移到setup函数中执行。
-
beforeMount -> onBeforeMount:
- 在Vue 2中,beforeMount钩子在挂载之前执行。
- 在Vue 3中,可以使用onBeforeMount函数来替代beforeMount钩子。该函数会在组件挂载之前执行。
-
mounted -> onMounted:
- 在Vue 2中,mounted钩子在挂载完成后执行。
-onMounted函数来替代mounted钩子。该函数会在组件挂载完成后执行。
- 在Vue 2中,mounted钩子在挂载完成后执行。
-
beforeUpdate -> onBeforeUpdate:
- 在Vue 2中,beforeUpdate钩子在数据更新之前执行。
- 在Vue 3中,可以使用onBeforeUpdate函数来替代beforeUpdated:
- 在Vue 2中,updated钩子在数据更新完成后执行。
- 在Vue 3中,可以使用onUpdated函数来替代updated钩子。该函数会在组件更新完成后执行。
-
beforeUnmount -> onBeforeUnmount:
- 在Vue 2中,beforeUnmount钩子在组件卸载之前执行。
- 在Vue 3中,可以使用onBeforeUnmount函数来替代beforeUnmount钩子。该函数会在组件卸载之前执行。
-
unmounted -> onUnmounted:
- 在Vue 2中,unmounted钩子在组件卸载完成后执行。
- 在Vue 3中,可以使用onUnmounted函数来替代unmounted钩子。该函数会在组件卸载完成后执行。
【二】示例
src\views\HomeView.vue
<script setup>
</script>
<template>
<div>
<h1>这是一个首页</h1>
<br>
<h2>组件HelloWorld</h2>
<br>
<button @click="showFunc">点击显示</button>
<br>
<HelloWorld v-if="show"></HelloWorld>
</div>
</template>
<script>
import HelloWorld from "@/components/HelloWorld.vue";
// 导入ref函数
import {ref, reactive, watch, computed} from "vue";
// 导入reactive函数
export default {
name: "HomeView",
setup() {
let show = ref(true);
const showFunc = () => {
show.value = !show.value
}
return {show, showFunc}
},
components: {
HelloWorld,
},
}
</script>
src\components\HelloWorld.vue
<script setup>
</script>
<template>
<div class="hello">
<h1>HelloWorld页面</h1>
</div>
</template>
<script>
import { onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted, reactive } from 'vue';
export default {
name: "HelloWorld",
// 生命周期钩子函数
// beforeCreate===>setup()
// created=======>setup()
// beforeMount ===>onBeforeMount
// mounted=======>onMounted
// beforeUpdate===>onBeforeUpdate
// updated =======>onUpdated
// beforeUnmount ==>onBeforeUnmount
// unmounted =====>onUnmounted
setup() {
// 在beforeCreate钩子中的逻辑可放置于setup函数中
const data = reactive({
message: 'Hello Vue 3!',
count: 0
});
// created钩子中的逻辑也可以放置于setup函数中
console.log('组件已创建');
// beforeMount -> onBeforeMount
onBeforeMount(() => {
console.log('组件挂载前');
});
// mounted -> onMounted
onMounted(() => {
console.log('组件已挂载');
});
// beforeUpdate -> onBeforeUpdate
onBeforeUpdate(() => {
console.log('组件更新前');
});
// updated -> onUpdated
onUpdated(() => {
console.log('组件已更新');
});
// beforeUnmount -> onBeforeUnmount
onBeforeUnmount(() => {
console.log('组件卸载前');
});
// unmounted -> onUnmounted
onUnmounted(() => {
console.log('组件已卸载');
});
return {
data
};
}
}
</script>
<style scoped>
</style>
【七】toRef
- ...{对象}---> 相当于解压
- 在setup函数中return时,使用return
- 以后在templte中直接使用内层的变量即可
<script setup>
</script>
<template>
<div>
<h1>这是一个首页</h1>
<!-- <br>-->
<!-- {{ userInfo }}-->
name ----- > {{name}}
<br>
age -----> {{ age}}
<br>
<button @click="clickImg">点我看美女</button>
</div>
</template>
<script>
// 导入ref函数
import {ref, reactive, toRefs} from "vue";
// 导入reactive函数
export default {
name: "HomeView",
setup() {
let userInfo = reactive({"name": "蚩梦", "age": 19})
const clickImg = () => {
alert("美女")
}
// 原来的写法
// return {userInfo,clickImg}
// 高级写法
// 等同于 {name:data.name,age:data.age}
return {...toRefs(userInfo), clickImg}
},
}
</script>
【七】<script setup>
【1】详解
- 在Vue 3中,
<script setup>
是一个新的语法糖,用于编写组件的逻辑部分。- 它可以帮助我们更简洁地编写组件,并且提供了一些额外的好处。
- 使用
<script setup>
有以下几个特点和注意事项:
(1)无需显式导入Vue函数:
- 在
<script setup>
中,你无需显式导入Vue函数,所有的基础选项(如name
、components
等)会自动绑定到组件上。
(2)变量声明和初始化
- 在
<script setup>
中,你可以直接使用JavaScript的变量声明和初始化语法(如let
,const
,var
),无需使用return
将其暴露给组件模板。 - 除了变量声明,也可以直接在响应式对象中进行属性的声明和初始化。
(3)模板中使用变量
- 在模板中,你可以直接使用
<script setup>
中声明的变量,无需通过this
或其他的变量访问方式。 - 在非响应式的数据上,可以通过直接引用变量名来获取数据。
- 在响应式的数据上,需要使用
ref
或toRefs
函数将其转换为响应式引用,以便在模板中使用。 - 使用
ref
或toRefs
时,可以通过解构赋值将引用的属性直接暴露给模板。
(4)事件处理
- 在
<script setup>
中,你可以直接声明和使用函数作为事件处理程序(如点击事件、表单提交等)。 - 在模板中,可以通过
@
或v-on:
指令绑定到声明的函数。
(4)生命周期钩子和侦听器
- 你可以在
<script setup>
中直接使用生命周期钩子函数 (onMounted
,onUpdated
等) 和侦听器 (watch
,watchEffect
等)。
(5)小结
- 使用
<script setup>
的好处包括了更简洁的代码、更直观的数据访问方式以及更好的性能优化。- 它使得编写组件变得更加清晰和高效,并且可以更好地与TypeScript等静态类型语言集成。
- 需要注意的是,
<script setup>
目前还处于实验阶段,并且需要配合Vue的新编译器(vue-template-compiler@^3.2.0)进行使用。- 此外,在使用
<script setup>
时,一些高级用例和特性可能会有一些限制,需要进行额外的学习和了解。
- 此外,在使用
【2】示例
<script setup>
表示,这个script里的所有东西是setup函数,原来写在setup中的,现在顶格写即可
<script setup>
import {ref, toRefs} from 'vue'
import HelloWorld from '@/components/HelloWorld.vue'
let name = ref('dream')
const handelClick = () => {
name.value = '蚩梦'
}
// watch,computed
// 生命周期钩子
// 组件导入,自动注册
// 不需要return
</script>
本文来自博客园,作者:Chimengmeng,转载请注明原文链接:https://www.cnblogs.com/dream-ze/p/17610532.html