文档:

API Reference

教程

课件

1. 初始化项目

// ① npm i -g @vue/cli
// ② vue create my-project
// ③ npm install @vue/composition-api -S // ④ main,js
import Vue from 'vue'
import VueCompositionApi from '@vue/composition-api'
Vue.use(VueCompositionApi)

2. setup方法

setupvue3.x中新的操作组件属性的方法,它是组件内部暴露出所有的属性和方法的统一API。

2.1 执行时机

setup的执行时机在:beforeCreate 之后 created之前

setup(props, ctx) {
console.log('setup')
},
beforeCreate() {
console.log('beforeCreate')
},
created() {
console.log('created')
},

2.2 接受props数据

<!-- 组件传值 -->
<com-setup p1="传值给 com-setup"/>
// 通过 setup 函数的第一个形参,接收 props 数据:
setup(props) {
console.log(props)
},
// 在 props 中定义当前组件允许外界传递过来的参数名称:
props: {
p1: String
}
/*
{}
p1: "传值给 com-setup"
get p1: ƒ reactiveGetter()
set p1: ƒ reactiveSetter(newVal)
__proto__: Object
*/

2.3 context

setup 函数的第二个形参是一个上下文对象,这个上下文对象中包含了一些有用的属性,这些属性在 vue 2.x 中需要通过 this 才能访问到,在 vue 3.x 中,它们的访问方式如下:

  setup(props, ctx) {
console.log(ctx)
console.log(this) // undefined
},
/*
attrs: Object
emit: ƒ ()
listeners: Object
parent: VueComponent
refs: Object
root: Vue
...
*/

注意:在 setup() 函数中无法访问到 this

3. reactive

reactive函数接收一个普通函数,返回一个响应式的数据对象。

reactive函数等价于 vue 2.x 中的 Vue.observable() 函数,vue 3.x 中提供了 reactive() 函数,用来创建响应式的数据对象,基本代码示例如下:

<template>
<div>
<!-- 在 template 中访问响应式数据 -->
<p>当前的 count 值为:{{count}}</p>
<button @click="count += 1">+1</button>
</div>
</template> <script>
import {reactive} from '@vue/composition-api'
export default {
setup(props, ctx) {
// 创建响应式数据对象,得到的 state 类似于 vue 2.x 中 data() 返回的响应式对象
const state = reactive({ count: 0 })
state.count += 1
console.log(state)
// setup 函数中将响应式数据对象 return 出去,供 template 使用
return state
}
}
</script>

4. ref

ref() 函数用来根据给定的值创建一个响应式数据对象ref() 函数调用的返回值是一个对象,这个对象上只包含一个 .value 属性:

<template>
<div>
<h3>02.ref.vue 文件</h3>
<p>refCount:{{refCount}}</p>
<button @click="refCount += 1">+1</button>
</div>
</template> <script>
import { ref } from '@vue/composition-api'
export default {
setup() {
// / 创建响应式数据对象 count,初始值为 0
const refCount = ref(0)
// 如果要访问 ref() 创建出来的响应式数据对象的值,必须通过 .value 属性才可以,只有在setup内部才需要 .value 属性
console.log(refCount.value) // 输出 0
// 让 refCount 的值 +1
refCount.value++
// 再次打印 refCount 的值
console.log(refCount.value) // 输出 1
return {
refCount
}
}
}
</script>

4.1 在 reactive 对象中访问 ref 创建的响应式数据

当把 ref() 创建出来的响应式数据对象,挂载到 reactive() 上时,会自动把响应式数据对象展开为原始的值,不需通过 .value 就可以直接被访问,例如:

setup() {
const refCount = ref(0)
const state = reactive({refCount})
console.log(state.refCount) // 输出 0
state.refCount++ // 此处不需要通过 .value 就能直接访问原始值
console.log(refCount) // 输出 1
return {
refCount
}
}

注意:新的 ref 会覆盖旧的 ref,示例代码如下:

