Vue3 组合式API
1.入口
- 创建实例时,配置setup方法,然后其内部书写组合式API代码,通过组合式API生产的数据和返回,需要暴漏出去才能给HTML使用
<script>
//组合式(解构赋值)
const {createApp,ref} = Vue
var app = Vue.createApp({
//所有的代码写入到steup方法中
setup(){
//创建响应式数据
const title = ref('实例2')
function modifyTitle(){
//在 JavaScript 中需要 .value
title.value = "实例2被修改"
}
//返回定义的数据和方法
return {
title,
modifyTitle
}
}
})
app.mount('#app2')
</script>
- 单文件组件:将setup声明写到script标签中,然后直接组合式API代码
<template>
<div>
<h1>{{ title }}</h1>
</div>
</template>
<script setup>
import { ref } from 'vue'
const title = ref("组件标题")
</script>
<style scoped>
</style>
2.ref()和reactive()
- 官方推荐使用ref()函数来声明响应式状态,可以传入支持传入简单数据和引用类型的数据,返回一个数据代理对象。通过对象的value属性读取数值(再模版中使用时可以忽略value属性)
<h2>{{title}}</h2>
<h3>{{person.name}} - {{person.age}}</h3>
const title = ref('实例2')
const person = ref({
name:"张三", age: 20
})
- Ref 会使它的值具有深层响应性,传入对象或者数组这种应用类型的数据时,修改对象属性或者数组子元素都可以触发视图更新
const person = ref({
name:"张三", age: 20
})
const list = ref([1,2,3])
function modifyTitle(){
//在 JavaScript 中需要 .value
person.value.age++
list.value[0] = 5
}
- reactive() 返回的是一个原始对象的 Proxy,所以他只接受对象类型的数据 (对象、数组和如 Map、Set 这样的集合类型),通过他创建的数据访问时无需通过value属性
const person2 = reactive({
name:"李四", age: 18
})
const list = reactive([1,2,3])
function modifyTitle(){
person2.age++
list[0] = 5
}
- ref和reactive底层都是调用Proxy()来创建响应式数据,因为Proxy()不支持简单数据,所以ref会对传入的数据用对象进行包裹,用value来存放传入原数据,这样再调用Proxy()就可以返回响应式数据,正因为多了一层包裹,所以他支持简单数据类型而reactive不支持,也正因为如此,所以ref返回的数据需要用value进行操作
- 打印对象:
const title = ref('实例2')
const person = ref({
name:"张三", age: 20
})
const list = reactive({
name:"张三", age: 20
})
- 嵌套调用:当ref嵌套到reactive内部使用时,会涉及到ref的解包机制,平时估计用不上,使用时再查看文档
3.计算属性 computed
- 通过computed()来创建并返回一个代理对象
<body>
<div id="app" v-cloak>
<div class="form-group">
<label>姓:</label>
<input type="text" v-model="person.firstName" class="form-control" placeholder="请输入姓">
</div>
<div class="form-group">
<label>名:</label>
<input type="text" v-model="person.lastName" class="form-control" placeholder="请输入名">
</div>
<div class="form-group">
<label>姓名:</label>
<h2>{{fullName}}</h2>
</div>
</div>
</body>
<script>
//组合式(解构赋值)
const {createApp, ref, reactive,computed} = Vue
var app = Vue.createApp({
//所有的代码写入到steup方法中
setup(){
const person = ref({
firstName: "",
lastName: ""
})
const fullName = computed(()=>{
return person.value.firstName + person.value.lastName
})
//返回定义的数据和方法
return {
person,
fullName
}
}
})
app.mount('#app')
</script>
4.监听器 watch
- 通过watch()来监听数据变化,并执行对应的回调,参数一为需要监听的响应式数据(同时监听多个数据用数组进行包裹),参数二为需要执行的回调函数
<body>
<div id="app" v-cloak>
<input type="text" v-model="title">
</div>
</body>
<script>
//组合式(解构赋值)
const {createApp, ref, reactive,watch} = Vue
var app = Vue.createApp({
//所有的代码写入到steup方法中
setup(){
const title = ref("测试")
//注册监听器
watch(title,(newValue, oldValue)=>{
console.log('title发送变化,最新值为',title.value)
})
//返回定义的数据和方法
return {
title
}
}
})
app.mount('#app')
</script>
- 深度监听:如果监听对象是复杂类型的数据,例如对象,默认不会监听其内部的变化,需要配置deep->true
//注册监听器
watch(person,(newValue, oldValue)=>{
console.log('person发生变化,最新值为',person.value)
},{
deep: true
})
//监听内部某个属性
watch(()=> person.value.age,(newValue, oldValue)=>{
console.log('person.age发生变化,最新值为',person.value.age)
})
- 其他配置:一次性监听(once: true),即时回调(immediate: true),触发时机(flush: 'post'->Dom更新后,flush: 'sync'->Dom更新前,默认)
- watchEffect(): 和计算属性类似,自动识别回调中的依赖对象作为监听,发生改变则触发回调,传入的回调会立即执行一次
<body>
<div id="app" v-cloak>
<input type="text" v-model="name">
<input type="number" v-model="age">
</div>
</body>
<script>
//组合式(解构赋值)
const {createApp, ref, reactive,watchEffect} = Vue
var app = Vue.createApp({
//所有的代码写入到steup方法中
setup(){
const name = ref("张三")
const age = ref(20)
//注册监听器
watchEffect(()=>{
var person = {name: name.value,age:age.value}
console.log('person发生变化',name.value,age.value)
})
//返回定义的数据和方法
return {
name,age
}
}
})
app.mount('#app')
</script>
5.组件数据交互
- 父->子:通过defineProps()方法来定义要接收的参数,这些定义的参数就可以使用了,提供数组语法和对象语法(二选一)
<script setup lang="ts">
//声明要接收的字段,(数组语法,提供属性名即可)
//defineProps(['msg','num'])
//声明要接收的字段,(对象语法,可以限制属性值的类型)
const props = defineProps({
msg: String,
num: Number
})
</script>
- 子->父:用法与vue2.x一致,不过在setup作用域中,需要使用 defineEmits() 对事件进行注册,然后使用返回的emit对象触发事件
<script setup lang="ts">
//声明自定义事件
const emit = defineEmits(['sayHello'])
//触发事件
const handleSayHello = ()=>{
emit('sayHello','someone')
}
</script>
- 父->后代:通过依赖注入的形式,让所有后代组件都可以访问父组件的数据
//全局提供,所有组件都可以使用
import { createApp } from 'vue'
const app = createApp({})
app.provide()
<script setup lang="ts">
//组件提供,只能给后代组件使用
import { ref, provide } from 'vue'
//将数据暴漏给后代组件(参数一:名称,参数二:值,可以是任意类型,包括响应式的状态)
provide('home_title',"Home title")
provide('sayHello',()=>{
console.log("sayHello define in Home")
})
const num = ref(100)
//暴漏ref
provide('home_num', num)
</script>
<script setup lang="ts">
//接收方
import { inject } from 'vue'
//接收祖先组件暴漏的数据(注入)
const home_title = inject('home_title')
const sayHello = inject('sayHello')
const home_num = inject('home_num')
console.log('home_title',home_title)
console.log('sayHello',sayHello)
console.log('home_num',home_num)
//不确定,或者不存在的值给个默认值
const _unknown = inject('_unknown',null)
console.log('_unknown',_unknown)
const setNum = () => {
//不推荐更改祖先数据,如果需要,最好让祖先组件暴漏一个转码修改数据的办法
home_num.value++
}
</script>
6.模版引用
- 通过ref访问Dom:给Dom挂载一个ref属性,值为ref(null)返回的对象,则可通过这个ref对象直接访问dom
<body>
<div id="app" v-cloak>
<h2 ref="h2">{{title}}</h2>
</div>
</body>
<script>
//组合式(解构赋值)
const {createApp, ref, reactive,onMounted} = Vue
var app = Vue.createApp({
//所有的代码写入到steup方法中
setup(){
const title = ref("测试")
const h2 = ref()
onMounted(()=>{
//onMounted 测试
console.log('onMounted',title.value)
console.log(h2.value)
})
//返回定义的数据和方法
return {
title,h2
}
}
})
app.mount('#app')
</script>
- 在使用了 script setup 的组件是默认私有的,一个父组件无法访问到一个使用了 script setup 的子组件中的任何东西,除非子组件在其中通过 defineExpose 宏显式暴露
<script setup>
import { ref } from 'vue'
const a = 1
const b = ref(2)
// 像 defineExpose 这样的编译器宏不需要导入
defineExpose({
a,
b
})
</script>
7.生命周期
- 通过暴漏出来的API,传入生命周期函数,在不同阶段执行对应的代码
<script>
//组合式(解构赋值)
const {createApp, ref, reactive,onMounted} = Vue
var app = Vue.createApp({
//所有的代码写入到steup方法中
setup(){
const title = ref("测试")
onMounted(()=>{
//onMounted 测试
console.log('onMounted',title.value)
})
//返回定义的数据和方法
return {
title,
}
}
})
app.mount('#app')
</script>
- steup执行时机早于beforeCreate,他能用的生命周期API如下
生命周期钩子 | 说明 |
---|---|
onBeforeMount() | 在组件被挂载之前被调用,此时无法操作Dom |
onMounted() | 在组件挂载完成后执行 |
onBeforeUpdate() | 在组件即将因为响应式状态变更而更新其 DOM 树之前调用 |
onUpdated() | 在组件因为响应式状态变更而更新其 DOM 树之后调用 |
onBeforeUnmount() | 在组件实例被卸载之前调用 |
onUnmounted() | 在组件实例被卸载之后调用 |
Vue3 组合式API的更多相关文章
- vue3组合式API
vue3组合式API 为什么要用组合式API,我们来看看它是如何解决vue2的局限性的 1.vue2的局限性 当组件内容越来越多,逻辑越来越复杂,可读性就会降低,并且难以维护. vue2组件采用配置式 ...
- 解决WebStorm无法正确识别Vue3组合式API的问题
1 问题描述 Vue3的组合式API无法在WebStorm中正确识别,表现为defineComponent等无法被识别: 2 尝试方案 猜想这种问题的原因是无法正确识别对应的Vue3库,笔者相信Web ...
- [Vue]浅谈Vue3组合式API带来的好处以及选项API的坏处
前言 如果是经验不够多的同志在学习Vue的时候,在最开始会接触到Vue传统的方式(选项式API),后边会接触到Vue3的新方式 -- 组合式API.相信会有不少同志会陷入迷茫,因为我第一次听到新的名词 ...
- vue3组合式API介绍
为什么要使用Composition API? 根据官方的说法,vue3.0的变化包括性能上的改进.更小的 bundle 体积.对 TypeScript 更好的支持.用于处理大规模用例的全新 API,全 ...
- Vue3 组合式 API 中获取 DOM 节点的问题
模板引用 Vue 提供了许多指令让我们可以直接操作组件的模板.但是在某些情况下,我们仍然需要访问底层 DOM 元素.在模板中添加一个特殊的属性ref就可以得到该元素. 访问模板引用 <scrip ...
- 第三十五篇:vue3,(组合式api的初步理解)
好家伙, 来一波核心概念:数据劫持是响应式的核心 1.由set up开始 (1)vue3中的一个新的配置项,值为一个函数. (2)组件中所用的到的:数据,方法,计算属性均要配置在set up中. (3 ...
- 一篇文章讲明白vue3的script setup,拥抱组合式API!
引言 vue3除了Composition API是一个亮点之外,尤大大又给我们带来了一个全新的玩意 -- script setup,对于setup大家相信都不陌生,而对于script setup有些同 ...
- Vue3笔记(二)了解组合式API的应用与方法
一.组合式API(Composition API)的介绍 官方文档: https://v3.cn.vuejs.org/guide/composition-api-introduction.html 组 ...
- Vue3全局APi解析-源码学习
本文章共5314字,预计阅读时间5-15分钟. 前言 不知不觉Vue-next的版本已经来到了3.1.2,最近对照着源码学习Vue3的全局Api,边学习边整理了下来,希望可以和大家一起进步. 我们以官 ...
- Vue3 Composition API写烦了,试试新语法糖吧—setup script
前言 Vue3发布近一年了,相信大家对Vue3的新特性,新语法都很熟悉了.那么在使用Composition API的过程中,有没有觉得整个过程比较繁琐.比如你的模板里用到了大量的state和方法的时候 ...
随机推荐
- 技术解析 | ZEGO 移动端超分辨率技术
即构超分追求:速度更快.效果更好.码率更低.机型更广. 超分辨率(Super Resolution, SR)是从给定的低分辨率(Low Resolution, LR)图像中恢复高分辨率(High ...
- Parquet.Net: 将 Apache Parquet 移植到 .NET
Parquet.Net 是一个用于读取和写入 Apache Parquet 文件的纯 .NET 库,使用MIT协议开源,github仓库:https://github.com/aloneguid/pa ...
- Spring —— bean实例化
bean 实例化 bean本质上就是对象,创建bean使用构造方法完成(反射) 构造方法(常用) 静态工厂* 实例工厂* FactoryBean(实 ...
- JSP+Java编程资源
<JSP+Servlet+Tomcat应用开发从零开始学(第2版)>源码课件视频下载地址: https://pan.baidu.com/s/1HkFRul3wYBxe-skXCoQPwg ...
- C4996 'scanf': This function or variable may be unsafe. Consider using scanf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS.
错误原因 VS平台认为scanf函数不安全,要求换成scanf_s函数 解决方案 方案一:将scanf换成scanf_s[不建议] 将scanf换成scanf_s 但是,scanf_s函数只能在vs上 ...
- iotdb时序数据库常见使用命令
docker 安装IOTDB核心代码: #docker启动 docker run -d -p 6667:6667 -p 31999:31999 -p 8181:8181 --name some-iot ...
- C#WebApi 对数据进行缓存加快前请求数据的速度
using ClassLibrary1; using ClassLibrary2; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions ...
- vant 2 的 toast
因为toast使用的场景比较频繁,所以在 注册使用 Toast 的时候,直接在Vue实列的原型上添加了toast方便我们使用 : 格式:this.$toast.fail() this.$to ...
- JOI Open 2016
T1 JOIRIS 你在玩俄罗斯方块,游戏区域是一个宽度为 \(n\),高度足够大的矩形网格.初始时第 \(i\) 列有 \(a_i\) 个方块. 给定参数 \(k\),你可以做不超过 \(10^4\ ...
- 云原生爱好者周刊:玩 Kubernetes 游戏,赢取免费机票
云原生一周动态要闻: Grafana 8.2.2 发布 OSM(Open Service Mesh)发布 v1.0 的第一个候选版本 谷歌宣布推出 Google Distributed Cloud K ...