Vue3新特性 尝鲜 真香
官方还没有正式推出来,利用@vue/composition-api先预热一下初始化项目npm install -g @vue/clivue create vue3npm install @vue/composition-api --save// main.js 导入import VueComposition from '@vue/composition-api'Vue.use...
官方还没有正式推出来,利用@vue/composition-api
先预热一下
初始化项目
npm install -g @vue/cli
vue create vue3
npm install @vue/composition-api --save
// main.js 导入
import VueComposition from '@vue/composition-api'
Vue.use(VueComposition)
一、setup
setup是专门为使用vue3的composition-api
新特性开放的统一入口
1.1 执行时机
beforeCreate 与 created 之间
可以新建一个模块,如下操作
import {} from "@vue/composition-api";
export default {
setup() {
console.log("setup");
},
beforeCreate() {
console.log("beforeCreate");
},
created() {
console.log("created");
},
1.2 接收props数据
// 父
<setup :page = "1"></setup>
// 子
props: {
page: { type: Number }
},
setup(props) {
console.log(props.page); // 1 props必须声明
},
1.3 context
执行上下文,在setup中它可以取代this,因为在setup上是取不到this的
setup(props,context) {
// console.log("setup");
// console.log(props.page);
console.log(context,"ctx")
},
二、reactive
可以创建多个响应式的数据对象
setup.vue
<template>
<div class="wrapper">
<p>count:{{count}}</p> // 没有state.count
<button @click="count+=1">+1</button>
</div>
</template>
<script>
import { reactive } from "@vue/composition-api";
export default {
props: {
page: { type: Number }
},
setup(props,context) {
// console.log("setup");
// console.log(props.page);
// console.log(context,"ctx")
const state = reactive({count:0})
state.count += 1;
console.log(state)
return state;
},
beforeCreate() {
// console.log("beforeCreate");
},
created() {
// console.log("created");
},
components: {},
data() {
return {};
},
};
</script>
<style lang="css" scoped>
.wrapper {
}
</style>
三、ref
3.1 ref()
根据给定的值,创建响应式的数据对象,返回值是一个对象,且只有value。
建议使用ref创建,不提倡reactive
ref.vue
<template>
<div class="wrapper">
<div>{{a}}</div> // 不需要a.value
<button @click="a+=1">+1 ref</button>
</div>
</template>
<script>
import { ref } from "@vue/composition-api";
export default {
setup(){
const a = ref(0)
console.log(a.value)
return {
a
}
},
components:{},
props:{},
data(){
return {
}
},
}
</script>
<style lang="css" scoped>
.wrapper{}
</style>
3.2 在reactive中访问ref创建的响应式对象
setup(){
const b =ref (1)
const state = reactive({
b
})
console.log(b)
}
3,3 ref覆盖
const c1 = ref(2)
const state = reactive({
c1
})
const c2 = ref(9)
state.c1 = c2
state.c1++
console.log(state.c1) // 10
console.log(c2.value) // 10
console.log(c1.value) // 2
3.4 isRef
判断某个值是ref()创建
import { isRef } from "@vue/composition-api"
console.log(isRef(c2) ? c2.value : c2)
3.5 toRefs
toRefs函数能将reactive创建的响应式对象,转化成为普通的对象,只不过,这个对象上的每个节点,都是ref()类型的响应式数据
<template>
<div class="wrapper">
<div>count: {{count}}</div>
<button @click="add">+1</button>
</div>
</template>
<script>
import { reactive ,isRefs, toRefs} from "@vue/composition-api";
export default {
setup(){
const state = reactive({count:0,name:'yp'});
// 定义+1方法
const add =()=>{
state.count += 1;
}
return {
//...state, // reactive 展开运算符后就不响应了
...toRefs(state),
add
}
},
data(){
return {
}
},
watch:{},
computed:{},
}
</script>
<style lang="css" scoped>
.wrapper{}
</style>
四、computed
computed()函数用来创建计算属性,返回的是个ref实例
4.1 只读属性
<template>
<div class="wrapper">
<p>count:{{refCount}}</p>
<p>计算属性:{{computedCount}}</p>
<button @click="refCount+=1">+1</button>
</div>
</template>
<script>
import { ref,computed } from "@vue/composition-api";
export default {
setup(){
const refCount = ref(0)
const computedCount = computed(()=> refCount.value+1)
// computedCount=2
return {
refCount,
computedCount
}
},
components:{},
props:{},
data(){
return {
}
},
}
</script>
<style lang="css" scoped>
.wrapper{}
</style>
4.2 可读可写
<template>
<div class="wrapper">
<p>count:{{refCount}}</p>
<p>计算属性:{{computedCount}}</p>
<button @click="refCount+=1">+1</button>
</div>
</template>
<script>
import { ref, computed } from "@vue/composition-api";
export default {
setup() {
const refCount = ref(0);
// const computedCount = computed(()=> refCount.value+1)
// computedCount=2
const computedCount = computed({
get: () => refCount.value + 1,
set: a => {
refCount.value = a + 112;
}
});
computedCount.value = 33;
return {
refCount,
computedCount
};
},
components: {},
props: {},
data() {
return {};
}
};
</script>
<style lang="css" scoped>
.wrapper {
}
</style>
五、watch
监视数据变化,做响应处理。组件创建,默认会执行一次,可配置项
5.1 基本用法
import { watch,ref, set } from "@vue/composition-api";
export default {
setup(){
const refCount = ref(0)
watch(()=>console.log(refCount.value))
setTimeout(()=>{
refCount.value += 2;
},1000)
},
data(){
return {
}
},
}
5.2 监听指定数据源
ref
const count = ref(2)
watch(count,(count,oldCount)=>{
console.log(count,oldCount)
})
setTimeout(() => {
count.value += 2;
}, 1000);
// 2 undefined
// 4 2
reactive
setup() {
const state = reactive({ count: 0 });
watch(() => state.count, (count, oldCount) => console.log(count, oldCount));
setTimeout(() => {
state.count += 2;
}, 1000);
},
// 0 undefined
// 2 0
----------------------------------------
watch(
() => state.count,
(count, oldCount) =>{ console.log(count, oldCount)},
{lazy:true,} //组件第一次创建不调用
);
5.3 监视多个数据源
ref
const count = ref(0)
const name = ref('yp1')
watch(
[count,name],
([count,name],[oldCount,oldName])=>{
console.log(count)
console.log(name)
console.log('------------')
console.log(oldCount)
console.log(oldName)
},
{
lazy:true
}
)
setTimeout(()=>{
count.value++
name.value = "yp2"
})
// 1
// yp2
// ---------------------
// 0
// yp1
reactive
const state = reactive({count:0,name:'yp1'})
watch(
[()=>state.count,()=>state.name],
([count,name],[oldCount,oldName])=>{
console.log(count)
console.log(name)
console.log("---------------------")
console.log(oldCount)
console.log(oldName)
},
{
lazy: true
}
)
setTimeout(()=>{
state.count++
state.name = "yp2"
})
// 1
// yp2
// ---------------------
// 0
// yp1
5.4 取消监视
在setup()
函数内创建的watch监视,会在当前组件被销毁的时候自动停止。watch的返回值调用
两秒内点击按钮,取消了watch监听,可查 console
<template>
<div class="wrapper">
<div>{{count}}</div>
<button @click="stopwatch">stop</button>
</div>
</template>
<script>
import { watch, ref, set, reactive } from "@vue/composition-api";
export default {
setup() {
const count = ref(0)
const stop = watch(()=>{
console.log("监听到watch的变化"),
console.log(count.value)
}
)
setTimeout(() => {
count.value += 2
}, 2000);
const stopwatch = ()=>{
stop()
}
return {
count,
stopwatch
}
},
data() {
return {};
}
};
</script>
<style lang="css" scoped>
.wrapper {
}
</style>
5.5 watch 清除无效的异步
当watch
监视的值发生变化的时候,或者watch本身被stop()
之后,我们希望能够清除那些无效的异步任务,此时,watch
回调中提供一个cleanup registrator function
来执行清除的工作,
eg watch 被重复执行了 或者被强制stop
实际场景一:打开a.html 会执行a.html的页面的3个ajax请求;但是在有两个ajax请求还没有发出去的时候,用户打开b.html,那剩下的两个请求我就不需要再接着请求了
实际场景二:输入框按键输值请求
<!-- -->
<template>
<div>
<input type="text" v-model="kw">
</div>
</template>
<script>
import { ref, watch } from "@vue/composition-api";
export default {
name: "",
setup() {
const kw = ref("");
const asyncprint = val => {
return setTimeout(() => {
console.log(val);
}, 1000);
};
watch(
kw,
(kw, oldkw, callback) => {
const timeId = asyncprint(kw);
callback(()=>clearTimeout(timeId));
},
{ lazy: true }
);
return {
kw
};
},
data() {
return {};
},
created() {},
components: {},
computed: {},
mounted() {},
watch: {},
methods: {}
};
</script>
<style lang='css' scoped>
</style>
六、 LifeCycle Hooks
在setup()
中
vue2生命周期 | vue3生命周期 |
---|---|
beforeCreate | setup |
created | setup |
beforeMount | onBeforeMount |
mounted | onMounted |
beforeUpdate | onBeforeUpdate |
updated | onUpdated |
beforeDestory | onBeforeDestory |
destroyed | onUnmounted |
errorCaptured | onErrorCaptured |
建议异步请求,在onMounted()/mounted()
import { onBeforeMount,onMounted, } from "@vue/composition-api";
setup(){
onBeforeMount(()=>{
console.log("onBeforeMount")
});
onMounted(()=>{
console.log("onMounted")
})
}
七、provide & inject
7.1 共享普通数据
祖组件
import { provide } from '@vue/composition-api'
setup(){
provide('themeColor','red') // 键值
},
孙组件
import { inject } from '@vue/composition-api'
setup(){
const color = inject('themeColor');
return {
color: color,
}
},
7.2 共享ref()数据
祖组件
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png">
<h1>父组件</h1>
<button @click="color='red'">红色</button>
<button @click="color='yellow'">黄色</button>
<button @click="color='blue'">蓝色</button>
<hr>>
<child />
</div>
</template>
setup(){
const color = ref('red');
provide('themeColor',color)
return {
color
}
},
八、refs
8.1 元素引用
<!-- refs -->
<template>
<div>
<h3 ref="h3Ref">我是一个h3标签</h3>
</div>
</template>
<script>
import { ref , onMounted } from '@vue/composition-api'
export default {
name:'',
setup(){
const h3Ref = ref(null)
onMounted(()=>{
h3Ref.value.style.color = "red"
})
return {
h3Ref
}
}
}
8.2 组件的引用
子组件
<!-- refs -->
<template>
<div>
<h3 ref="h3Ref">我是一个h3标签</h3>
<p>{{str1}}</p>
</div>
</template>
<script>
import { ref , onMounted } from '@vue/composition-api'
export default {
name:'',
setup(){
const str1 = ref('this is 子组件')
const setStr = ()=>{
str1.value = "被赋值了---"
}
return {
str1,
setStr
}
}
}
</script>
<style lang='css' scoped>
</style>
父组件
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png">
<template-refs ref="childref"></template-refs>
<button @click="show">展示</button>
</div>
</template>
<script>
import { provide, ref } from "@vue/composition-api";
import templateRefs from "./components/template-refs";
export default {
name: "app",
setup() {
const childref = ref(null);
const show = () => {
childref.value.setStr() // 注意 .value 函数调用
console.log(childref);
console.log("str1的值是:" + childref.value.str1);
};
return {
childref,
show
};
},
components: {
templateRefs
}
};
</script>
<style>
#app {
font-family: "Avenir", Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
九、createComponent
非必需,完美配合typescript的类型推断的
gitHub:案例地址
更多推荐
所有评论(0)