目录
概要
随着vue3.0的发布,不久后vue3.2紧接着发布了,现在uniapp也支持了vue3.2的编译。vue3.x的优点我在这里就不多说了,了解更多到uniapp官方vue3的教程。
从学习前端开始,学习的主要框架就是vue,一直以来也是vue的忠实粉丝。现在3.x的发布,让我感觉到它用在移动端上面是目前最好的选择,毕竟不需要考虑ie兼容。uniapp本身初衷就是为移动端而生,所以vue3.x用在uniapp上面,简直就是完美至极。
目前vue3.2在uniapp中暂时只支持h5,小程序端目前只支持到vue3.0,这只是时间的问题,uniapp的小程序肯定会支持vue3.2的,那么我们可以先拿h5来预热吧!uniapp中的vue3.2的用法在vue-cli脚手架项目中是完全一样,放心学习。
vue3.2改进了 setup语法糖,怎么使用怎么爽! vue3.2的一些特性在vue3.0的基础上做出了改动,这篇文章直接总结vue3.2的特性,接下来就让我们快速体验vue3.2。
下面讲解的内容不局限于vue3.2做出的改动,部分写法已在vue3.0中改动。
拉开序幕的setup语法糖
从vue3.2开始setup直接写在script标签上面,意味着所有的js代码直接在script中间完成。setup语法糖在vue的将来绝对是一种趋势,而且这种趋势已经到来。
<script setup> </script> 是一种编译时语法糖,可在 SFC 内使用Composition API 时极大地提升工作效率。在script 中声明的 js变量,template模板中可以直接读取使用,后面会有大量相关案例展示。
生命周期
虽然3.x写法上与2.x的script里面的代码相差很大,但是生命周期还是必不可少,毕竟在开发的过程中还是有需求不同阶段进行处理逻辑。
特性:在2.x的生命周期钩子前面加上“on”来访问组件的生命周期钩子。 了解更多vue3.x生命周期钩子
<script setup>
import { onBeforeMount, onMounted } from 'vue';
onBeforeMount(() => {
console.log('onBeforeMount生命周期')
})
onMounted(() => {
console.log('onMounted生命周期')
})
</script>
vue2.x与vue3.x生命周期的区别:
选项式 API | Hook inside setup |
---|
beforeCreate | Not needed* | created | Not needed* | beforeMount | onBeforeMount | mounted | onMounted | beforeUpdate | onBeforeUpdate | updated | onUpdated | beforeUnmount | onBeforeUnmount | unmounted | onUnmounted | errorCaptured | onErrorCaptured | renderTracked | onRenderTracked | renderTriggered | onRenderTriggered | activated | onActivated | deactivated | onDeactivated |
Tips: 因为setup 是围绕beforeCreate 和 created 生命周期钩子运行的,所以不需要显式地定义它们。换句话说,在这些钩子中编写的任何代码都应该直接在 setup 函数中编写。
ref函数与reactive函数对比
- 从定义数据类型角度区分:
- ref用来定义:基本数据类型 。
- reactive用来定义:对象(或数组)类型数据 。
- 备注:ref也可以用来定义对象(或数组)类型数据,其内部会自动通过
reactive 转换代理对象。 - 从原理角度区分:
- ref通过
Object.defineProperty() 的get 与set 来完成响应式(数据劫持)。 - reactive通过使用Proxy 来实现响应式(数据劫持),并通过Reflect操作源对象内部的数据。
- 从使用角度区分:
- ref定义的数据:在js中操作数据需要.value,template模板中读取数据不需要.value:
const v = ref(999);
consle.log(v.value);// 这样获取的值是 999
- reactive定义的数据:操作数据与读取数据:均不需要.value。
const data = reactive({
a:1,
b:2
});
consle.log(data);// 这样获取的值是{a:1,b:2}
computed计算属性
computed与vue2.x的配置项一致
<template>
<view class="content">
<view>{{fullname1}}</view>
<view>{{fullname2}}</view>
</view>
</template>
<script setup>
import { reactive,computed } from 'vue'
let person = reactive({
firstName:'尤',
lastName:'大'
});
// 计算属性-简写
const fullname1 = computed(()=>{
return `${person.firstName}-${person.lastName}`
})
// 计算属性-完整
const fullname2 = computed({
get(){
return `${person.firstName}-${person.lastName}`
},
set(value){
const nameArr = value.split('-')
person.firstName = nameArr[0]
person.lastName = nameArr[1]
}
})
</script>
监视(watch、watchEffect)
1. watch函数
情况一: 监视单个ref定义的响应式数据:
<script setup>
import { ref } from 'vue'
const v1 = ref(1);
const v2 = ref(2);
watch(v1, (newValue, oldValue) => {
console.log('v1====', newValue, oldValue)
},{immediate:true})
watch(v2, (newValue, oldValue) => {
console.log('v2====', newValue, oldValue);
})
</script>
情况二: 监视多个ref定义的响应式数据:
<script setup>
import { ref } from 'vue'
const v1 = ref(1);
const v2 = ref(2);
watch([v1,v2], (newValue, oldValue) => {
console.log('v1====', newValue, oldValue);
})
</script>
情况三: 监视多个reactive定义的响应式数据:
- 注意: watch监视的是reactive定义的响应式数据,则强制开启了深度监视,也就是说设置
{deep:false} 无效。
<script setup>
import { ref, reactive } from 'vue'
let data = reactive({
a: 1,
b: 2,
c:{
sss:'yes'
}
});
watch(data, (newValue, oldValue) => {
console.log('v1====', newValue, oldValue);
})
</script>
情况四: 监视reactive定义的响应式数据中的某个属性:
<script setup>
import { ref, reactive } from 'vue'
let data = reactive({
a: 1,
b: 2,
c:{
sss:'yes'
}
});
watch(() => data.a, (newValue, oldValue) => {
console.log('监视reactive定义的响应式数据中的某个属性a:', newValue, oldValue)
})
watch(() => data.c.sss, (newValue, oldValue) => {
console.log('监视reactive定义的响应式数据中的某个属性sss:', newValue, oldValue)
})
</script>
情况五: 监视reactive定义的响应式数据中的多个属性:
<script setup>
import { ref, reactive } from 'vue'
let data = reactive({
a: 1,
b: 2,
c:{
sss:'yes'
}
});
watch([() => data.a,() => data.c.sss], (newValue, oldValue) => {
console.log('监视reactive定义的响应式数据中的多个属性a和sss:', newValue, oldValue)
})
</script>
情况六: 监视reactive定义的数组:
<script setup>
import { reactive } from 'vue'
const list = reactive([1,2,3])
watch(()=>[...list], (newValue, oldValue) => {
console.log('监视数组:', newValue, oldValue)
})
</script>
情况七: 监视vuex中的值:
<script setup>
import { useStore } from 'vuex'
const store = useStore()
console.log('store',store.state.count)
watch(()=>store.state.count, (newValue, oldValue) => {
console.log('监视vuex中的值:', newValue, oldValue)
})
</script>
2. watchEffect函数
- watchEffect与computed相似:
- 但computed注重的计算出来的值(回调函数的返回值),所以必须要写返回值。
- 而watchEffect更注重的是过程(回调函数的函数体),所以不用写返回值。
- watch的套路是:既要指明监视的属性,也要指明监视的回调。
- watchEffect的套路是:不用指明监视哪个属性,监视的回调中用到哪个属性,那就监视哪个属性。
<script setup>
import { ref, reactive, watchEffect } from 'vue'
const v1 = ref(0)
let data = reactive({
a: 1,
b: 2
})
watchEffect(() => {
console.log(v1.value)
console.log(data)
})
</script>
组件传值
1. props/emit
- vue3.2子组件中使用defineProps接受父组件的值,使用defineEmits向父组件传递方法。
父组件father.vue
<template>
<view>
父亲的值:{{v}}
<Son :v="v" @change="change"></Son>
</view>
</template>
<script setup>
import { ref } from 'vue'
import Son from './components/son.vue'
const v = ref(0);
function change(){
v.value++;
}
</script>
子组件son.vue
<template>
<view class="son">
son中接受父亲的值:{{v}}
<button type="default" @click="change">子组件的按钮</button>
</view>
</template>
<script setup>
import { defineProps, defineEmits } from 'vue'
defineProps({
v:Number
})
const emits = defineEmits(['change'])
function change(){
emits('change')
}
</script>
provide/inject
- provide/inject算是props的加强版,父组件用provide 提供数据,所有子组件可以通过inject获取这些数据,父组件不需要知道哪些子组件使用它provide的数据。
基本套路:
// 父组件中
provide('值',值);
// 子组件中
const v = inject('值');
注意:
- provide也可以传递普通数据,但是传递ref或reactive定义的数据才具有响应性。
- 不同于props,provide是双向数据流,即可以在子组件里修改父组件传递过来的值。
- 如果不想让子组件修改父组件传递的值,使用readonly,下面有示例。
父组件father.vue
<template>
<view>
父亲的值:{{v}}
<Son :v="v" @change="change"></Son>
</view>
</template>
<script setup>
import { ref, defineComponent } from 'vue'
import Son from './components/s.vue'
const v = ref(0);
function change(){
v.value++;
}
</script>
子组件son.vue
<template>
<view class="son">
<text>从父组件读取的值:{{count}}</text>
<grandChild></grandChild>
</view>
</template>
<script setup>
import { inject } from 'vue'
import grandChild from './grandChild.vue'
const count = inject('count')
</script>
孙组件grandChild.vue
<template>
<view class="grandChild">
<text>孙组件接收爷爷的值:{{count}}</text>
</view>
</template>
<script setup>
import { inject } from 'vue'
const count = inject('count')
setTimeout(()=>{
count.value = 10;// 3秒之后,发现值都变了,证明了上面注意中的第二点
},3000)
</script>
readonly
<script setup>
import { readonly } from 'vue';
const count = ref(1);
provide('count',readonly(count));
</script>
style样式使用v-bind绑定动态值
- 以前在做项目的时候,有场景就想着style中可以绑定js中的动态值,没想到vue3.2中就支持了,爽歪歪!
- v-bind 在 SFC 标签中启用组件状态驱动的动态 CSS 值。
<template>
<view class="content">
<text class="txt">带颜色的文字</text>
</view>
</template>
<script setup>
import { ref } from 'vue';
const color = ref('red');
const size = ref('60px');
</script>
<style scoped>
.txt {
color: v-bind(color);
font-size: v-bind(size);
}
</style>
获取路由信息
注意: uniappp中获取路由信息的方式不能用useRoute和useRouter,官方给出的方案是用getCurrentPages,如下:
<script setup>
var pages = getCurrentPages();
var page = pages[pages.length - 1];
console.log(page);
</script>
vue-cli脚手架搭建的项目可以使用useRoute和useRouter,如下:
<script setup>
import { useRoute, useRouter } from 'vue-router'
const r1 = useRoute();
const r2 = useRouter();
console.log(r1,r2);
</script>
全局API的转移
1. vue2.x中部分全局API和配置
比如:注册全局组件、注册全局指令等。
//注册全局组件
Vue.component('MyButton', {
data: () => ({
count: 0
}),
template: '<button @click="count++">Clicked {{ count }} times.</button>'
})
//注册全局指令
Vue.directive('focus', {
inserted: el => el.focus()
}
2. vue3.x中对这些API做出了调整
将全局的API,即:Vue.xxx调整到应用实例(app)上。
2.x 全局 API(Vue ) | 3.x 实例 API (app ) |
---|
Vue.config.xxxx | app.config.xxxx | Vue.config.productionTip | 移除 | Vue.component | app.component | Vue.directive | app.directive | Vue.mixin | app.mixin | Vue.use | app.use | Vue.prototype | app.config.globalProperties |
Composition API 的优势
1. vue2.x中的Options API 存在的问题
使用传统Options API中,新增或者修改一个需求,就需要分别在data,methods,computed里修改。
1. vue2.x中的Composition API的优势
使用Composition API中,我们可以更加优雅的组织我们的代码,函数。让相关功能的代码更加有序的组织在一起。
关注我,不迷路
小伙伴,用你可爱的小手,点个赞,关注我了解更多知识!!!
如果任何疑问的可以在评论区留言或者私聊。
也可以扫下面二维码加我wx,备注‘地区-名字-技术类型’,我会拉进我的微信技术分享群。注意:必须备注清楚哈。
也可以加QQ群交流:568984539,加群备注‘地区-名字-技术类型’。
更多前端、uniapp、nodejs等相关知识可关注我个人博客:https://blog.csdn.net/qq_42961150?spm=1011.2124.3001.5343
|