中文官网:Vite中文网
Vite是一种新型前端构建工具,能够显著提升前端开发体验
Vite 意在提供开箱即用的配置,同时它的 插件 API 和 JavaScript API 带来了高度的可扩展性,并有完整的类型支持。
搭建Vite项目相关命令:
使用 NPM:
$ npm create vite@latest
使用 Yarn:
$ yarn create vite
使用 PNPM:
$ pnpm create vite
要构建一个 Vite + Vue 项目,运行:
# npm 6.x
npm create vite@latest my-vue-app --template vue
# npm 7+, extra double-dash is needed:
npm create vite@latest my-vue-app -- --template vue
# yarn
yarn create vite my-vue-app --template vue
# pnpm
pnpm create vite my-vue-app --template vue
Vite解决@问题
修改项目中的vite.config.js文件
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from "path"
export default defineConfig({
plugins: [vue()],
// 配置根路径
resolve: {
// ↓路径别名,主要是这部分
alias: {
"@": resolve(__dirname, "./src")
}
}
})
错误提示:找不到模块 “path” 或其相应的类型声明 或者 找不到名称 “__dirname”
对node进行类型声明
yarn add @types/node -D
npm i @types/node --D
Vue是一款用于构建用户界面的 JavaScript 框架。它基于标准 HTML、CSS 和 JavaScript 构建,并提供了一套声明式的、组件化的编程模型,帮助你高效地开发用户界面。
Vue 的组件可以按两种不同的风格书写:选项式 API 和组合式 API。
使用选项式 API,我们可以用包含多个选项的对象来描述组件的逻辑,例如 data
、methods
和 mounted
。选项所定义的属性都会暴露在函数内部的 this
上,它会指向当前的组件实例。
通过组合式 API,我们可以使用导入的 API 函数来描述组件逻辑。在单文件组件中,组合式 API 通常会与
//子组件
子传父
//子组件
这是子组件----{{num}}
//父组件
父子组件双向数据v-model
//父组件
//子组件
双向数据------{{num}}
兄弟组件之间的传值
1、下载安装
npm i mitt -S
2、新建plugins/Bus.js文件
//Bus.js
import mitt from 'mitt'
const emitter = mitt()
export default emitter
//C组件
C组件
//D组件
D组件----{{strD}}
插槽
匿名插槽、具名插槽、作用域插槽、动态插槽名
匿名插槽
//父组件
这个是XXXX数据
//子组件
具名插槽
//父组件
//这里可以简写
我是yyy数据
//子组件
作用域插槽
让子组件在渲染时将一部分数据提供给插槽。
//父组件
//这里可以简写成
{{data}}
//子组件
动态插槽名
//父组件
这个是XXXX数据
Teleport传送
是一个内置组件,它可以将一个组件内部的一部分模板“传送”到该组件的 DOM 结构外层的位置去。
A
//渲染结果为
A
接收一个
to
prop 来指定传送的目标。to
的值可以是一个 CSS 选择器字符串,也可以是一个 DOM 元素对象。
动态组件
异步组件
在大型项目中,我们可能需要拆分应用为更小的块,并仅在需要时再从服务器加载相关组件。Vue 提供了 defineAsyncComponent,提升性能。
vueuse:https://vueuse.org/core/useIntersectionObserver/#useintersectionobserver
下载安装:npm i @vueuse/core -S
使用场景1
组件按需引入:当用户访问到了组件再去加载组件
使用场景2
打包分包处理:打包完成后,异步组件有单独的js文件,是从主体js分包出来的
Loading...
Mixin混入
Mixin 提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能。一个 mixin 对象可以包含任意组件选项。当组件使用 mixin 对象时,所有 mixin 对象的选项将被“混合”进入该组件本身的选项。
在src目录下创建mixins/mixin.js文件在里面写复用的内容
import { ref } from 'vue'
export default function () {
let num = ref(1)
let fav = ref(false)
let favBtn = () => {
num.value += 1
fav.value = true
setTimeout(() => {
fav.value = false
}, 2000);
}
return {
num,
fav,
favBtn
}
}
在B、C组件中使用,这里只展示其中一个的代码
-----{{num}}---
在选项式API中使用
export const fnaBtn = {
data() {
return {
num:10
}
},
methods: {
favBtnAdd(params) {
this.num += params
}
},
}
-----{{num}}-----
Provide / Inject 依赖注入
1、provide()
接受两个参数:第一个参数是要注入的 key,可以是一个字符串或者一个 symbol,第二个参数是要注入的值。2、inject()第一个参数是注入的 key。Vue 会遍历父组件链,通过匹配 key 来确定所提供的值。如果父组件链上多个组件对同一个 key 提供了值,那么离得更近的组件将会“覆盖”链上更远的组件所提供的值。如果没有能通过 key 匹配到值,
inject()
将返回undefined
,除非提供了一个默认值。第二个参数是可选的,即在没有匹配到 key 时使用的默认值。第二个参数也可以是一个工厂函数,用来返回某些创建起来比较复杂的值。在这种情况下,你必须将
true
作为第三个参数传入,表明这个函数将作为工厂函数使用,而非值本身。
组合式 API:依赖注入 | Vue.js
//提供
provide('count', count)
// 注入响应式的值
const count = inject('count')
Vuex
下载安装:
# npm
npm install vuex@next --save# yarn
yarn add vuex@next --save
创建/src/store/index.js文件
import { createStore } from 'vuex'
import user from './modules/user'
export default createStore({
state: { //存放数据的地方
},
getters:{//类似于组件的计算属性
},
mutations: {//状态更新的唯一方式:提交 mutation,store.commit('方法名')
},
actions: {//异步操作,通过dispatch 调用action 中定义的sum_action 方法
},
modules: {//模块儿化管理
user
}
})
在main.js文件中引入
import store from './store/index'
createApp(App).use(router).use(store).mount('#app')
在组件中使用时
import { useStore } from 'vuex' // 引入useStore 方法
const store = useStore() // 该方法用于返回store 实例
console.log(store.state.user.userInfo) // store 实例对象
let numStore = computed(()=> store.state.numStore)
const btn = () =>{
store.commit('changeNum',2)
store.dispatch('changeBtn')
}
持久化存储vuex-persistedstate
下载安装:npm install vuex-persistedstate --save
在store/index.js中引用
import persistedstate from 'vuex-persistedstate';
在modules下面添加plugins配置
import { createStore } from 'vuex'
import persistedstate from 'vuex-persistedstate';
import user from './modules/user'
export default createStore({
state: { //存放数据的地方
},
getters:{//类似于组件的计算属性
},
mutations: {//状态更新的唯一方式:提交 mutation,store.commit('方法名')
},
actions: {//异步操作,通过dispatch 调用action 中定义的sum_action 方法
},
modules: {//模块儿化管理
user
},
plugins: [persistedstate({
key: 'per-vuex',//浏览器中的名字
paths:['user'] //需要存储起来的参数模块,不写存储的就是指当前文件内的参数
})]
})
大致总结:
1、支持选项式API和组合式API写法
2、pinia没有mutations,只有:state、getters、actions
3、pinia分模块不需要modules
4、TypeScript支持更好
5、自动化代码拆分
6、pinia体积更小(性能更好)
7、pinia可以直接修改数据
Pinia 官网:Pinia | The intuitive store for Vue.js
下载安装
npm install pinia
// or
yarn add pinia
在main.js中引入
import { createPinia } from 'pinia'
createApp(App).use(router).use(createPinia()).mount('#app')
在store/index.js中引入
import { defineStore } from "pinia";
export const useStore = defineStore('storeId', {
state: () => {
return {
counter:0,
}
},
getters: {//有缓存机制,几乎和vuex是一样的
},
actions: {//几乎也没有什么变化
upNum(val) {
this.counter += val
}
}
})
在组件中使用
import {useStore} from '../store/index'
const store = useStore();
console.log(store.counter);
修改数据
import {useStore} from '../store/index'
import {storeToRefs} from 'pinia'
const store = useStore();
let {counter} = storeToRefs(store)
const changBtn = ()=>{
counter.value +=1
}
批量更新数据store.$patch()
import {useStore} from '../store/index'
import {storeToRefs} from 'pinia'
const store = useStore();
let {counter} = storeToRefs(store)
const changBtn = ()=>{
store.$patch((state)=>{
state.counter ++
})
}
使用actions中提供的方法
const btnAdd = () =>{
store.upNum(200)
}
模块儿化直接在store里创建模块儿化js文件,如user.js、shop.js等,shop.js文件内容在下面
在组件中引入使用,例如
import {shop} from '../store/shop'
import {storeToRefs} from 'pinia'
const shopStore = shop()
const {shopList} = storeToRefs(shopStore)
持久化存储
下载安装:
npm i pinia-plugin-persist --save
修改main.js文件
import store from './store/index'
createApp(App).use(router).use(store).mount('#app')
在store/index.js中
import { createPinia } from 'pinia'
import piniaPluginPersist from 'pinia-plugin-persist'
const store = createPinia()
store.use(piniaPluginPersist)
export default store
在store/shop.js中配置
import { defineStore } from "pinia";
export const shop = defineStore('shopId', {
state: () => {
return {
shopList: [
{ id: 1, name: '苹果' },
{ id: 2, name: '橘子' },
]
}
},
getters: {
},
actions: {
},
persist: {//开启数据缓存
enabled: true,
strategies: [
{
key: 'my-shop',
storage: localStorage,
paths:['shopList'] //默认是全部需要持久化,也可以通过该属性指定
}
]
}
})
设置代理
在vite.config.js中添加
//设置代理解决跨域问题
server: {
proxy: {
'/api':'所代理的地址'
}
}
在src目录下创建utils/request.js文件
import axios from 'axios'
//创建axios对象
const service = axios.create();
//请求拦截器
service.interceptors.request.use(config => {
return config;
}, error => {
Promise.reject(error)
});
//响应拦截
service.interceptors.response.use(response => {
//判断code码
return response.data
}, error => {
return Promise.reject(error)
});
export default service;
在src目录下创建api文件夹,里面添加需要添加的API接口,例如
import request from '../utils/request'
export function getSliders() {
return request({url:'/api/slider/getSliders'})
}
在组件中使用
import {getSliders} from '../api/slider'
let list = ref([]);
onBeforeMount(()=>{
getSliders().then(res=>{
list.value = res.data.list
for (let index = 0; index < list.value.length; index++) {
if(index == 0){
list.value.splice(0,1)
}
}
})
})