Vue 之 vue3 的一些新特性的知识梳理(主要是在setup 语法糖中的语法编写,含vuex 4状态管理vue-router 4路由管理)
Posted zhuangwei_8256
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vue 之 vue3 的一些新特性的知识梳理(主要是在setup 语法糖中的语法编写,含vuex 4状态管理vue-router 4路由管理)相关的知识,希望对你有一定的参考价值。
vue3的一些新特性(含vue2的实现)
前言
如果有对vue还不熟悉的小伙伴,建议先看Vue 之 Vue 的基础知识汇总 —— 总结一。
基础语法几乎不变,例如:
- 插值
- 一系列的指令(
v-text、v-html、v-if、v-show、v-for
等)
下面是vue3
的简单介绍:
特此说明,一切以vue官方文档为准,本文只是做新特性的知识梳理(含
vuex 4
状态管理、vue-router 4
路由管理)。
组合式API
以及 单文件组件组合式 API 语法糖 (<script setup>)
是我们关注的重点。
正文
setup
setup
语法糖是vue3
新增的一大重点新特性,它将颠覆vue2
的一些语法的写法,例如:定义响应式数据、定义方法、计算属性computed、监听属性watch、生命周期、组件通信等。
注:以下内容都是在
setup
语法糖的前提下的实现方式。
主要是在以下两种方式:
单文件组件组合式 API 语法糖 (<script setup>)
<script setup>
</script>
组合式API
这种方式可以延续使用vue2
的写法,不受任何影响,关于setup
新增的语法可以在setup()方法中编写:
<script>
export default
name: '',
data() // 定义响应式数据
return
,
setup()
// 编写关于setup新增的语法,最终需将被组件使用的属性和方法 给return 出去
return
...
,
watch: , // 监听属性
computed: , // 计算属性
mounted() , // mounted生命周期
methods:
// 定义方法
</script>
下面正式介绍在setup
语法糖中的新语法的代码编写。
开始之前
这里需要注意的是,在
setup
语法中是没有this
的,这也就意味着:我们在使用或者赋值响应式数据、使用方法时,不能通过this.xxx
的方式获取,而是通过xxx.value
的方式获取以及赋值
定义响应式数据
具体请看官方文档
以下只是列了常用的定义响应式数据的方式:
ref、reactive
这两种好理解
- 解释一下
toRef, toRefs
:toRef
:官方解释是可以用来为源响应式对象上的某个 property 新创建一个 ref。然后,ref 可以被传递,它会保持对其源 property 的响应式连接。
大白话就是通过对象新创建了一个 ref,这个 ref 的值和原对象的 property 保持一致,也就是说,当对象中的 property 改变了,与这个property 通过 toRef 连接的新 ref 也会改变。toRefs
:官方解释是将响应式对象转换为普通对象,其中结果对象的每个 property 都是指向原始对象相应 property 的 ref。
大白话就是通过对象新创建了一个 reactive,这个 reactive 的每一个property 和原对象对应的 property 保持一致,也就是说,当对象中的 property 改变了,与这个 property 通过 toRefs 连接的新 reactive 的 property 也会改变。
注:toRef, toRefs可以用来解决props 组件通信时的响应式问题,详见下方的组件通信
<script setup>
import ref, reactive, toRef, toRefs from 'vue'
// 使用ref定义相关响应式数据,需先从vue中引入ref
let str = ref('aa')
let num = ref(3)
let bool = ref(true)
let arr1 = ref([])
let arr2 = ref([1, 2, 3])
// 使用reactive 定义对象响应式数据,需先从vue中引入reactive
let obj1 = reactive()
let obj2 = reactive(
id: 00202204240001,
name: 'vue3'
)
let id = toRef(obj2, 'id')
let obj3 = toRefs(obj2)
</script>
定义方法
<script setup>
import ref from 'vue'
let str = ref('aa')
// 定义方法
const changeStr = () =>
str.value = 'bb' // 这里需要通过xxx.value的方式获取、赋值响应式数据
</script>
计算属性 computed
<script setup>
import ref, computed from 'vue'
const num = ref(3)
const newNum = computed(() => num.value * 2) // 使用了箭头函数省略return 的写法
num.value++
console.log(num.value) // 4
console.log(newNum.value) // 8
</script>
监听属性 watch
<script setup>
import ref, watch from 'vue'
let num = ref(0)
watch(num, (newValue, oldValue) =>
console.log('The new num value is: ' + num.value)
)
</script>
生命周期
选项式 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 |
<script setup>
// 需先将生命周期函数引入
import onMounted from 'vue'
onMounted(() =>
console.log('Component is mounted!')
// 调接口
)
</script>
组件通信
- 父组件
<template>
<!-- 父组件向子组件传参 -->
<HelloWorld :msg="msg" @getMsg="getMessage" :isShow="isShow"/>
<br>
<button @click="changIsShow">changIsShow</button>
</template>
<script setup>
// 将组件引入之后可以直接在 template 中使用
import HelloWorld from "@/components/HelloWorld.vue"
import ref from "vue"
let msg = ref("父组件向子组件传参")
let isShow = ref(true)
const getMessage = emitMsg =>
console.log('子组件向父组件传参', emitMsg) // 子组件向父组件传参
const changIsShow = () =>
isShow.value = !isShow.value
</script>
- 子组件
<template>
<h1> msg </h1>
<h2> message </h2>
<h2 v-show="isShow"> isShow </h2>
<button @click="changeMsg">change</button>
</template>
<script setup>
import ref, toRefs, toRef, watch from "vue"
let props = defineProps(
msg: String,
isShow: Boolean
)
console.log(1111, props.msg) // 打印的就是传过来的msg的值:父组件向子组件传参
let message = ref(props.msg)
// 1、toRefs时将props的每个property与新数据做响应式连接
let msg = toRefs(props)
// 2、而toRef则是将props的单个property与新数据做响应式连接
let isShow = toRef(props, 'isShow')
const emit = defineEmits(["getMsg"])
const changeMsg = () =>
message.value = message.value + " ====> emit"
emit("getMsg", message) // 然后向父组件传参
watch(isShow, (newVal) =>
if(newVal)
console.log('true', isShow);
else
console.log('false', isShow);
)
</script>
ref(属性)
这个
ref
是指属性ref
,不是定义响应式数据的ref
,但是还是要依赖响应式数据的ref Api
去实现。
vue2
中ref
属性的写法,在js
代码中是通过 this.$refs.xxx
的方式获取,但是vue3
由于setup
语法糖中没有没有this
,所以我们需要依赖ref Api
去实现。
<template>
<div ref="divDom">divDom</div>
<button @click="getRef">获取ref属性</button>
</template>
<script setup>
import ref from 'vue'
let divDom = ref(null)
const getRef = () =>
console.log(divDom.value);
divDom.value.style.color = 'red'
</script>
router
-
router/index.js
-
vue-router 4
import createRouter, createWebHashHistory from "vue-router" const router = createRouter( // 内部提供了 history 模式的实现。为了简单起见,我们在这里使用 hash 模式。 history: createWebHashHistory(), routes: [...] // 路由数组 ) export default router
-
vue-router 3
import Vue from "vue" import VueRouter from "vue-router" Vue.use(VueRouter) const router = new VueRouter( mode: "hash", routes: [...], // 路由数组 ) export default router
-
-
某列表组件
<script setup>
import ref, watch from 'vue'
import useRouter, useRoute from 'vue-router'
const router = useRouter() // 和 vue2中的this.$router 是一样的
const toDetail = (id) =>
router.push(
path: `/detail`
query:
id: id
)
const route = useRoute() // 和 vue2中的this.$route 是一样的
watch(route, () =>
// ...
)
</script>
detail.vue
<script setup>
import ref, onMounted from 'vue'
import useRoute from 'vue-router'
const route = useRoute() // 和 vue2中的this.$route 是一样的
let currentId = ref('')
onMounted( () =>
currentId.value = route.query.id
)
</script>
vuex
tabsView.js modules
注:
state
在vuex3
中是一个对象的命名方式,而在vuex4
中是一个函数的命名方式。
/**
* 顶部页签栏
*/
// vuex3命名state
// const state =
// tabList: [], // 页签数组
//
// vuex4命名state
const state = () =>
return
tabList: [], // 页签数组
const getters =
navList: (state) =>
return state.tabList.filter(item => item.isNav)
const mutations =
ADDTAB()
const actions =
removeTab()
export default
namespaced: true, // 开启命名空间
state,
getters,
mutations,
actions,
store
出口文件index.js
此代码是使用了
vuex-persistedstate
对state
进行了持久化处理,详见Vue 之 vuex 解决刷新页面 state 数据丢失的问题,使用vuex-persistedstate进行state持久化
import createStore from "vuex"
import createPersistedState from "vuex-persistedstate"
import tabsView from "./modules/tabsView"
const tabListState = createPersistedState(
storage: window.sessionStorage,
paths: ["tabsView.tabList"],
)
const store = createStore(
modules:
tabsView,
,
plugins: [tabListState],
)
export default store
- 某组件中
<script setup>
import ref from 'vue'
import useStore from 'vuex'
let store = useStore() // 和vue2中的this.$store是一样的
// 只不过需要注意的是:
// state、getter 是在 computed 计算属性中获取
// 使用 state
let tabList = computed(() => store.state.tabsView.tabList)
// 使用 getter
let navList = computed(() => store.getters.tabsView.navList)
// mutations、actions 则直接使用箭头函数return即可
// 使用 mutation
const ADDTAB = () => store.commit('tabsList/ADDTAB', 123),
// 使用 action
const removeTab = () => store.dispatch('tabsList/removeTab', 321)
</script>
写在末尾
一切以官方文档为准,本文只是就 vue3、vuex 4状态管理、vue-router 4路由管理的一些新特性做了简单的知识梳理;
如有错误,欢迎指出。谢谢。
如有不足,望大家多多指点! 谢谢!
以上是关于Vue 之 vue3 的一些新特性的知识梳理(主要是在setup 语法糖中的语法编写,含vuex 4状态管理vue-router 4路由管理)的主要内容,如果未能解决你的问题,请参考以下文章