vue3.0组件API风格以及组合式API响应式基础
vue组件API风格
vue组件API风格:选项式 API 和组合式 API
1、选项式API
与vue2写法相似,使用选项的对象来描述组件的逻辑,例如data、methods和mounted等生命周期函数。选项所定义的属性都会暴露在函数内部的this上,它会指向当前的组件实例。
<script>
export default{
data(){
return{
count:0
}
},
methods:{
increment(){
this.count++
}
},
mounted(){
console.log(`The initial count is ${this.count}.`);
}
}
</script>
<template>
<button @click="increment">Count is: {{ count }}</button>
</template>
2、组合式API
通过组合式 API,我们可以使用导入的 API 函数来描述组件逻辑。在单文件组件中,组合式 API 通常会与
<script setup>
import { ref, onMounted } from 'vue'
// 响应式状态
const count = ref(0)
// 用来修改状态、触发更新的函数
function increment() {
count.value++
}
// 生命周期钩子
onMounted(() => {
console.log(`The initial count is ${count.value}.`)
})
</script>
<template>
<button @click="increment">Count is: {{ count }}</button>
</template>
3、选项式和组合式API的区别
- **选项式:**以“组件实例”的概念为中心 (即上述例子中的 this),对于有面向对象语言背景的用户来说,这通常与基于类的心智模型更为一致。同时,它将响应性相关的细节抽象出来,并强制按照选项来组织代码,从而对初学者而言更为友好。
- **组合式:**组合式 API 的核心思想是直接在函数作用域内定义响应式状态变量,并将从多个函数中得到的状态组合起来处理复杂问题。这种形式更加自由,也需要你对 Vue 的响应式系统有更深的理解才能高效使用。相应的,它的灵活性也使得组织和重用逻辑的模式变得更加强大。
4、注意事项
Vue 2 在 2022 年 6 月发布了最后一个小版本 (2.7),Vue 2 在 2023 年 12 月 31 日将到达它的截止维护日期;目前vue3是vue当前的最新主版本;
vue3提供了更小的包体积、更好的性能、更好的可扩展性和更好的 TypeScript/IDE 支持。如果你现在要开始一个新项目,推荐你选择 Vue 3。但需支持EI11,如果项目无法满足此需求可考虑使用vue2
最新版本的 Vue (3.x) 只支持原生支持 ES2015 的浏览器。这并不包括 IE11。Vue 3.x 使用的 ES2015 功能无法在旧版本的浏览器中进行兼容,如果你需要支持旧版本的浏览器,请使用 Vue 2.x 替代
5、组合式API响应的核心
组合式api通常与< script setup > 搭配使用;
ref()
computed()
reactive()
readonly()
watchEffect()
watchPostEffect()
watchSyncEffect()
watch()
5.1、ref(),由于reactive的限制,推荐使用ref()作为声明响应式状态的主要API
组合API中,推荐使用ref()来声明响应式状态;
ref() 接收参数,并将其包裹在一个带有 .value 属性的 ref 对象中返回:
当你在模板中使用了一个 ref,然后改变了这个 ref 的值时,Vue 会自动检测到这个变化,并且相应地更新 DOM。这是通过一个基于依赖追踪的响应式系统实现的。当一个组件首次渲染时,Vue 会追踪在渲染过程中使用的每一个 ref。然后,当一个 ref 被修改时,它会触发追踪它的组件的一次重新渲染。
//设置简单类型
<script setup>
import { ref } from 'vue'
const count = ref(0)
console.log(count) // { value: 0 }
console.log(count.value) // 0
//ref 会根据初始化时的值推导其类型:
const year = ref(2020);//Number
const str = ref('hello word');//String
const isShow = ref(true);//Boolean
</script>
<script setup>
import { ref, onMounted} from 'vue'
// 响应式状态
const count = ref(0)
// 用来修改状态、触发更新的函数
function increment() {
count.value++
}
// 生命周期钩子
onMounted(() => {
console.log(`The initial count is ${count.value}.`)
})
</script>
<template>
<div>在模板中使用 ref 时,我们不需要附加.value; 当在模板中使用时,ref 会自动解包</div>
<button @click="increment">Count is: {{ count }}</button>
</template>
5.1.1、模板解包注意事项
在模板渲染上下文中,只有顶级的 ref 属性才会被解包。
另一个需要注意的点是,如果 ref 是文本插值的最终计算值 (即 {{ }} 标签),那么它将被解包;该特性仅仅是文本插值的一个便利特性,等价于 {{ object.id.value }}
const count = ref(0)
const object = { id: ref(1) };
const { id } = obj;//对象的解构,必须对象名相同
function countHandle(){
count.value++;
obj.id++;
}
<template>
<div>count+1:{{ count+1 }} 按照预期工作,结果为1,</div>
<div>obj.id:{{ obj.id }} 等价于 obj.id.value</div>
<div>obj.id.value:{{ obj.id.value+1 }} 结果为2</div>
<div>obj.id+1:{{ obj.id + 1 }} 不会按照预期工作,结果为[object Object]1</div>
<div>{{ id+1 }} 结果为2</div>
<button @click="countHandle()">点击方法查看响应区别</button>
</template>
5.1.2、DOM更新时机
当你修改了响应式状态时,DOM 会被自动更新。但是需要注意的是,DOM 更新不是同步的。Vue 会在“next tick”更新周期中缓冲所有状态的修改,以确保不管你进行了多少次状态修改,每个组件都只会被更新一次。
要等待 DOM 更新完成后再执行额外的代码,可以使用 nextTick() 全局 API:
//设置简单类型
<script setup>
import { ref } from 'vue'
const count = ref(0)
console.log(count) // { value: 0 }
console.log(count.value) // 0
//ref 会根据初始化时的值推导其类型:
const year = ref(2020);//Number
const str = ref('hello word');//String
const isShow = ref(true);//Boolean
</script>
<script setup>
import { ref,nextTick } from 'vue'
function increment() {
const count = ref(0);
console.log(document.getElementById('counter').textContent);//0
nextTick(()=>{
//现在DOM已更新
console.log(document.getElementById('counter').textContent);//1
})
}
</script>
<template>
<div>count: <span id="counter">{{count}}</span></div>
<button @click="increment">Count is: {{ count }}</button>
</template>
async function countHandle(){
count.value++;
console.log(document.getElementById('counter').textContent);//0
await nextTick();
console.log(document.getElementById('counter').textContent);//1
}
5.2、reactive()响应式API
reactive() 将使对象本身具有响应性;
将一个 ref 赋值给一个 reactive 属性时,该 ref 会被自动解包:
<script setup>
const count = ref(0);
const obj = reactive({age:18,name:'张三'});
obj.count = count;
function countHandle(){
count.value++;
obj.age++;
}
</script>
<template>
<button @click="countHandle" id="counter">加1,count的值:{{count}}</button>
<div>obj的age:{{obj.age}}</div>
<div>obj的count:{{obj.count}}</div>
</template>
reactive() 的局限性:
- 有限的值类型:它只能用于对象类型 (对象、数组和如 Map、Set 这样的集合类型)。它不能持有如 string、number 或 boolean 这样的原始类型。
- 不能替换整个对象:由于 Vue 的响应式跟踪是通过属性访问实现的,因此我们必须始终保持对响应式对象的相同引用。这意味着我们不能轻易地“替换”响应式对象,因为这样的话与第一个引用的响应性连接将丢失;
- 对解构操作不友好:当我们将响应式对象的原始类型属性解构为本地变量时,或者将该属性传递给函数时,我们将丢失响应性连接:
一个 ref 会在作为响应式对象的属性被访问或修改时自动解包。换句话说,它的行为就像一个普通的属性
<script setup>
const state = reactive({count});
function countHandle(){
count.value++;
}
</script>
<template>
<div>count: <span id="counter">{{count}}</span></div>
<div>state: {{state.count}}</div>
<button @click="countHandle()">count和state.count值同时更改</button>
</template>
如果将一个新的 ref 赋值给一个关联了已有 ref 的属性,那么它会替换掉旧的 ref:
<script setup>
const state = reactive({count});
const otherCount = ref(2);
//原始 ref 现在已经和 state.count 失去联系
state.count = otherCount;
function countHandle(){
count.value++;
}
</script>
<template>
<div>count: <span id="counter">{{count}}</span></div>
<div>state: {{state.count}}</div>
<button @click="countHandle()">state.count值不会更改</button>
</template>
6、vue3响应式API:核心
- ref()
- computed()
- reactive()
- readonly()
- watchEffect()
- watchPostEffect()
- watchSyncEffect()
- watch()
vue3响应式API核心官网介绍