1. 搭建项目
npm create vite@latest vite-vue3-ts -- --template vue-ts
2. 安装sass
npm install sass -D
3. 安装路由
npm install vue-router@4
这里面需要确定一下,vue3里最好使用router4以上的版本,否则支持不是很友好。
// router/index.ts
import {createRouter, createWebHistory, createWebHashHistory, RouteRecordRaw, Router} from 'vue-router'
const routes: Array<RouteRecordRaw> = [
{
path: '/',
name: 'hello',
component: () => import('@/pages/Home.vue')
},
{
path: '/login',
name: 'login',
component: () => import('@/pages/Login/Login.vue')
},
{
path: '/fortress',
name: 'fortress',
component: () => import('@/pages/Fortress/Index.vue')
}
]
const router = createRouter({
history: createWebHistory(''),
routes
})
export default router
// main.ts
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
const app = createApp(App)
app.use(router)
app.mount('#app')
defineProps
在子组件中接收如组件传过来的数据
<script setup>
import {defineProps} from 'vue'
defineProps({
msg: {
type: String,
default: 'aaaaa'
}
})
</script>
defineEmits
<script setup>
// 子组件
const props = defineProps({
num: {
type: Number,
default: 100
}
})
const emit = defineEmits(['update: num'])
const btn = () => {
emit('update: num', 200) //修改num的值
}
</script>
// 父组件
<List v-model:num='num'></List>
let num = ref(1)
自动导入vue和vue-router的函数
npm i unplugin-auto-import -D
// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
import path from 'path'
export default defineConfig({
base: './',
resolve: {
alias: {
"@": path.resolve(__dirname, "src"),
},
},
plugins: [vue(),
AutoImport({
imports: ['vue', 'vue-router'], //自动导入vue和vue-router相关函数
resolvers: [ElementPlusResolver()],
}),
Components({
resolvers: [ElementPlusResolver()],
}),
],
server: {
host: '0.0.0.0',
proxy: {
"/api": {
target: 'http://192.168.101.57:8080/',
ws: true,
changeOrigin: true,
}
}
}
})
toRefs
完成数据的解构
<script setup>
let obj = reactive({
name: '张三',
age: 18
})
let {name, age} = toRefs(obj)
</script>
watch
- 监听一个数据
watch(msg, (newVal, oldVal) => {
console.log(newVal, oldVal)
}, {
immediate: true // 初始化监听
})
- 监听多个数据
watch([msg, str], (newVal, oldVal) => {
console.log(newVal, oldVal)
}, {
immediate: true
})
- 监听对象中某个对象
watch(() => obj.arr, (newVal, oldVal) => {
console.log(newVal, oldVal)
})
watch([msg, str, () => obj.arr], (newVal, oldVal) => {
console.log(newVal, oldVal)
})
- 立即执行监听函数
watchEffect(() => {
console.log(msg.value)
})
useRoute 和 useRouter
<script setup>
import {useRoute, useRouter} from 'vue-router' //若配置了自动引入此处可以不再导入
const router = useRouter()
const go = () => router.push('/about')
</script>
兄弟组件直接的传值
- mitt
npm install mitt -S
// plugins/Bus.js
import mitt from 'mitt'
const emitter = mitt()
export default emitter
// A 组件
emitter.emit('fn', str)
// B 组件
emitter.on('fn', e => {
s.value = e.value
})
插槽
- 匿名插槽
- 具名插槽
- 作用域插槽
- 动态插槽
Teleport 传送
注意顺序,必须传送到有这个Dom的内容
<teleport to="#xxx"></teleport>
<teleport to=".xxx"></teleport>
<teleport to="body"></teleport>
动态组件
<keep-alive>
<component :is="currentComponent.com"></component>
</keep-alive>
异步组件
- 组件按需引入,当用户访问到了组件,再去加载组件
<template>
<div ref="target">
<C v-if="targetIsVisible"></C>
</div>
</template>
<script setup>
import {useIntersectionObserver} from '@vueuse/core'
const C = defineAsyncComponent(() => import('../compontents/C.vue'))
const target = ref(null)
const targetIsVisible = ref(false)
const {stop} = useIntersectionObserver(target, ([{isIntersecting}]) => {
if(isIntersecting){
targetIsVisible.value = isIntersecting
}
})
</script>
- 分包
<Suspense>
<template #default>
<A></A>
</template>
<template #fallback>
加载中...
</template>
</Suspense>
<script setup>
const A = defineAsyncComponent(() => import('../compontents/A.vue'))
</script>
minix
Provide / Inject 依赖注入
// 父组件
<script setup>
provide('changeNum', 100)
</script>
// 子孙组件
<script setup>
const aNum = inject('changeNum')
</script>
vuex
<script setup>
import {useStore} from 'vuex'
let store = useStore()
let num = computed(() => store.state.num)
let total = computed(() => store.getters.total)
store.commit('xxx')
store.dispatch('xxx')
</script>
持久化存储
localstorage
npm install vuex-persistedstate -S
Pinia
- 支持选项式API和组合式API的写法
- pinia没有mutations,只有 state,getters,actions
- pinia分模块不需要modules
- ts支持良好
- 自动化代码拆分
- pinia体积更小、性能更好
- pinia可以直接修改state数据
- 安装
npm install pinia
- 在main.js中引用
import {createPinia} from 'pinia'
createApp(App)..use(createPinia()).use(router).mount('#app')
- store/index.js
import {defineStore} from 'pinia'
export const useStore = defineStore('storeId', {
state: () => {
return {
num: 0,
name: 'xxxxxx'
}
},
getters: {
changeNum(){
return this.num + 1000
}
},
actions: {
updateNum(val){
this.num += val
}
}
})
- 在组件中使用
<script setup>
import { storeToRefs } from 'pinia'
import { useStore } from '../store'
const store = useStore()
let {name, num, changeNum} = storeToRefs(store)
const changeName = () => {
name.value = 'lisi'
//批量修改
store.$patch(state => {
state.num++
state.name = 'xxx'
})
}
const btn = () => {
store.updateNum(200)
}
</script>
- 持久化存储
pinia-plugin-persist