前言
vue3.0 Rc
(候选公布版本)曾经于7月18
上线,离正式版本公布曾经不远了,鉴于此,自己就通过@vue/composition-api
这个 Vue Composition API
来当时体验下3.0的新个性,为当前能疾速上手新版本做筹备。
筹备工作
下载与引入
- 下载体验版api
npm i @vue/composition-api
- 引入与应用
1. 在main.js中要引入全副的api import VueCompositionApi from '@vue/composition-api' Vue.use(VueCompositionApi) 2. 在页面中按需引入api import { 须要应用的api } from '@vue/composition-api'
tips: main.js
和部分页面都须要引入,不能只在页面中引入。
开发与应用
reactive和toRefs
reactive
创立响应式数据,toRefs
把一般数据转换成响应式数据
<template> <div class="home"> <span>{{name}}</span> <span>{{num}}</span> <button @click="btn">按钮</button> <button @click="btn2">按钮2</button> </div></template><script>// reactive 创立响应式数据对象 --相似dataimport { reactive, toRefs } from '@vue/composition-api'export default { name: 'Home', setup () { // state对象 const state = reactive({ name: 'hello world' }) // modelData const modelData = reactive({ num: 1 }) const btn = () => modelData.num++ const btn2 = () => { state.name = '我是不双向绑定的数据,没有toRefs转换不可更改' return state } return { ...state, ...toRefs(modelData), //把数据转换为响应式 btn, // 事件 btn2 } }}</script>
tips:
- 在
setup
中是没有this
的- 数据、办法都写在
setup
外面。- 办法里扭转值需
return
这个值- 用了
...
运算符后应用reactive
创立进去的数据都不是响应式数据了,须要应用toRefs
转换为ref()
类型的响应式数据
ref(举荐)
- 和
reactive
一样创立响应式数据,但更举荐应用。
<template> <div class="RefCom"> <span>{{refCount}}</span> <button @click="refCount+=1">+1</button> </div></template><script>import { ref, reactive } from '@vue/composition-api'export default { name: 'RefCom', setup (props, { root }) { const refCount = ref(0) //创立响应式数据 console.log(refCount.value) const data = reactive({ refCount }) console.log(data.refCount) data.refCount++ console.log(data.refCount) return { ...data, refCount } }}</script>
- 模板上的ref--获取dom
//父组件<template> <div class="Father"> <h1 ref="h1Ref">父组件</h1> <som ref="somRef"></som> </div></template><script>import som from './Som'import { ref, onMounted } from '@vue/composition-api'export default { name: 'Father', components: { som }, setup (props, { root }) { const h1Ref = ref(null) //赋值null const somRef = ref(null) onMounted(() => { console.log(h1Ref.value, 'h1的dom') console.log(somRef.value, 'som的dom') }) return { h1Ref, //要和模板上ref值雷同 somRef } }}</script>
//子组件 <template> <div class="Som"> <h3>子组件</h3> </div></template><script>export default { name: 'som', setup (props, { root }) {}}</script>
tips:
ref
括号里的值就是refCount
的值,括号里的值能够是各种类型的值。- 在
setup
要通过xxx.value获取ref
转换的值。- 模板中无需通过xxx.value展现数据,间接{{xxx}}即可,在
return
时曾经进行了转换了。ref
包裹创立进去的值是个对象,外面就一个属性value
。- 用
reactive
包裹ref
创立的值不须要通过XXX.value拜访- 新的
ref
会笼罩旧的ref
的值- 通过
isRef
能够判断是否是ref
创立进去的。
computed
计算属性:可创立可读可写的计算属性。
<template> <div class="RefCom"> <span>原值:{{refCount}}</span> | <span> 计算属性值:{{ onlyReadComputed }} </span> | <button @click="refCount+=1">+1</button> </div></template><script>import { ref, computed } from '@vue/composition-api'export default { name: 'RefCom', setup (props, { root }) { const refCount = ref(0) // 只读的计算属性 const onlyReadComputed = computed(() => refCount.value + 1) // 可读可写的计算属性 const rwComputed = computed({ get: () => refCount.value + 1, set: value => { refCount.value = value - 1 } }) console.log(onlyReadComputed, '只读计算属性的值') rwComputed.value = 11 console.log(rwComputed, '可读可写计算属性的值') return { refCount, rwComputed, onlyReadComputed } }}</script>
watch
监听数据的变动
<template> <div class="RefCom"> <span>{{refCount}}</span> <span>{{name}}</span> <button @click="stopWatch">进行watch</button> <input v-model="inputValue" /> </div></template><script>import { ref, reactive, watch, toRefs } from '@vue/composition-api'export default { name: 'watch', setup (props, { root }) { const refCount = ref(0) const inputValue = ref('') const state = reactive({ name: '张总' }) /* ---监听单个--- */ // ref const stop = watch( refCount, (newValue, oldValue) => { console.log(refCount.value) console.log('新值:' + newValue, '旧的值:' + oldValue) } ) const stopWatch = () => { stop() } // reactive watch( () => state.name, (newValue, oldValue) => { // console.log(refCount.value) console.log('新值:' + newValue, '旧的值:' + oldValue) } ) /* ---监听多个--- */ watch( [() => refCount, () => state.name], ([newRefCount, newName], [oldRefCount, oldName]) => { console.log('newRefCount:' + newRefCount.value, 'newName:' + newName) console.log('oldRefCount:' + oldRefCount.value, 'oldName:' + oldName) } ) setTimeout(() => { refCount.value++ }, 1000) setTimeout(() => { state.name = '李总' }, 3000) // 异步打印 const asyncPrint = (val) => { return setTimeout(() => { console.log(val) }, 1000) } // ref watch( inputValue, (newValue, oldValue, clean) => { const timeId = asyncPrint(newValue) // 每当数据变动的时候革除定时器 clean(() => clearTimeout(timeId)) } ) return { ...toRefs(state), refCount, stopWatch, inputValue } }}</script>
tips:
ref
和reactive
的值的监听办法不同,reactive
需用办法返回值,() => xxx,ref
可间接应用。- 当监听多个时,不论是
ref
还是reactive
创立的值,都须要用办法返回- 在监听多个值时,用数组来解构新旧值时,新值和旧值别离在不同的数组里,和
vue2.x
不一样。watch
监听返回新值、旧值时还返回了个函数,以后函数在watch被反复执行
和stop
操作时产生,可做些革除操作。常见利用场景有防抖。- 防抖:就是对于频繁触发的事件增加一个延时同时设定一个最小触发距离,如果触发距离小于设定的距离,则革除原来的定时,从新设定新的定时;如果触发距离大于设定距离,则保留原来的定时,并设置新的定时;防抖的后果就是频繁的触发转变为触发一次
生命周期
- beforeCreate -> setup()
- created -> setup
- beforeMount -> onBeforeMount
- mounted -> onMounted
- beforeUpdate -> onBeforeUpdate
- updated -> onUpdated
- beforeDestroy -> onBeforeUnmount
- destroyed -> onUnmounted
- errorCaptured -> onErrorCaptured
<template> <div class="Father"> </div></template><script>import { onMounted, onUpdated, onBeforeUnmount } from '@vue/composition-api'export default { name: 'Father', setup (props, { root }) { onMounted(() => { console.log('onMounted') }) onUpdated(() => { console.log('onUpdated') }) onBeforeUnmount(() => { console.log('onBeforeUnmount') }) }}</script>
tips:
- 去除了
beforeCreate
和created
生命周期,间接就在setup
中,setup
执行程序 是beforeCreate
后,created
前- 其余生命周期就在本来前加上
on
,性能没有什么变动,且定义在setup
函数中- 举荐申请都放在
onMounted
中
依赖注入
- provide
//父组件<template> <div class="Father"> <h1>父组件</h1> <button @click="color='red'">红色</button> <button @click="color='blue'">蓝色</button> <button @click="color='yellow'">黄色</button> <som></som> </div></template><script>import som from './Som'import { provide, ref } from '@vue/composition-api'export default { name: 'Father', components: { som }, setup (props, { root }) { const color = ref('red') //响应式的值,父组件批改可影响子孙后代 //注入值 provide('color', color) return { color } }}</script>
//子组件 <template> <div class="Som"> <h3>子组件</h3> <Grandson /> </div></template><script>import Grandson from './Grandson'export default { name: 'som', components: { Grandson }, setup (props, { root }) { }}</script>
- inject
//孙子组件<template> <div class="Grandson"> <h5 :style="{color:color}">孙子组件</h5> </div></template><script>import { inject } from '@vue/composition-api'export default { name: 'Grandson', setup (props, { root }) { //接管值 const color = inject('color') return { color } }}</script>
路由跳转
<template> <div class="home"> <button @click="jump">跳转</button> </div></template><script>export default { name: 'Home', setup (props, { root }) { const jump = () => root.$router.push('/about') return { jump } }}</script>
tips:root
指代的就是vue
对象,即this
,且名字是不可更改的。
props
//父<template> <div class="about"> <h1>This is an about page</h1> <div>{{num}}</div> <button @click="btn">减少</button> <HelloWorld msg="我是props传进去的值" /> </div></template>//子<template> <div class="hello"> <h1>{{ msg }}</h1> </div></template><script>export default { name: 'HelloWorld', props: { msg: String }, setup (props) { console.log(props) }}</script>