setup() {
// 创建 ref 并挂载到 reactive 中
const c1 = ref(0);
const state = reactive({ c1 }); // 再次创建 ref,命名为 c2
const c2 = ref(9);
// 将 旧 ref c1 替换为 新 ref c2
state.c1 = c2;
state.c1++; console.log(state.c1); // 输出 10
console.log(c2.value); // 输出 10
console.log(c1.value); // 输出 0
}

5. isRef

isRef() 用来判断某个值是否为 ref() 创建出来的对象;应用场景:当需要展开某个可能为 ref() 创建出来的值的时候,例如:

import { ref, reactive, isRef } from "@vue/composition-api";
export default {
setup() {
const unwrapped = isRef(foo) ? foo.value : foo
}
};

6. toRefs

toRefs() 函数可以将 reactive() 创建出来的响应式对象,转换为普通的对象,只不过,这个对象上的每个属性节点,都是 ref() 类型的响应式数据。

<template>
<div>
<h3>03.toRefs.vue文件</h3>
<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>

7. computed计算属性

7.1 只读的计算属性

<template>
<div>
<h3>04.computed.vue文件</h3>
<p>refCount: {{refCount}}</p>
<p>计算属性的值computedCount : {{computedCount}}</p>
<button @click="refCount++">refCount + 1</button>
<!-- 点击报错 -->
<button @click="computedCount++">计算属性的值computedCount + 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)
console.log(computedCount)
return {
refCount,
computedCount
}
}
};
</script>

7.2 可读可写的计算属性

<template>
<div>
<h3>04.computed.vue文件</h3>
<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
}
})
console.log(computedCount.value)
// 为计算属性赋值的操作,会触发 set 函数
computedCount.value = 10
console.log(computedCount.value)
// 触发 set 函数后,count 的值会被更新
console.log(refCount.value)
return {
refCount,
computedCount
}
}
};
</script>

8. watch

watch() 函数用来监视某些数据项的变化,从而触发某些特定的操作,使用之前需要按需导入:

import { watch } from '@vue/composition-api'

8.1 基本用法

<template>
<div>
<h3>05.watch.vue文件</h3>
<p>refCount: {{refCount}}</p>
</div>
</template> <script>
import { watch, ref } from '@vue/composition-api'
export default {
setup() {
const refCount = ref(100)
// 定义 watch,只要 count 值变化,就会触发 watch 回调
// 组件在第一次创建的时候执行一次 watch
watch(() => console.log(refCount.value), { lazy: false})
setInterval(() => {
refCount.value += 2
}, 5000)
return {
refCount
}
}
};
</script>

8.2 监视数据源

监视 reactive 类型的数据源:

<template>
<div>
<h3>05.watch.vue文件</h3>
<p>count: {{count}}</p> // 不是响应式数据
</div>
</template> <script>
import { watch, ref, reactive } from '@vue/composition-api'
export default {
setup() {
const state = reactive({count: 100})
watch(
// 监听count
() => state.count,
// 如果变换 执行以下函数
(newVal, oldVala) => {
console.log(newVal, oldVala)
},
{ lazy: true }
)
setInterval(() => {
state.count += 2
}, 5000)
return state
}
};
</script>

监视 ref 类型的数据源:

export default {
setup() {
// 定义数据源
let count = ref(0);
// 指定要监视的数据源
watch(count, (count, prevCount) => {
console.log(count, prevCount)
})
setInterval(() => {
count.value += 2
}, 2000)
console.log(count.value)
return {
count
}
}
};

8.3 监听多个数据源

监视 reactive 类型的数据源:

export default {
setup() {
const state = reactive({count: 100, name: 'houfei'})
watch(
// 监听count name
[() => state.count, () => state.name],
// 如果变换 执行以下函数
([newCount, newName], [oldCount, oldName]) => {
console.log(newCount, oldCount)
console.log(newName, oldName)
},
{ lazy: true} // 在 watch 被创建的时候,不执行回调函数中的代码
)
setTimeout(() => {
state.count += 2
state.name = 'qweqweewq'
}, 3000)
return state
}
};

监视 ref 类型的数据源:

export default {
setup() {
// 定义数据源
const count = ref(10)
const name = ref('zs')
// 指定要监视的数据源
watch(
[count, name],
([newCount, newName], [oldCount, oldName]) => {
console.log(newCount, oldCount)
console.log(newName, oldName)
},
{ lazy: true}
)
setInterval(() => {
count.value += 2
}, 2000)
console.log(count.value)
return {
count
}
}
};

