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>


生命周期

选项式 APIHook inside setup
beforeCreateNot needed*
createdNot needed*
beforeMountonBeforeMount
mountedonMounted
beforeUpdateonBeforeUpdate
updatedonUpdated
beforeUnmountonBeforeUnmount
unmountedonUnmounted
errorCapturedonErrorCaptured
renderTrackedonRenderTracked
renderTriggeredonRenderTriggered
activatedonActivated
deactivatedonDeactivated
<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去实现。

  vue2ref 属性的写法,在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

vue-router4官网

  • 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

vuex4官网

  • tabsView.js modules

注:statevuex3 中是一个对象的命名方式,而在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-persistedstatestate 进行了持久化处理,详见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>



写在末尾

一切以官方文档为准,本文只是就 vue3vuex 4状态管理vue-router 4路由管理的一些新特性做了简单的知识梳理;


如有错误,欢迎指出。谢谢。


如有不足,望大家多多指点! 谢谢!

以上是关于Vue 之 vue3 的一些新特性的知识梳理(主要是在setup 语法糖中的语法编写,含vuex 4状态管理vue-router 4路由管理)的主要内容,如果未能解决你的问题,请参考以下文章

vue3.x新特性之setup函数,看完就会用了

Vue3 的 Reactive 响应式到底是什么

Vue3基础知识总结

Vue3基础知识总结

Vue3基础知识总结

Vue3.0 的新特征 | Vue3.0 面试题总结