4.1watch()
watch 作用:监视数据变化
watch 特点:Vue3 中的 watch 可以监视以下4种数据
1.ref定义的数据
2.reactive定义的数据
3.函数返回一个值(getter函数
)
4.一个包含上述内容的数组
*情况一
监视 ref 定义的 [基本类型] 数据(监视ref的基本数据时不需要也不能加 .value 因为根据Vue3官方文档给出的内容 watch只能监视ref定义的数据 如果加上了 .value 那么监视的就是数据的内容了而不是数据本身 比如 let sum = ref(0) sum是 ref定义的数据 而 sum.value是0)
<script setup lang="ts" name="Person">
import {ref, watch} from 'vue'
//数据
let sum = ref(0)
//函数
function changeSum() {
sum.value += 1
}
//监视
const stopWatch =watch(sum, (newValue, oldValue) => {
//在此处给监视事件赋一个只读的值在下方用于结束监视
// watch(谁?,回调函数){
console.log('sum变化了', newValue, oldValue)
if (newValue>10)stopWatch()
// 当newValue的值大于10时停止监视
})
</script>
<template>
<h1><h2>情况一: 监视 [ref] 定义的 [基本类型] 数据</h2></h1>
<h2>当前求和为:{{ sum }}</h2>
<button @click="changeSum">点击加一</button>
</template>
<style scoped>
</style>
`情况二
监视ref定义的 [对象类型] 数据: 直接写数据名, 监视的是对象的 [地址值] ,若想监视对象内部的数据, 要手动开启深度监视.
注意:
`若修改的是ref 定义的对象中的属性, newValue 和 oldValue 都是新的值,因为它们是同一个对象.
`若修改整个ref定义的对象, newValue 是新值, oldValue 是旧值, 因为不是同一个对象了.
<script setup lang="ts" name="Person">
import {ref, watch} from "vue";
//数据
let person = ref({
name: '张三',
age: 18
})
//函数
function changeName() {
person.value.name += '~'
}
function changeAge() {
person.value.age++
}
function changePersion() {
person.value = {name: '李四', age: 20}
}
//监视,情况一:监视 [ref] 定义的 [对象类型] 数据,监视的是对象的地址值
// watch(person, (newValue, oldValue) => {
// console.log('persion变化了', newValue, oldValue)
// }
//监视,情况二:监视 [ref] 定义的 [对象类型] 数据监视的是对象的地址值,若想监视对象的属性变化则需要手动开启深度监视: {deep:true}
/**
* watch的第一个参数: 被监视的数据
* watch的第二个参数: 监视的回调
* watch的第三个参数: 配置对象(deep immediate等等......)
*/
watch(person, (newValue, oldValue) => {
console.log('persion变化了', newValue, oldValue)
}, {deep: true})
/**
* deep: 深度监视
* immediate: 立即监视
*/
</script>
<template>
<h2>情况二: 监视 [ref] 定义的 [对象类型] 数据</h2>
<h2>姓名:{{ person.name }}</h2>
<h2>年龄:{{ person.age }}</h2>
<button @click="changeName">修改姓名</button>
<button @click="changeAge">修改年龄</button>
<button @click="changePersion">修改人物</button>
</template>
<style scoped>
</style>
`情况三
监视reactive定义的 [对象类型] 数据, 且默认开启了深度监视
<script setup lang="ts" name="Person">
import {reactive, watch} from "vue";
//数据
let person = reactive({
name: '张三',
age: 18
})
//函数
function changeName() {
person.name += '~'
}
function changeAge() {
person.age++
}
function changePersion() {
Object.assign(person,{name:'李',age:14})
}
//监视 情况三: 监视 [reactive] 定义的 [响应式对象]数据 且默认是开启深度监视的
watch(person,(newValue,oldValue)=>{
console.log('persion变化了',newValue,oldValue)
})
</script>
<template>
<h2>情况三: 监视 [reactive] 定义的 [响应式对象]</h2>
<h2>姓名:{{ person.name }}</h2>
<h2>年龄:{{ person.age }}</h2>
<button @click="changeName">修改姓名</button>
<button @click="changeAge">修改年龄</button>
<button @click="changePersion">修改人物</button>
</template>
<style scoped>
</style>
`情况四
监视ref或reactive 定义的 [对象类型] 数据中的某个属性,注意点如下:
1.若该属性不是 [对象类型],需要写成函数形式
2.若该属性值依然是 [对象类型],可直接编写,也可以写成函数,不过建议携程函数
结论:监视的是对象内的属性,那么最好写函数式,注意:若是对象监视的是地址值 ,需要关注对象内部,需要手动开启深度监视
<script setup lang="ts" name="Person">
import {reactive, watch} from "vue";
//数据
let person = reactive({
name: '张三',
age: 18,
car: {
c1: '奔驰',
c2: '宝马'
}
})
//方法
function changeName() {
person.name += '~'
}
function changeAge() {
person.age++
}
function changeC1() {
person.car.c1 = '奥迪'
}
function changeC2() {
person.car.c2 = '劳斯莱斯'
}
function changeCar() {
person.car = {c1: '雅迪', c2: '小刀'}
}
//监视 情况四: 情况一:监视响应式对象数据中的某个属性,且该属性是基本类型的 要写成函数
//若该属性不是 [对象类型],需要写成函数形式 监视 recative定义的数据内的某一项内容
// watch(()=>{return person.name}, (newValue, oldValue) => {
// console.log('persion.name 变化了', newValue, oldValue)
// })
//监视 情况四: 情况二:监视响应式对象数据中的某个属性,且该属性是基本类型的 可以直接写,也能写成函数,但是更推荐写函数
// watch(person.car, (newValue, oldValue) => {
// console.log('persion.car 变化了', newValue, oldValue)
// //此时当c1 和c2 发生变化时可以监视的到但是当整个car发生改变时无法监视,
// //因为 changeCar()改变了整个car 而此处的监视监视的是之前的car
// })
// watch(()=>person.car, (newValue, oldValue) => {
// console.log('persion.car 变化了', newValue, oldValue)
// //此时当c1 和c2 发生变化时监视不到但是当整个car发生改变时可以监视的到,
// //因为 此时外面包了函数所以此时检测的是地址值
// })
watch(()=>person.car, (newValue, oldValue) => {
console.log('persion.car 变化了', newValue, oldValue)
//此时当c1 ,c2 ,car 发生变化时都可以监视的到,
//因为 此时外面包了函数所以此时检测的是地址值,且对此地址进行了深度监视
},{deep:true})
</script>
<template>
<h2>情况四: 监视[ref] 或 [reactive] 定义的 [对象类型] 数据中的某个属性</h2>
<h2>姓名:{{ person.name }}</h2>
<h2>年龄:{{ person.age }}</h2>
<h2>汽车:{{ person.car.c1 }}</h2>
<h2>汽车:{{ person.car.c2 }}</h2>
<h2>汽车:{{ person.car.c1 }}、{{ person.car.c2 }}</h2>
<button @click="changeName">修改名字</button>
<button @click="changeAge">修改年龄</button>
<button @click="changeC1">修改第一台车</button>
<button @click="changeC2">修改第二台车</button>
<button @click="changeCar">修改所有车</button>
</template>
<style scoped>
</style>
`情况五
监视上述的多个数据时
<script setup lang="ts" name="Person">
import {reactive, watch} from "vue";
//数据
let person = reactive({
name: '张三',
age: 18,
car: {
c1: '奔驰',
c2: '宝马'
}
})
//方法
function changeName() {
person.name += '~'
}
function changeAge() {
person.age++
}
function changeC1() {
person.car.c1 = '奥迪'
}
function changeC2() {
person.car.c2 = '劳斯莱斯'
}
function changeCar() {
person.car = {c1: '雅迪', c2: '小刀'}
}
//监视 情况五: 监视上述多个数据
watch([()=>person.name,()=>person.age,()=>person.car,()=>person.car.c1,()=>person.car.c2], (newValue, oldValue) => {
console.log('persion.car 变化了', newValue, oldValue)
},{deep:true})
</script>
<template>
<h2>情况五: 监视上述多个数据</h2>
<h2>姓名:{{ person.name }}</h2>
<h2>年龄:{{ person.age }}</h2>
<h2>汽车:{{ person.car.c1 }}</h2>
<h2>汽车:{{ person.car.c2 }}</h2>
<h2>汽车:{{ person.car.c1 }}、{{ person.car.c2 }}</h2>
<button @click="changeName">修改名字</button>
<button @click="changeAge">修改年龄</button>
<button @click="changeC1">修改第一台车</button>
<button @click="changeC2">修改第二台车</button>
<button @click="changeCar">修改所有车</button>
</template>
<style scoped>
</style>
4.2watchEffect
立即运行一个函数,同时响应式地追踪其依赖,并在依赖更改时重新执行该函数
<script setup lang="ts" name="Person">
import {ref, watch, watchEffect} from "vue";
//数据
let temp = ref(10)
let height = ref(50)
//方法
function changerTemp() {
temp.value += 10
}
function changerHeight() {
height.value += 10
}
//监视
//不用watchEffect的写法
// watch([temp, height], (newValue, oldValue) => {
// //[()=>{return temp.value},()=>{return height.value}]数组里面放函数也可以
// // console.log('当前'+newValue,'曾经'+oldValue)
// let [newTemp, newHeight] = newValue
// if (newTemp >= 60 || newHeight >= 80) {
// console.log('当前水温为'+newTemp,'当前水位为'+newHeight+'超过要求')
// }
// })
//用watchEffect的写法
watchEffect(()=>{
if (temp.value >= 60 || height.value >= 80) {
console.log('当前水温为'+temp.value,'当前水位为'+height.value+'超过要求')
}
})
</script>
<template>
<h1>watchEffect</h1>
<h2>需求,当水温达到60,或水位达到80时,给服务器发送请求</h2>
<h2>当前水温{{ temp }}℃</h2>
<h2>当前水位{{ height }}m</h2>
<button @click="changerTemp">点我升高温度+10</button>
<button @click="changerHeight">点我升高高度+10</button>
</template>
<style scoped>
</style>
4.3watch和watchEffect对比
1.都能监听响应式数据的变化,不同的时监听数据变化的方式不同
2.watch: 要明确的指出监视的数据
3.watchEffect: 不需要明确指出监视的数据(函数中用到哪些属性,就监视那些的属性)
5` 标签的ref属性
常用作 作为标记点 防止页面内容发生冲突
persion.vue
<script setup lang="ts" name="Person">
import {ref,defineExpose} from "vue";
//数据
//存储元素标记内容
let title2 = ref()
let a =ref(0)
let b =ref(0)
let c =ref(0)
//函数
//通过id获取到页面代码 此方法可能会出现id冲突问题 实际项目工作中不建议使用
// function showLog() {
// console.log(document.getElementById('title2'))
// }
function showLog() {
console.log(title2.value)
}
//导出 如果此处不导出那么下面的那个vue 是取不到此处 a b c的内容的
defineExpose({a,b,c})
</script>
<template>
<div class="person">
<h1>标签的ref属性</h1>
<h1>中国</h1>
<h2 ref="title2" >北京</h2>
<h3>胡同</h3>
<button @click="showLog">点击我输出h2</button>
</div>
</template>
<style scoped>
如果输出的时候内容的时候多出了例如 data-v-4cadc14e 等这一类的内容
是因为在此处使用了局部样式 ,将scoped那块删了就没有了
但是! 如果删了的话 那么此处的样式就是全局的了
如果样式的名发生冲突可能会出现显示混乱的效果
.person{
background-color: skyblue;
box-shadow: 0 0 10px;
border-radius: 10px;
padding: 20px;
}
</style>
lab.vue
<script setup lang="ts">
import router from "@/router";
import Person from "@/components/Person.vue";
import {ref} from "vue";
function logon() {
router.push({
path: "/log",
name:"log"
})
}
let title2 = ref(0)
let per = ref()
function showLog() {
//此处可以看作是调用persion.vue的内容
console.log(per.value)
}
</script>
<template>
<h1 ref="title2">主页</h1>
<person ref="per"/>
<button @click="showLog">测试</button>
</template>
<style scoped>
</style>
6` 接口 泛型 自定义类型
person.ts
//1. 定义一个接口 用于限制person对象的具体属性
export interface Person{
id:string,
name:string,
age:number
}
//2. 一个自定义类型
//数组 方法一
// export type Persons = Array<Person>
//数组 方法二
export type Persons = Person[]
Person.vue
<script setup lang="ts" name="Person">
import {type Person,type Persons} from '@/typedefine/person'
//定义单个数据
// let persion:Person = {id:'01',name:'LiM',age:18}
//定义数组数据
// let persion: Array<Person> = [
// //let定义 persion名称 :Array数组 <person>泛型
// {id: '01', name: 'LiM', age: 19},
// {id: '02', name: 'Li', age: 18},
// {id: '03', name: 'L', age: 19}
// ]
let persion:Persons = [
//let定义 persion名称 :Array数组 <person>泛型
{id: '01', name: 'LiM', age: 19},
{id: '02', name: 'Li', age: 18},
{id: '03', name: 'L', age: 19}
]
</script>
<template>
<div class="person">
???
</div>
</template>
<style scoped>
.person {
background-color: skyblue;
box-shadow: 0 0 10px;
border-radius: 10px;
padding: 20px;
}
</style>
7` props的使用
简单示例:
接收父类传过来的数据 defineProps([’ '])
父类内容:
<template>
<person a="哈哈哈哈"/>
</template>
子类引用:
<script setup lang="ts" name="Person">
defineProps(['a'])
</script>
<template>
{{ a }}
</template>
曾加难度:
接收数组
父类内容:
<script setup lang="ts">
import Person from "@/components/Person.vue";
import {type Persons} from '@/typedefine/person'
import {reactive} from "vue";
//定义数组数据
let persionList= reactive<Persons>([
//let定义 persion名称 :Array数组 <person>泛型
{id: '01', name: 'LiM', age: 19},
{id: '02', name: 'Li', age: 18},
{id: '03', name: 'L', age: 19}
])
console.log(persionList)
</script>
<template>
<person a="哈哈哈哈" :list="persionList"/>
</template>
<style scoped>
</style>
子类内容:
<script setup lang="ts" name="Person">
import type {Persons} from "@/typedefine/person";
// //只接收list
// defineProps(['list'])
// //接收list + 限制类型
// defineProps<{ list: Persons }>()
// //接收list + 限制类型 + 限制必要性
// defineProps<{ list?: Persons }>()
//接收list + 限制类型 + 限制必要性 + 指定默认值
withDefaults(defineProps<{ list?: Persons }>(), {
list: () => [{id: '00', name: '0号', age: 20}]
})
// //接收list 同时将props保存起来
// let x = defineProps(['list'])
</script>
<template>
<div class="person">
<ul>
<li v-for="persionObj in list" :key="persionObj.id">
{{ persionObj.name }} -- {{ persionObj.age }}
</li>
</ul>
</div>
</template>
<style scoped>
.person {
background-color: skyblue;
box-shadow: 0 0 10px;
border-radius: 10px;
padding: 20px;
}
</style>
8` 生命周期
概念:Vue组件实例在创建时要经历一系列的初始化步骤,在此过程中Vue会在合适的时机, 调用特定的函数, 从而让开发者有机会在特定阶段运行自己的代码, 这些特定的函数统称为: 生命周期钩子
注意:
当引用组件时 子组件会优先于父组件进行挂载
用 v-if 来决定是否显示时 如果条件为false那么内容将会被销毁
用v-show来决定是否显示时 如果条件为false那么内容会被隐藏
8.1 Vue2生命周期
组件的生命周期: 四个周期 八个钩子
[时刻] [调用特定函数]
–>创建(创建前 beforeCreate, 创建完毕 created)
–>挂载(创建前 beforeMount, 挂载完毕 mounted)
–>更新(创建前 beforeUpdate, 挂载完毕 update)
–>销毁(创建前 beforeDestroy, 销毁完毕 destroyed)
拓展: 用 v-if 来决定是否显示时 如果条件为false那么内容将会被销毁 但是如果用v-show则会隐藏
8.2 Vue3生命周期
组件的生命周期: 四个周期 八个钩子
[时刻] [调用特定函数]
–>创建 setup函数(vue3推荐使用setup语法糖 所以setup都不需要在写了)
–>挂载(创建前 onBeforeMount, 挂载完毕 onMounted)
–>更新(创建前 onBeforeUpdate, 挂载完毕 onUpdate)
–>卸载(创建前 onBeforeUnmount, 销毁完毕 onUnmounted)
拓展: vue3调用函数需要在函数内写上回调函数 ()=>{ 这里面写你要写的东西 }
9`自定义Hooks
hooks 简单来说就是外联ts 把冗杂的ts内容(数据 函数 方法 钩子)单独存放,在需要的时候进行使用
9.1 创建一个文件夹名称为hooks
9.2 创建ts文件
axios 网络请求
安装: npm i axios (控制台)
引入: import axios from ‘axios’ (组件)
useDog.ts
import axios from "axios";
import {reactive} from "vue";
export default function () {
//数据
let dogList = reactive([
'Https://api.dujin.org/pic'
])
//函数
async function getDog() {
try {
let result = await axios.get('Https://api.dujin.org/pic')
dogList.push(result.data.message)
} catch (error) {
alert(error)
}
}
//向外部提供信息
return {dogList,getDog}
}
useSum.ts
import {ref} from "vue";
export default function () {
//数据
let sum = ref(0)
//函数
function changerSum() {
sum.value++
}
return {sum,changerSum}
}
9.3在需要的时候使用
在vue组件内使用
import useSum from "@/hooks/useLoginIn";
const {sum,changerSum} = useSum()
二`路由
路由就是 一组 key 和 value 的对应关系( key + value => route) 多个路由由路由器管理
1.路由的基本切换效果
创建几个vue文件
@/router/index.ts
// 创建一个路由器 ,并暴露出去
//引入
import {createRouter, createWebHistory} from 'vue-router'
// 引入组件
import lable from '@/views/lable.vue'
import logHome from "@/views/log/logHome.vue";
import login from "@/views/log/page/login.vue";
import logon from "@/views/log/page/logon.vue";
import back from "@/views/log/page/back.vue";
// 创建路由
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: '/',
name: 'lable',
component: () => lable,
// 标签页
}, {
path: '/log',
name: 'log',
component: () => logHome,
// 登录注册页
children: [
{
path: '/log/login',
name: 'login',
component: () => login
// 登录页
}, {
path: '/log/logon',
name: 'logon',
component: () => logon
// 注册页
}, {
path: '/log/back',
name: 'back',
component: () => back
// 找回
},
]
}
]
})
// 暴露路由
export default router
main.ts
// 引入createApp用于创建应用
import { createApp } from 'vue'
// 引入App跟组件
import App from './App.vue'
// 引入路由
import router from './router'
// 使用路由
app.use(router)
// 挂载整个容器到app容器中
app.mount('#app')
vue.页面
<script setup lang="ts" name="Person">
//展示区占位RouterView
import {RouterView,RouterLink} from "vue-router";
</script>
<template>
<div class="person">
<h2>VUE路由测试</h2>
<!-- 导航区-->
<div>
<RouterLink to="/lable" active-class="/logHome">首页</RouterLink>
<!-- active-class="" 激活时展示样式-->
<RouterLink to="/login">登录</RouterLink>
<RouterLink to="/logon">注册</RouterLink>
<RouterLink to="/back">找回</RouterLink>
</div>
<!-- 展示区-->
<div>
展示组件
<RouterView/>
</div>
</div>
</template>
<style scoped>
.person {
background-color: skyblue;
box-shadow: 0 0 10px;
border-radius: 10px;
padding: 20px;
}
</style>
2` 路由的两个注意点
1.路由组件通常存放在pages 或者 views文件夹 ,一般组件通常放在 components文件夹
路由组件: 靠路由的规则渲染出来的(不是通过标签展示出来的 比如: 这种的)
一般组件: 是咱们程序员亲手写的那种标签的组件
2.通过点击导航,视觉上"消失"了的路由组件 ,默认是被销毁掉的 ,需要的时候再去挂载
3` to的两种写法
基础写法:
1.字符串写法:登录
2.对象写法: 登录
传参写法:
query写法:
<div>
<!-- 路由传参-->
<ul>
<!-- 方法一-->
<li v-for=" item in newList " :key="item.id">
<RouterLink :to="`/?id=${item.id}&title=${item.title}`">{{ item.title }}</RouterLink>
</li>
<!-- 方法二-->
<li v-for=" item in newList " :key="item.id">
<RouterLink
:to="{
path:'/',
query:{
id:item.id,
title:item.title
}
}">
{{ item.title }}
</RouterLink>
</li>
</ul>
</div>
参数接收
<script setup lang="ts">
let route = useRoute()
let {query} = toRefs(route)
</script>
<template>
<ul>
<li>编号:{{router.id}}</li>
<li>标题:{{router.title}}</li>
</ul>
</template>
params写法:
备注1:传递params参数时 ,若使用to的对象写法,必须使用name配置项,不能用path
备注2:传递params参数时 ,需要提前在规则中占位
vue组件内:
<script setup lang="ts" name="Person">
</script>
<template>
<div class="person">
<h2>VUE路由测试</h2>
<!-- 导航区-->
<div>
<!-- 路由传参-->
<ul>
<!-- 方法一-->
<li v-for=" item in newList " :key="item.id">
<RouterLink :to="`/${item.id}/${item.title}`">{{ item.title }}</RouterLink>
</li>
</ul>
<ul>
<!-- 方法二-->
<li v-for=" item in newList " :key="item.id">
<RouterLink
:to="{
name:"/"
<!--注意因为之前路径用占位了所以这块用name跳转 且不能传对象和数组-->
params:{
id:item.id,
title:item.title
}
}"
>
{{ item.title }}</RouterLink>
</li>
</ul>
</div>
<!-- 展示区-->
<div>
展示组件
<RouterView/>
</div>
</div>
</template>
<style scoped>
.person {
background-color: skyblue;
box-shadow: 0 0 10px;
border-radius: 10px;
padding: 20px;
}
</style>
路由文件内:
routes: [
{
path: '/:x/:y?',//:x为必须传的 :y?为可传可不传
name: 'lable',
component: () => lable,
// 标签页
}
]
参数接收
<script setup lang="ts">
let route = useRoute()
let {query} = toRefs(route)
</script>
<template>
<ul>
<li>编号:{{router.params.id}}</li>
<li>标题:{{router.params.title}}</li>
</ul>
</template>
4` 路由器的工作模式
history模式
写法:
vue2: mode:'hsitory
vue3: history:createWebHistory()
React: BrowserRouter 标签
优点:URL更加美观,不带有# ,更接近传统网站的URL
缺点:后期项目上线 ,需要服务端配合处理路径问题 ,否则刷新会有404错误
hash模式
写法:
vue2: mode:'hash
vue3: history:createWebHashHistory()
React: HashRouter 标签
优点:兼容性更好 ,因为不需要服务器端处理路径
缺点:URL带有#不太美观 ,且在SEO优化方面相对较差
`5 路由的props配置
作用:让路由组件更方便的收到参数(可以将路由参数作为 props 传给组件)
路由:
routes: [
{
path: '/:x/:y?',//:x为必须传的 :y?为可传可不传
name: 'lable',
component: () => logHome,//组件地址
// 第一种写法,将路由收到的所有params参数作为props传给路由组件
props:true
// 第二种写法,可以自己决定将什么作为props传给路由组件
// 对象写法
// 比如传query的
// props(route){
// return route.query
// }
}
]
组件:
<script setup lang="ts">
defineProps(['id','title'])
</script>
<template>
<ul>
<li>编号:{{id}}</li>
<li>标题:{title}}</li>
</ul>
</template>
6` replace属性
push: 栈模式 可以 前进 后退(默认)
replace: 覆盖 不能 前进 后退 在
7` 编程试导航
脱离RouterLink实现跳转
路由组件的两个重要的属性: $route 和 $router 变成了两个 hooks
<script setup lang="ts" name="Person">
import {onMounted} from "vue";
import {useRouter} from "vue-router";
//路由器
const router = useRouter()
//组件挂在
onMounted(()=>{
//展示事件
setTimeout(()=>{
//让路由实现跳转
router.push('/')//push跳转 留下历史记录 可以前进 后退
// router.replace('/')//replace跳转 不留记录
},3000)//只能看3s
})
</script>
<template>
<div class="person">
</div>
</template>
<style scoped>
.person {
background-color: skyblue;
box-shadow: 0 0 10px;
border-radius: 10px;
padding: 20px;
}
</style>
8` 路由的重定向
将本来应该跳转到/的跳转到/home那
routes: [
{
path: '/',
name: 'lable',
component: () => lable,
// 标签页
},{
path: '/home',
name: 'home',
component: () => home,
// 标签页
},{
path: '/',
redirect: '/home'
}
]
三` pinia 仓库
Pinia: 集中式状态(数据) 管理
1.搭建环境
下载: npm install pinia
main.ts
// 引入createApp用于创建应用
import {createApp} from 'vue'
//引入App跟组件
import App from './App.vue'
//引入pinia
import {createPinia} from 'pinia'
// 应用路由
const app = createApp(App)
// pinia注入
app.use(createPinia())
// 挂载整个容器到app容器中
app.mount('#app')
### 最后
四轮技术面+一轮hr面结束,学习到了不少,面试也是一个学习检测自己的过程,面试前大概复习了 一周的时间,把以前的代码看了一下,字节跳动比较注重算法,面试前刷了下leetcode和剑指offer, 也刷了些在牛客网上的面经。大概就说这些了,写代码去了~
祝大家都能收获大厂offer~
**篇幅有限,仅展示部分内容**
![](https://img-blog.csdnimg.cn/img_convert/ac0b1c2376da47d727e0dc8a77e76478.png)
![](https://img-blog.csdnimg.cn/img_convert/b871b45fb2e6d5442144c863cbcff965.png)
![](https://img-blog.csdnimg.cn/img_convert/f5c18f4b2878302f1f53a8c393e7eb0d.png)