vue3.0API详解
Vue 3.0 于 2020-09-18 发布了,使用了 Typescript 进行了大规模的重构,带来了 Composition API RFC 版本,类似 React Hook 一样的写 Vue,可以自定义自己的 hook ,让使用者更加的灵活。
为什么推出3.0?
- 对 TypeScript 支持不友好(所有属性都放在了 this 对象上,难以推倒组件的数据类型)
- 大量的 API 挂载在 Vue 对象的原型上,难以实现 TreeShaking
- TreeShaking:当我引入一个模块的时候,我不引入这个模块的所有代码,我只引入我需要的代码
- 架构层面对跨平台 dom 渲染开发支持不友好
- CompositionAPI。受 ReactHook 启发
- 更方便的支持了 jsx
- Vue 3 的 Template 支持多个根标签,Vue 2 不支持
- 对虚拟 DOM 进行了重写、对模板的编译进行了优化操作
一、setup
为我们使用 vue3 的 Composition API 新特性提供了统一的入口, 有些文章说setup 函数会在 beforeCreate 之后、created 之前执行但实践证明这个说法不正确如下图打印顺序, vue3 也是取消了这两个钩子,统一用 setup 代替, 该函数相当于一个生命周期函数,vue 中过去的 data,methods,watch 等全部都用对应的新增 api 写在 setup()函数中。
1、setup参数
- props: 组件传入的属性
- context:attrs,emit,slots
props
setup中接受的props
是响应式的, 当传入新的props 时,会及时被更新。由于是响应式的, 所以不可以使用ES6解构,解构会消除它的响应式。需要结构可以用toRefs()
context
setup
中不能访问Vue2中最常用的this
对象,所以context
中就提供了this
中最常用的三个属性:attrs
、slot
和emit
,分别对应Vue2.x中的 $attr
属性、slot
插槽 和$emit
发射事件。
简单用法
2、reactive、ref与toRefs
在vue2.x中, 定义数据都是在data
中, 但是Vue3.x 可以使用reactive
和ref
来进行数据定义。
区别
reactive
用于处理对象的双向绑定,ref
则处理js基础类型的双向绑定,reactive
不能代理基本类型,例如字符串、数字、boolean等。
简单用法
<template>
<div>
<span>{{ year }}</span
><span>{{ user.name }}</span
><span>{{ user.label }}</span>
</div>
</template> <script>
import { reactive, ref } from "vue";
export default {
props: {
data: {
type: Object,
default: {
id: 1,
name: "匹配",
},
},
},
components: {}, setup(props, con) {
const year = ref(10);
const user = reactive({
name: "夏利",
label: "",
});
//这里ref取值需要加value
if (year.value > 5) {
user.label = "牛逼";
} else {
user.label = "一般";
}
return {
year,
user,
};
},
};
</script>
不能直接对user
进行结构, 这样会消除它的响应式, 这里就和上面我们说props
不能使用ES6直接解构就呼应上了。那我们就想使用解构后的数据怎么办,解决办法就是使用toRefs
。
return {
year,
// 使用reRefs
...toRefs(user)
}
3、生命周期
我们可以看到beforeCreate
和created
被setup
替换了(但是Vue3中你仍然可以使用, 因为Vue3是向下兼容的, 也就是你实际使用的是vue2的)。其次,钩子命名都增加了on
; Vue3.x还新增用于调试的钩子函数onRenderTriggered
和onRenderTricked
<script>
import {
defineComponent,
onBeforeMount,
onMounted,
onBeforeUpdate,
onUpdated,
onBeforeUnmount,
onUnmounted,
onErrorCaptured,
onRenderTracked,
onRenderTriggered,
} from "vue"; export default defineComponent({
// beforeCreate和created是vue2的
beforeCreate() {
console.log("------beforeCreate-----");
},
created() {
console.log("------created-----");
},
setup() {
console.log("------setup-----"); // vue3.x生命周期写在setup中
onBeforeMount(() => {
console.log("------onBeforeMount-----");
});
onMounted(() => {
console.log("------onMounted-----");
});
// 调试哪些数据发生了变化
onRenderTriggered((event) => {
console.log("------onRenderTriggered-----", event);
});
},
});
</script>
4、全局定义属性 globalProperties
在项目中往往会全局定义公共属性或方法,方便我们组件间调用。
import { createApp } from 'vue'
import App from './App.vue'
import utils from './utils' // vue2.0写法
let vue=new Vue()
vue.prototype.utils=utils
// vue3.0写法
const app=createApp(App)
app.config.globalProperties.utils=utils
app.mount('#app')
vue3.0中使用全局定义的属性
<script>
import { getCurrentInstance } from "vue";
export default {
components: {},
setup(props, con) {
const { ctx } = getCurrentInstance();
console.log(ctx.utils);
},
};
</script>
5、use与plugin
定义一个组件
通过use引入
6、readonly 只读属性
在使用readonly后重新进行复制是不允许修改的,这个api不常用
7、computed计算api
这里引入了proxy内的类似写法,有了set与get的内容写法,该函数用来创造计算属性,和过去一样,它返回的值是一个 ref 对象。里面可以传方法,或者一个对象,对象中包含 set()、get()方法。
7.1 创建只读的计算属性
<template>
<div>
<p>refCount: {{refCount}}</p>
<p>计算属性的值computedCount : {{computedCount}}</p>
<button @click="refCount++">refCount + 1</button>
</div>
</template> <script>
import { computed, ref } from '@vue/composition-api'
export default {
setup() {
const refCount = ref(1)
// 只读
let computedCount = computed(() => refCount.value + 1) //2
console.log(computedCount)
return {
refCount,
computedCount
}
}
};
</script>
7.2 通过 set()、get()方法创建一个可读可写的计算属性
<template>
<div>
<p>refCount: {{refCount}}</p>
<p>计算属性的值computedCount : {{computedCount}}</p>
<button @click="refCount++">refCount + 1</button>
</div>
</template> <script>
import { computed, ref } from '@vue/composition-api'
export default {
setup() {
const refCount = ref(1)
// 可读可写
let computedCount = computed({
// 取值函数
get: () => refCount.value + 1,
// 赋值函数
set: val => {
refCount.value = refCount.value -5
}
})
//触发get函数
console.log(computedCount.value)
// 为计算属性赋值的操作,会触发 set 函数
computedCount.value = 10
console.log(computedCount.value)
// 触发 set 函数后,count 的值会被更新
console.log(refCount.value)
return {
refCount,
computedCount
}
}
};
</script>
8、watch与watchEffect
8.1watch
watch 函数用来侦听特定的数据源,并在回调函数中执行副作用。默认情况是惰性的,也就是说仅在侦听的源数据变更时才执行回调。
<script>
import { ref, watch } from "vue";
export default {
components: {},
setup(props, con) {
const count = ref(0);
const name = ref("iuuggu");
setTimeout(() => {
(count.value = 1), (name.value = "这一行山");
}, 200);
watch(
() => {
/*
* 1、需要一个明确的数据资源
* 2、需要有一个回调函数
* 3、等到改变才会执行函数
*
*/
return count.value;
},
() => {}
);
// 4、ref简写 ,reactive不可以
watch(count, () => {});
// 5、监听多个
watch(
() => {
return [count, name];
},
([newv, oldv], [newv, oldv]) => {}
);
// 6、onTrack,onTrigger
watch(
() => {
return [count, name];
},
([newv, oldv], [newv, oldv]) => {},
{
onTrack(e) {},
onTrigger(e) {},
}
);
},
};
</script>
8.1.1 监听数据源
reactive
setup(props, context) {
const state = reactive<Person>({ name: 'vue', age: 10 }) watch(
() => state.age,
(age, preAge) => {
console.log(age); // 100
console.log(preAge); // 10
}
)
// 修改age 时会触发watch 的回调, 打印变更前后的值
state.age = 100
return {
...toRefs(state)
}
}
ref
setup(props, context) {
const age = ref<number>(10); watch(age, () => console.log(age.value)); // 100 // 修改age 时会触发watch 的回调, 打印变更后的值
age.value = 100
return {
age
}
}
8.1.2监听多个
setup(props, context) {
const state = reactive<Person>({ name: 'vue', age: 10 }) watch(
[
() => state.age,
() => state.name
],
([newName, newAge], [oldName, oldAge]) => {
console.log(newName);
console.log(newAge); console.log(oldName);
console.log(oldAge);
}
)
// 修改age 时会触发watch 的回调, 打印变更前后的值, 此时需要注意, 更改其中一个值, 都会执行watch的回调
state.age = 100
state.name = 'vue3'
return {
...toRefs(state)
}
}
8.1.3stop 停止监听
在 setup() 函数内创建的 watch 监视,会在当前组件被销毁的时候自动停止。如果想要明确地停止某个监视,可以调用 watch() 函数的返回值即可,语法如下:
setup(props, context) {
const state = reactive<Person>({ name: 'vue', age: 10 }) const stop = watch(
[() => state.age, () => state.name],
([newName, newAge], [oldName, oldAge]) => {
console.log(newName);
console.log(newAge); console.log(oldName);
console.log(oldAge);
}
)
// 修改age 时会触发watch 的回调, 打印变更前后的值, 此时需要注意, 更改其中一个值, 都会执行watch的回调
state.age = 100
state.name = 'vue3' setTimeout(()=> {
stop()
// 此时修改时, 不会触发watch 回调
state.age = 1000
state.name = 'vue3-'
}, 1000) // 1秒之后讲取消watch的监听 return {
...toRefs(state)
}
}
8.2 watchEffect
该函数有点像update函数,但他执行在update与beforeuodate之前。
* 1、首次加载会立即执行
* 2、响应的最终所有依赖监听变化(数据改变)
* 3、在卸载onUnmounte时自动停止
* 4、执行stop就会停止监听,否则一直监听
* 5、异步函数先执行再去监听改变
<script>
import { watchEffect, ref, onMounted } from "vue";
export default {
components: {},
//con==context(attrs,emit,slots)
setup(props, con) {
const count = ref(0);
setTimeout(() => {
count.value = 1;
}, 2000);
const stop = watchEffect(
() => {
/*
* 1、首次加载会立即执行
* 2、响应的最终所有依赖监听变化(数据改变)
* 3、在卸载onUnmounte时自动停止
* 4、执行stop就会停止监听,否则一直监听
* 5、异步函数先执行再去监听改变
*/
},
{
// 6、在update之后执行
flush: "post",
// 同步执行
flush: "async",
}
);
setTimeout(() => {
stop();
}, 4000); // 7、组件挂在ref
const myRef = ref(null);
// 避免监听时先见听到null 在监听到h1
onMounted(() => {
watchEffect(() => {
console.log(myRef.value);
});
});
// 8、debugging 开发模式使用
watchEffect(
() => {
console.log(count.value);
},
{
onTrack(e) {
// 监听到count和改变count
},
onTrigger(e) {
// count改变了会触发
},
}
);
return {
myRef,
count,
};
},
};
</script>
9、ref,torefs,isref,unref
9.1ref
ref() 函数用来根据给定的值创建一个响应式的数据对象,ref() 函数调用的返回值是一个对象,这个对象上只包含一个 .value 属性:
ref数据
<template>
<div class="mine">
{{count}} // 10
</div>
</template> <script >
import {ref } from 'vue';
export default {
setup() {
const count = ref(10)
// 在js 中获取ref 中定义的值, 需要通过value属性
console.log(count.value);
return {
count
}
}
}
</script>
ref 访问dom
在 reactive 对象中访问 ref 创建的响应式数据
当把 ref() 创建出来的响应式数据对象,挂载到 reactive() 上时,会自动把响应式数据对象展开为原始的值,不需通过 .value 就可以直接被访问,例如:
<template>
<div class="mine">
{{count}} -{{t}} // 10 -100
</div>
</template> <script >
import reactive, ref, toRefs } from 'vue';
export default {
setup() {
const count = ref(10)
const obj = reactive({
t: 100,
count
})
// 通过reactive 来获取ref 的值时,不需要使用.value属性
console.log(obj.count);
return {
...toRefs(obj)
}
}
}
</script>
9.2 toRefs() 函数
toRefs() 函数可以将 reactive() 创建出来的响应式对象,转换为普通的对象,只不过,这个对象上的每个属性节点,都是 ref() 类型的响应式数据
<template>
<div>
<p>{{ count }} - {{ name }}</p>
<button @click="count += 1">+1</button>
<button @click="add">+1</button>
</div>
</template> <script>
import { reactive, toRefs } from "@vue/composition-api";
export default {
setup() {
// 响应式数据
const state = reactive({ count: 0, name: "zs" });
// 方法
const add = () => {
state.count += 1;
};
return {
// 非响应式数据
// ...state,
// 响应式数据
...toRefs(state),
add
};
}
};
</script>
9.3 isref
isRef() 用来判断某个值是否为 ref() 创建出来的对象
setup(props, context) {
const name: string = 'vue'
const age = ref(18)
console.log(isRef(age)); // true
console.log(isRef(name)); // false return {
age,
name
}
}
9.4 unref
unRef() 用来判断某个值是否为 ref() 创建出来的对象有抛出该对象
setup(props, context) {
const name: string = 'vue'
const age = ref(18)
console.log(unRef(age)); // 18
console.log(unRef(name)); // vue return {
age,
name
}
}
最新文章
- 浅析linux内核中的idr机制
- 可惜Java中没有yield return
- shell程序设计
- .net 小技巧
- Java 集合深入理解(3):Collection
- matlab 相关代码记录
- adb device出现error:unknown host service
- DedeCMS Error:Tag disabled:";php";的解决办法
- 在O(1)时间删除链表结点
- java在线截图---通过指定的URL对网站截图
- hdu 2546 饭卡(DP)
- css伪类选择器详细解析及案例使用-----伪类选择器(2)
- VMTools安装
- [django]添加自定义template filter标签
- ARMV8 datasheet学习笔记4:AArch64系统级体系结构之Self-hosted debug
- JavaScript--常用的输出方式
- CSS 笔记(一)
- Google Android API官网封杀了,没法查android技术资料的3种解决方式
- PSR编码规范
- 使用 Win2D 绘制带图片纹理的圆(或椭圆)
热门文章
- vue实现拖拽排序
- 使用 Elastic 技术栈构建 Kubernetes全栈监控
- Prometheus 配置文件中 metric_relabel_configs 配置--转载
- 专家动态页面的实现——php基于CI框架的学习(二)
- 【软件推荐】使用Cmder替换Windows自带的控制台
- Dynamic CRM登陆界面的客制化(持续更新)
- Java(195-214)【final、权限、内部类】
- Jmeter(四十三) - 从入门到精通高级篇 - Jmeter之IP伪装和欺骗(详解教程)
- 推荐个开源在线文档,助道友领悟 Django 之“道”
- top:0;bottom:0;left:0;right:0;同时使用的效果