8.4 清除监视

setup() 函数内创建的 watch 监视,会在当前组件被销毁的时候自动停止。如果想要明确地停止某个监视,可以调用 watch() 函数的返回值即可,语法如下:

<script>
// 创建监视,并得到 停止函数
const stop = watch(() => {
/* ... */
}) // 调用停止函数,清除对应的监视
stop()
<template>
<div>
<!-- <h3>05.watch.vue文件</h3> -->
<p>count: {{ count }}</p>
<button @click="stopWatch">停止监听</button>
</div>
</template> <script>
import { watch, ref, reactive } from "@vue/composition-api";
export default {
setup() {
// 定义数据源
const count = ref(10)
const name = ref('zs')
// 指定要监视的数据源
const stop = watch(
[count, name],
([newCount, newName], [oldCount, oldName]) => {
console.log(newCount, oldCount)
console.log(newName, oldName)
},
{ lazy: true}
)
setInterval(() => {
count.value += 2
name.value = 'houyue'
}, 2000)
// 停止监视
const stopWatch = () => {
console.log("停止监视,但是数据还在变化")
stop()
}
console.log(count.value)
return {
stop,
count,
stopWatch
}
}
}; </script>

8.5 在watch中清除无效的异步任务

有时候,当被 watch 监视的值发生变化时,或 watch 本身被 stop 之后,我们期望能够清除那些无效的异步任务,此时,watch 回调函数中提供了一个 cleanup registrator function 来执行清除的工作。这个清除函数会在如下情况下被调用:

  • watch 被重复执行了

  • watch 被强制 stop

Template 中的代码示例如下

<template>
<div>
<!-- <h3>05.watch.vue文件</h3> -->
<input type="text" v-model="keywords" />
<p>keywords:--- {{ keywords }}</p>
</div>
</template>

Script 中的代码示例如下

<script>
import { watch, ref, reactive } from "@vue/composition-api"; export default {
setup() {
// 定义响应式数据 keywords
const keywords = ref(""); // 异步任务:打印用户输入的关键词
const asyncPrint = val => {
// 延时 1 秒后打印
return setTimeout(() => {
console.log(val);
}, 1000);
}; // 定义 watch 监听
watch(
keywords,
(keywords, prevKeywords, onCleanup) => {
// 执行异步任务,并得到关闭异步任务的 timerId
const timerId = asyncPrint(keywords);
// 如果 watch 监听被重复执行了,则会先清除上次未完成的异步任务
onCleanup(() => clearTimeout(timerId));
},
// watch 刚被创建的时候不执行
{ lazy: true }
); // 把 template 中需要的数据 return 出去
return {
keywords
};
}
};
</script>

9. provide & inject 组件传值

provide()inject() 可以实现嵌套组件之间的数据传递。这两个函数只能在 setup() 函数中使用。父级组件中使用 provide() 函数向下传递数据;子级组件中使用 inject() 获取上层传递过来的数据。

9.1 共享普通数据

app.vue 根组件:

<template>
<div id="app">
<h1>父组件</h1>
<button @click="color = 'blue'">蓝色</button>
<button @click="color = 'red'">红色</button>
<button @click="color = 'yellow'">黄色</button>
<son></son>
<son></son>
</div>
</template> <script>
import { ref, provide } from '@vue/composition-api'
import Son from './components/06.son.vue' export default {
name: 'app',
components: {
'son': Son
},
setup() {
const color = ref('green')
provide('themecolor', color)
return {
color
}
}
}
</script>

06.son.vue son 组件:

<template>
<div>
<h3 :style="{color: color}">son 组件</h3>
<grandson></grandson>
</div>
</template> <script>
import { inject } from '@vue/composition-api'
import Grandson from './07.grandson.vue'
export default {
components: {
'grandson': Grandson
},
setup() {
const color = inject('themecolor')
return {
color
}
}
}
</script>

07.grandson.vue son 组件:

