Vue3基础
Vue3
Vue 3 是一个流行的开源JavaScript框架,用于构建用户界面和单页面应用。它带来了许多新特性和改进,包括更好的性能、更小的打包大小、更好的TypeScript支持、全新的组合式 API,以及一些新的内置组件。
Vue3的优势:
- 组合式API:这是Vue 3最重要的新特性之一,它允许更灵活、更逻辑化地组织代码。
- 更好的性能:Vue 3的虚拟DOM重写,提供了更快的挂载、修补和渲染速度。
- 更小的打包大小:由于新的架构和树摇技术,Vue 3的打包大小比Vue 2小。
- 更好的TypeScript支持:Vue 3在内部使用了TypeScript,因此它为开发者提供了更好的TypeScript支持。
使用create-vue创建项目
前置条件 - 已安装16.0或更高版本的Node.js
执行如下命令,这一指令将会安装并执行 create-vue
npm init vue@latest
vue3项目目录结构:
一、setup选项
在Vue 3中,你可以使用 setup
函数来使用组合式API。setup
函数是组件的入口点,在组件实例被创建和初始化之后,但在渲染发生之前被调用。
<script>// 数据 和 函数,需要在 setup 最后 return,才能模板中应用
export default {setup () {// console.log('setup函数', this)// 数据const message = 'hello Vue3'// 函数const logMessage = () => {console.log(message)}return {message,logMessage}},beforeCreate () {console.log('beforeCreate函数')}
}
</script>
在beforeCreate钩子之前执行,因此在setup()函数中获取不到this
script标签添加 setup标记,不需要再写导出语句,默认会添加导出语句
<script setup>const message = 'this is message'const logMessage = ()=>{console.log(message)}
</script>
二、reactive和ref函数
Vue 3提供了两个主要的函数来创建响应式数据:ref
和 reactive
。
1. ref
ref
函数创建一个响应式引用。在模板中,你可以直接使用响应式引用的值,而在JavaScript代码中,你需要通过 .value
属性来访问或修改它的值。
作用:接受对象类型数据的参数传入并返回一个响应式的对象
<script setup>// 导入import { ref } from 'vue'// 执行函数 传入参数 变量接收const count = ref(0)const setCount = ()=>{// 修改数据更新视图必须加上.valuecount.value++}
</script><template><button @click="setCount">{{count}}</button>
</template>
2.reactive
reactive
函数创建一个响应式对象。你可以直接访问和修改它的属性。
<script setup>// 导入import { reactive } from 'vue'// 执行函数 传入参数 变量接收const state = reactive({msg:'this is msg'})const setSate = ()=>{// 修改数据更新视图state.msg = 'this is new msg'}
</script><template>{{ state.msg }}<button @click="setState">change msg</button>
</template>
reactive 对比 ref:
- 都是用来生成响应式数据
- 不同点
- reactive不能处理简单类型的数据
- ref参数类型支持更好,但是必须通过.value做访问修改
- ref函数内部的实现依赖于reactive函数
- 在实际工作中的推荐
- 推荐使用ref函数,减少记忆负担
三、computed
计算属性基本思想和Vue2保持一致,组合式API下的计算属性只是修改了API写法
<script setup>
// 导入
import {ref, computed } from 'vue'
// 原始数据
const count = ref(0)
// 计算属性
const doubleCount = computed(()=>count.value * 2)// 原始数据
const list = ref([1,2,3,4,5,6,7,8])
// 计算属性list
const filterList = computed(item=>item > 2)
</script>
四、watch
侦听一个或者多个数据的变化,数据变化时执行回调函数,俩个额外参数 immediate控制立刻执行,deep开启深度侦听
01- 侦听单个数据
<script setup>// 1. 导入watchimport { ref, watch } from 'vue'const count = ref(0)// 2. 调用watch 侦听变化watch(count, (newValue, oldValue)=>{console.log(`count发生了变化,老值为${oldValue},新值为${newValue}`)})
</script>
02- 侦听多个数据
侦听多个数据,第一个参数可以改写成数组的写法
<script setup>// 1. 导入watchimport { ref, watch } from 'vue'const count = ref(0)const name = ref('cp')// 2. 调用watch 侦听变化watch([count, name], ([newCount, newName],[oldCount,oldName])=>{console.log(`count或者name变化了,[newCount, newName],[oldCount,oldName])})
</script>
03-监听对象中某个值
// 对于对象中的单个属性,进行监视
watch(() => userInfo.value.age, (newValue, oldValue) => {console.log(newValue, oldValue)
})
-immediate
在侦听器创建时立即出发回调,响应式数据变化之后继续执行回调
<script setup>// 1. 导入watchimport { ref, watch } from 'vue'const count = ref(0)// 2. 调用watch 侦听变化watch(count, (newValue, oldValue)=>{console.log(`count发生了变化,老值为${oldValue},新值为${newValue}`)},{immediate: true})
</script>
-deep
通过watch监听的ref对象包含的是简单类型数据默认是浅层侦听的,直接修改嵌套的对象属性不会触发回调执行,需要开启deep
<script setup>// 1. 导入watchimport { ref, watch } from 'vue'const state = ref({ count: 0 })// 2. 监听对象state 并开启deepwatch(state, ()=>{console.log('数据变化了')},{deep:true})const changeStateByCount = ()=>{// 此时修改可以触发回调state.value.count++}
</script>
五、生命周期函数
1. 选项式对比组合式
2. 生命周期函数基本使用
- 导入生命周期函数
- 执行生命周期函数,传入回调
<scirpt setup>
import { onMounted } from 'vue'
onMounted(()=>{// 自定义逻辑
})
</script>
3. 执行多次
生命周期函数执行多次的时候,会按照顺序依次执行
<scirpt setup>
import { onMounted } from 'vue'
onMounted(()=>{// 自定义逻辑
})onMounted(()=>{// 自定义逻辑
})
</script>
六、父子通信
1. 父传子
基本思想
- 父组件中给子组件绑定属性
- 子组件内部通过props选项接收数据
动态传值
给父组件的传值属性前面:
,子属性值会跟着父属性值变化而变化
<div><h3>父组件 - {{ money }}<button @click="getMoney">挣钱</button></h3><!-- 给子组件,添加属性的方式传值 --><SonCom car="宝马车" :money="money"></SonCom></div>
2. 子传父
基本思想
- 父组件中给子组件标签通过@绑定事件
- 子组件内部通过 emit 方法触发事件
七、模版引用
概念:通过 ref标识 获取真实的 dom对象或者组件实例对象
1. 基本使用
实现步骤:
- 调用ref函数生成一个ref对象
- 通过ref标识绑定ref对象到标签
<script setup>
import TestCom from '@/components/test-com.vue'
import { onMounted, ref } from 'vue'// 模板引用(可以获取dom,也可以获取组件)
// 1. 调用ref函数,生成一个ref对象
const inp = ref(null)// 生命周期钩子 onMounted
onMounted(() => {// 3. 通过ref对象.value即可访问到绑定的元素(必须渲染完成后,才能拿到)console.log(inp.value)inp.value.focus()
})
</script><template><div><!--2.通过ref标识,进行绑定--><input ref="inp" type="text"><button @click="clickFn">点击让输入框聚焦</button></div>
</template>
2. defineExpose
默认情况下在
八、provide和inject
顶层组件向任意的底层组件传递数据和方法,实现跨层组件通信
1. 跨层传递普通数据
实现步骤
- 顶层组件通过
provide
函数提供数据 - 底层组件通过
inject
函数提供数据
2. 跨层传递响应式数据
在调用provide函数时,第二个参数设置为ref对象
3. 跨层传递方法
顶层组件可以向底层组件传递方法,底层组件调用方法修改顶层组件的数据
九、Vue Router
Vue Router 是 Vue.js 的路由库,可以使用它构建单页面应用程序,步骤如下:
- 1.安装完成后,在项目的入口文件中(通常是
main.js
)进行配置:
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'createApp(App).use(router).mount('#app')
- 2.在配置文件中引入Vue Router,并将其作为Vue应用的插件进行注册。接下来,我们需要创建一个路由配置文件(通常是
router.js
),并在其中配置路由信息:
import { createRouter, createWebHistory } from 'vue-router'
import Home from './components/Home.vue'
import About from './components/About.vue'const router = createRouter({history: createWebHistory(),routes: [{ path: '/', component: Home },{ path: '/about', component: About }]
})
配置属性:
- history模式(请求路径不带
#
号): createWebHistory() - hash模式: createWebHashHistory()
vite 的配置 import.meta.env.BASE_URL 是路由的基准地址,默认是 ’/‘
https://vitejs.dev/guide/build.html#public-base-path如果将来你部署的域名路径是:http://xxx/my-path/user
vite.config.ts 添加配置 base: my-path,路由这就会加上 my-path 前缀了
- 3最后,在组件中使用
<router-link>
和<router-view>
来导航和渲染路由:
<template><router-link to="/">Home</router-link><router-link to="/about">About</router-link><router-view></router-view>
</template>
编程式路由跳转
在vue2中我们通常用this.$router.push('/路径')
方式跳转路由,但在vue3中不支持this
方式获取路由对象,所以vue3给我们提供了useRouter
和useRoute
获取路由对象和路由参数
<script>
//引入函数
import { useRouter, useRoute } from 'vue-router' setup() { const router = useRouter()const route = useRoute() //获取路由参数console.log(route)//跳转路由const goToHome = () => { router.push({ name: 'Home' }) } </script>
十、Pinia
Pinia 是 Vue 的专属的最新状态管理库 ,是 Vuex 状态管理工具的替代品。相较于VueX:
- 去掉啦mutation,提供啦更加简单的API
- 统一与Vue3新语法,提供组合式风格的API
- 去掉了modules的概念,每一个store都是一个独立的模块
- 配合TypeScript更加友好,提供更可靠的类型推断
1. Option Store
与 Vue 的选项式 API 类似,我们也可以传入一个带有 state
、actions
与 getters
属性的 Option 对象(基本不使用)
export const useCounterStore = defineStore('counter', {state: () => ({ count: 0, name: 'Eduardo' }),getters: {doubleCount: (state) => state.count * 2,},actions: {increment() {this.count++},},
})
注:Pinia中mutation和action二合一,访问state使用this
2. Setup Store
也存在另一种定义 store 的可用语法。与 Vue 组合式 API 的 setup 函数 相似,我们可以传入一个函数,该函数定义了一些响应式属性和方法,并且返回一个带有我们想暴露出去的属性和方法的对象。
//'counter'是仓库唯一标识
export const useCounterStore = defineStore('counter', () => {const count = ref(0)const doubleCount = computed(() => count.value * 2)function increment() {count.value++}return { count, doubleCount, increment }
})
在 Setup Store 中:
ref()
就是state
属性computed()
就是getters
function()
就是actions
使用Store
<script setup>
import { useCounterStore } from '@/stores/counter'
// 可以在组件中的任意位置访问 `store` 变量
const store = useCounterStore()
</script>
3. 持久化
官方文档:https://prazdevs.github.io/pinia-plugin-persistedstate/zh/
- 安装插件 pinia-plugin-persistedstate
npm i pinia-plugin-persistedstate
- 使用 main.js
import persist from 'pinia-plugin-persistedstate'
...
app.use(createPinia().use(persist))
- 配置 store/counter.js
import { defineStore } from 'pinia'
import { computed, ref } from 'vue'export const useCounterStore = defineStore('counter', () => {...return {count,doubleCount,increment}
}, {persist: true
})
- 其他配置,看官网文档即可
s://prazdevs.github.io/pinia-plugin-persistedstate/zh/
- 安装插件 pinia-plugin-persistedstate
npm i pinia-plugin-persistedstate
- 使用 main.js
import persist from 'pinia-plugin-persistedstate'
...
app.use(createPinia().use(persist))
- 配置 store/counter.js
import { defineStore } from 'pinia'
import { computed, ref } from 'vue'export const useCounterStore = defineStore('counter', () => {...return {count,doubleCount,increment}
}, {persist: true
})
其他配置,看官网文档即可