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参数

  1. props: 组件传入的属性
  2. 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 函数用来侦听特定的数据源,并在回调函数中执行副作用。默认情况是惰性的,也就是说仅在侦听的源数据变更时才执行回调。

    *   1、需要一个明确的数据资源
         *   2、需要有一个回调函数
         *   3、等到改变才会执行函数
<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
}
}

vue3.0API详解的更多相关文章

  1. Vue3 setup详解

    setup执行的时机 在beforeCreate之前执行(一次),此时组件对象还没创建: this是undefined,不能通过this来访问data/computed/methods/props: ...

  2. Linq之旅:Linq入门详解(Linq to Objects)

    示例代码下载:Linq之旅:Linq入门详解(Linq to Objects) 本博文详细介绍 .NET 3.5 中引入的重要功能:Language Integrated Query(LINQ,语言集 ...

  3. 架构设计:远程调用服务架构设计及zookeeper技术详解(下篇)

    一.下篇开头的废话 终于开写下篇了,这也是我写远程调用框架的第三篇文章,前两篇都被博客园作为[编辑推荐]的文章,很兴奋哦,嘿嘿~~~~,本人是个很臭美的人,一定得要截图为证: 今天是2014年的第一天 ...

  4. EntityFramework Core 1.1 Add、Attach、Update、Remove方法如何高效使用详解

    前言 我比较喜欢安静,大概和我喜欢研究和琢磨技术原因相关吧,刚好到了元旦节,这几天可以好好学习下EF Core,同时在项目当中用到EF Core,借此机会给予比较深入的理解,这里我们只讲解和EF 6. ...

  5. Java 字符串格式化详解

    Java 字符串格式化详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 文中如有纰漏,欢迎大家留言指出. 在 Java 的 String 类中,可以使用 format() 方法 ...

  6. Android Notification 详解(一)——基本操作

    Android Notification 详解(一)--基本操作 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Notification 文中如有纰 ...

  7. Android Notification 详解——基本操作

    Android Notification 详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 前几天项目中有用到 Android 通知相关的内容,索性把 Android Notificatio ...

  8. Git初探--笔记整理和Git命令详解

    几个重要的概念 首先先明确几个概念: WorkPlace : 工作区 Index: 暂存区 Repository: 本地仓库/版本库 Remote: 远程仓库 当在Remote(如Github)上面c ...

  9. Drawable实战解析:Android XML shape 标签使用详解(apk瘦身,减少内存好帮手)

    Android XML shape 标签使用详解   一个android开发者肯定懂得使用 xml 定义一个 Drawable,比如定义一个 rect 或者 circle 作为一个 View 的背景. ...

随机推荐

  1. concurrentHashMap的put方法详解

    本文主要介绍ConcurrentHashMap的put操作如果有错误的地方欢迎大家指出. 1.ConcurrentHashMap的put操作 ConcurrentHashMap的put操作主要有3种方 ...

  2. 优化 ASP.NET Core Docker 镜像的大小

    在这容器化的世界里,我们已经很少直接通过文件发布来运行asp.net core程序了.现在大多数情况下,我们都会使用docker来运行程序.在使用docker之前,我们往往需要打包我们的应用程序.as ...

  3. Golang 基于Prometheus Node_Exporter 开发自定义脚本监控

    Golang 基于Prometheus Node_Exporter 开发自定义脚本监控 公司是今年决定将一些传统应用从虚拟机上迁移到Kubernetes上的,项目多而乱,所以迁移工作进展缓慢,为了建立 ...

  4. 【2020.8.23NOIP模拟赛】失落

    [ 2020.8.23 N O I P 模 拟 赛 ] 失 落 [2020.8.23NOIP模拟赛]失落 [2020.8.23NOIP模拟赛]失落 题目描述 出题人心情很失落,于是他直接告诉你让你求出 ...

  5. Linux(六):系统运维常用命令

    实际的生产环境下,不论是研发还是运维,或多或少的得面对在linux上定位问题这个关卡,这里介绍一下linux环境下一些状态查看常用的命令. 系统资源监控 总体资源占用情况查看 命令:top 像wind ...

  6. SqlServer存储过程应用二:分页查询数据并动态拼接where条件

    前言 开发中查询功能是贯穿全文的,我们来盘一盘使用存储过程分页查询,并且支持动态拼接where条件. 划重点:支持动态拼接where条件 对存储过程的使用有疑问的同学去[SqlServer存储过程的创 ...

  7. JMeter发送get请求并分析返回结果

    在实际工作的过程中,我们通常需要模拟接口,来进行接口测试,我们可以通过JMeter.postman等多种工具来进行接口测试,但是工具的如何使用对于我们来说并不是最重要的部分,最重要的是设计接口测试用例 ...

  8. 《SQL必知必会》学习笔记整理

    简介 本笔记目前已包含 <SQL必知必会>中的所有章节. 我在整理笔记时所考虑的是:在笔记记完后,当我需要查找某个知识点时,不需要到书中去找,只需查看笔记即可找到相关知识点.因此在整理笔记 ...

  9. Python学习从入门到放弃?我不允许!!!

    嗨,大家好 这里是汐仔 很多人都说学习python学习python,打开书本,三分钟,从入门到放弃. 这怎么可以!!!大家能选择python的原因可能是看它既简单,好入门,现在俨然是语言中的一匹黑马. ...

  10. aws eks上部署 ingress-nginx 加NLB

    转载自https://kubernetes.github.io/ingress-nginx/deploy/#aws In AWS we use a Network load balancer (NLB ...