<template>
<div>
<h5 :style="{color: color}">grandson 组件</h5>
</div>
</template> <script>
import { inject } from '@vue/composition-api'
export default {
setup() {
const color = inject('themecolor')
return {
color
}
}
}
</script>

9.2 共享ref响应式数据

app.vue 根组件:

<template>
<div id="app">
<h1>父组件</h1>
<son></son>
</div>
</template> <script>
import { provide } from '@vue/composition-api'
import Son from './components/06.son.vue' export default {
name: 'app',
components: {
'son': Son
},
setup() {
provide('themecolor', 'red')
}
}
</script>

06.son.vue son 组件:

<template>
<div>
<h3 :style="{color: color}">son 组件</h3>
<grandson></grandson>
</div>
</template> <script>
import { inject } from '@vue/composition-api'
import Grandson from './07.grandson.vue'
export default {
components: {
'grandson': Grandson
},
setup() {
const color = inject('themecolor')
return {
color
}
}
}
</script>

07.grandson.vue son 组件:

<template>
<div>
<h5 :style="{color: color}">grandson 组件</h5>
</div>
</template> <script>
import { inject } from '@vue/composition-api'
export default {
setup() {
const color = inject('themecolor')
return {
color
}
}
}
</script>

10. 节点的引用 template ref

10.1 dom的引用

<template>
<div>
<h3 ref="h3Ref">TemplateRefOne</h3>
</div>
</template> <script>
import { ref, onMounted } from '@vue/composition-api' export default {
setup() {
// 创建一个 DOM 引用
const h3Ref = ref(null) // 在 DOM 首次加载完毕之后,才能获取到元素的引用
onMounted(() => {
// 为 dom 元素设置字体颜色
// h3Ref.value 是原生DOM对象
h3Ref.value.style.color = 'red'
}) // 把创建的引用 return 出去
return {
h3Ref
}
}
}
</script>

10.2 组件的引用

App父组件:

<template>
<div id="app">
<h1>父组件</h1>
<button @click="showComRef">展示子组件的值</button>
<son ref="comRef"></son>
</div>
</template> <script> import Son from './components/06.son.vue' export default {
name: 'app',
components: {
'son': Son
},
setup() {
const comRef = ref(null)
const showComRef = () => {
console.log(comRef)
console.log('str1的值是' + comRef.value.str1)
comRef.value.setStr1()
}
return {
comRef,
showComRef
}
}
}
</script>

06.son.vue子组件:

<template>
<div>
<h3 :style="{color: color}">son 组件</h3>
<p>{{str1}}</p>
</div>
</template> <script>
import { ref } from '@vue/composition-api'
export default {
setup() {
const str1 = ref('这是一个子组件!!')
const setStr1 = () => {
str1.value = '被赋值了'
}
return {
str1,
setStr1
}
}
}
</script>

11 nextTick

<template>
<div>
<h3>09.nextTick 组件</h3>
<p>学习 $nextTick</p>
<button v-if="isShowInput === false" @click="showInput">展示文本框</button>
<input type="text" v-else ref="ipt">
</div>
</template> <script>
export default {
data() {
return {
isShowInput: false
}
},
methods: {
showInput() {
this.isShowInput = !this.isShowInput
// console.log(this.$refs)
this.$nextTick(() => {
this.$refs.ipt.focus()
})
}
}
}
</script>

VUE3.x 前瞻的更多相关文章

  1. JavaScript:正则表达式 前瞻

    正向前瞻:用来捕获出现在特定字符之前的字符,只有当字符后面跟着某个特定字符才去捕获它.(?=) 负向前瞻:它用匹配只有当字符后面不跟着某个特定字符时才去匹配它.(?!) 在执行前瞻和负向前瞻之类的运算 ...

  2. R0:前瞻

    原文链接http://www.wangafu.net/~nickm/libevent-book/Ref0_meta.html Libevent使用手册:前瞻 总览: Libevent是一个用来写高性能 ...

  3. cloudstack4.4新增功能前瞻

    cloudstack4.4.0新功能前瞻 转载请注明地址:http://blog.csdn.net/zt689/article/details/37698989 1.   cloudstack4.4. ...

  4. 2016 SyScan360 国际前瞻信息安全会议 多角度探讨信息安全

    SyScan360国际前瞻信息安全会议由与中国第一大互联网安全公司-360公司与SyScan前瞻信息安全技术年会(TheSymposiumonSecurityforAsiaNetwork,以下简称Sy ...

  5. JS 正则表达式否定匹配(正向前瞻)

    引言:JS 正则表达式是 JS 学习过程中的一大难点,繁杂的匹配模式足以让人头大,不过其复杂性和其学习难度也赋予了它强大的功能.文章从 JS 正则表达式的正向前瞻说起,实现否定匹配的案例.本文适合有一 ...

  6. JUnit5 技术前瞻

    更多原创测试技术文章同步更新到微信公众号 :三国测,敬请扫码关注个人的微信号,感谢! 原文链接:http://www.cnblogs.com/zishi/p/6868495.html   JUnit ...

  7. 护航者,腾讯云: 2017年度游戏行业DDoS态势报告—回溯与前瞻

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 作者:腾讯游戏云 前言 自14年开始,全球DDoS攻击持续爆发,攻击峰值不断创记录.2017年,这种依靠超大流量不断冲击服务器和带宽造成业务 ...

  8. vue3+typescript引入外部文件

    vue3+typescript中引入外部文件有几种方法 (eg:引入echarts) 第一种方法: 1 indext.html中用script引入 <div id="app" ...

  9. 预计2019年发布的Vue3.0到底有什么不一样的地方?

    摘要: Vue 3.0预览. 原文:预计今年发布的Vue3.0到底有什么不一样的地方? 作者:小肆 微信公众号:技术放肆聊 Fundebug经授权转载,版权归原作者所有. 还有几个月距离 vue2 的 ...

随机推荐

  1. UGUI 特效怎样在UI上裁剪

    刚好碰到有人问怎样把粒子特效放到 UI 上并且能正确被 Mask 裁剪, 首先想到给粒子效果的 Shader 添加模板模仿一般 UI 的模板方式, 应该就能正确裁剪了吧, 不过没那么简单, 我们看到在 ...

  2. ssh_crm项目

    1.代码 https://pan.baidu.com/s/1hudAhA8  密码:c7xu 2.总结 https://pan.baidu.com/s/1o9ArFf0 密码:hteu 3.资料 ht ...

  3. .net设计模式

    1.单例模式 public sealed class Singleton { static intance=null; static readonly object padlock=new objec ...

  4. 在 Mac/Windows 系统中使用 Laradock 搭建基于 Docker 的 Laravel 开发环境 (改)

    开篇 Use Docker First And Learn About It Later 简介 Laradock 是为 Docker 提供的完整 PHP 本地开发环境,和 Homestead 一样提供 ...

  5. 总结了一下 Vue.nextTick() 的原理和用途

    对于 Vue.nextTick 方法,自己有些疑惑.在查询了各种资料后,总结了一下其原理和用途,如有错误,请不吝赐教. 概览 官方文档说明: 用法: 在下次 DOM 更新循环结束之后执行延迟回调.在修 ...

  6. NSArary自定义对象排序 NSComparator, compare

    reference from :http://mobile.51cto.com/hot-434804.htm 1.构建Person类 Person.h @interface Person : NSOb ...

  7. C#中的扩展类的理解

    扩展类是一种静态的一种类的调用方法,通过实例化进行调用.利用this进行指正该类,有参数的时候直接在后面追加参数. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ...

  8. python实现PCA算法原理

    PCA主成分分析法的数据主成分分析过程及python原理实现 1.对于主成分分析法,在求得第一主成分之后,如果需要求取下一个主成分,则需要将原来数据把第一主成分去掉以后再求取新的数据X’的第一主成分, ...

  9. Jquery制作插件---内容切换

    //需求:点击左右导航箭头,实现内容的切换 //代码如下 <!DOCTYPE html> <html lang="en"> <head> < ...

  10. 吴裕雄--天生自然JAVA面向对象高级编程学习笔记:继承的应用

    class Array{ // 表示数组 private int temp[] ; // 整型数组 private int foot ; // 定义添加位置 public Array(int len) ...