06vue3实战-----项目开发准备
06vue3实战-----项目开发准备
- 1.CSS样式的重置
- 1.1先引入第三方库normalize.css
- 1.2自己写一些默认样式
- 2.路由配置
- 2.1安装路由:
- 2.2挂载路由:
- 2.3配置路由
- 3.状态管理配置
- 3.1安装pinia
- 3.2挂载pinia
- 3.3创建一个store文件
- 3.4应用store
- 4.网络请求封装axios
- 4.1再封装axios
- 4.2使用封装后的axios
1.CSS样式的重置
对默认CSS样式进行重置。
1.1先引入第三方库normalize.css
命令行安装normalize.css:
npm install normalize.css
在main.ts文件中引入:
...
import 'normalize.css'
...
1.2自己写一些默认样式
在assets文件夹下的css文件夹中新建几个文件:
common.less放公共的样式,reset.less中放重置的样式,index.less集成其它的css文件。
index.less文件:
@import './reset.less';
@import './common.less';
reset.css放重置的样式,可以自己写,也可以网上找。
reset.less文件:
/* reset.css样式重置文件 */
/* margin/padding重置 */
body, h1, h2, h3, ul, ol, li, p, dl, dt, dd {
padding: 0;
margin: 0;
}
/* a元素重置 */
a {
text-decoration: none;
color: #333;
}
/* img的vertical-align重置 */
img {
vertical-align: top;
}
/* ul, ol, li重置 */
ul, ol, li {
list-style: none;
}
/* 对斜体元素重置 */
i, em {
font-style: normal;
}
在main.js中引入index.less文件:
...
import 'normalize.css'
import './assets/css/index.less'
...
此时直接运行项目会报错,因为没有安装less编译插件:
安装less第三方库:
npm install less -D
再执行就可以成功了。
2.路由配置
2.1安装路由:
npm install vue-router
在router文件夹(没有该文件夹就在src下创建一个)中创建index.ts文件:
import { createRouter, createWebHashHistory } from 'vue-router'
//通过createRouter我们发现现在前端都转向了函数式编程,之前创建路由是用new关键字
const router = createRouter({
history: createWebHashHistory(),//这里我们用hash模式举例
routes: []
})
export default router
2.2挂载路由:
在main.ts中挂载:
import { createApp } from 'vue'
import 'normalize.css'
import './assets/css/index.less'
import App from './App.vue'
import router from './router'
const app = createApp(App)
app.use(router)
app.mount('#app')
2.3配置路由
先在views文件夹中创建一些文件:
Login.vue:
文件出现一个警告,鼠标悬浮提示:
Component name "Login" should always be multi-word.eslintvue/multi-word-component-names
在.eslintrc.cjs文件中进行rules配置:
rules: {
...
'vue/multi-word-component-names': 'off'
}
配置完之后就不会警告了。
上述初始化vue文件内容太麻烦,我们可以创建一些代码片段作为模板,具体操作见我写的这篇文章https://blog.csdn.net/fageaaa/article/details/145481103。
最终我们会初始化Login.vue和Main.vue中的内容。
Login.vue:
<template>
<div class="login">
<h2>login</h2>
</div>
</template>
<script setup lang="ts"></script>
<style lang="less" scoped></style>
Main.vue:
<template>
<div class="main">
<h2>main</h2>
</div>
</template>
<script setup lang="ts"></script>
<style lang="less" scoped></style>
在router/index.ts追加路由配置:
import { createRouter, createWebHashHistory } from 'vue-router'
const router = createRouter({
history: createWebHashHistory(),
// 映射关系: path => component
routes: [
{
path: '/',
redirect: '/main'
},
{
path: '/login',
component: () => import('../views/login/Login.vue')
},
{
path: '/main',
component: () => import('../views/main/Main.vue')
},
]
})
//后面要做路由导航守卫
export default router
当地址栏输入的网址没有对应页面的时候应该跳转到not found页面。新建not-found文件夹,并且初始化其中的vue文件内容。
NotFound.vue:
<template>
<div class="not-found">
<h2>您输入的路径地址不正确, 请联系管理员~</h2>
</div>
</template>
<script setup lang="ts"></script>
<style lang="less" scoped>
.not-found {
color: purple;
}
</style>
在router/index.ts可继续追加路由配置:
import { createRouter, createWebHashHistory } from 'vue-router'
const router = createRouter({
history: createWebHashHistory(),
// 映射关系: path => component
routes: [
...
{
path: '/:pathMatch(.*)',
component: () => import('../views/not-found/NotFound.vue')
}
]
})
//后面要做路由导航守卫
export default router
可以运行项目测试一下。
3.状态管理配置
- vuex: 目前依然使用较多的状态管理库;
- pinia: 强烈推荐, 未来趋势的状态管理库;
- …
3.1安装pinia
npm install pinia
在store文件夹(没有该文件夹就在src下创建一个)中创建index.ts文件:
import { createPinia } from 'pinia'
const pinia = createPinia()
export default pinia
3.2挂载pinia
在main.ts中挂载:
import { createApp } from 'vue'
import 'normalize.css'
import './assets/css/index.less'
import App from './App.vue'
import router from './router'
import pinia from './store'
const app = createApp(App)
app.use(router)
app.use(pinia)
app.mount('#app')
3.3创建一个store文件
在store文件中创建counter.ts文件:
import { defineStore } from 'pinia'
const useCounterStore = defineStore('counter', {
state: () => ({
counter: 100
}),
getters: {
doubleCounter(state) {
return state.counter * 2
}
},
actions: {
changeCounterAction(newCounter: number) {
this.counter = newCounter
}
}
})
export default useCounterStore
3.4应用store
<template>
<div class="main">
<h2>main: {{ counterStore.counter }}-{{ counterStore.doubleCounter }}</h2>
<button @click="changeCounter">修改counter</button>
</div>
</template>
<script setup lang="ts">
import useCounterStore from '@/store/counter'
const counterStore = useCounterStore()
function changeCounter() {
counterStore.changeCounterAction(999)
}
</script>
<style lang="less" scoped>
.main {
color: red;
}
</style>
4.网络请求封装axios
4.1再封装axios
需要对axios进行再封装。之后我会专门写一篇文章详细讲述封装axios的思路。下面是封装axios的目录结构:
service/config/index.ts:
let BASE_URL='接口地址';
const TIME_OUT = 10000;
export {
BASE_URL,
TIME_OUT
}
service/request/index.ts:
import axios from 'axios'
import type { AxiosInstance } from 'axios'
import type { HYRequestConfig } from './type'
// 拦截器: 蒙版Loading/token/修改配置
/**
* 两个难点:
* 1.拦截器进行精细控制
* > 全局拦截器
* > 实例拦截器
* > 单次请求拦截器
*
* 2.响应结果的类型处理(泛型)
*/
class HYRequest {
instance: AxiosInstance
// request实例 => axios的实例
constructor(config: HYRequestConfig) {
this.instance = axios.create(config)
// 每个instance实例都添加拦截器
this.instance.interceptors.request.use(
(config) => {
// loading/token
return config
},
(err) => {
return err
}
)
this.instance.interceptors.response.use(
(res) => {
return res.data
},
(err) => {
return err
}
)
// 针对特定的hyRequest实例添加拦截器
this.instance.interceptors.request.use(
config.interceptors?.requestSuccessFn,
config.interceptors?.requestFailureFn
)
this.instance.interceptors.response.use(
config.interceptors?.responseSuccessFn,
config.interceptors?.responseFailureFn
)
}
// 封装网络请求的方法
// T => IHomeData
request<T = any>(config: HYRequestConfig<T>) {
// 单次请求的成功拦截处理
if (config.interceptors?.requestSuccessFn) {
config = config.interceptors.requestSuccessFn(config)
}
// 返回Promise
return new Promise<T>((resolve, reject) => {
this.instance
.request<any, T>(config)
.then((res) => {
// 单词响应的成功拦截处理
if (config.interceptors?.responseSuccessFn) {
res = config.interceptors.responseSuccessFn(res)
}
resolve(res)
})
.catch((err) => {
reject(err)
})
})
}
get<T = any>(config: HYRequestConfig<T>) {
return this.request({ ...config, method: 'GET' })
}
post<T = any>(config: HYRequestConfig<T>) {
return this.request({ ...config, method: 'POST' })
}
delete<T = any>(config: HYRequestConfig<T>) {
return this.request({ ...config, method: 'DELETE' })
}
patch<T = any>(config: HYRequestConfig<T>) {
return this.request({ ...config, method: 'PATCH' })
}
}
export default HYRequest
service/request/type.ts:
import type { AxiosRequestConfig, AxiosResponse } from 'axios'
// 针对AxiosRequestConfig配置进行扩展
export interface HYInterceptors<T = AxiosResponse> {
requestSuccessFn?: (config: AxiosRequestConfig) => AxiosRequestConfig
requestFailureFn?: (err: any) => any
responseSuccessFn?: (res: T) => T
responseFailureFn?: (err: any) => any
}
export interface HYRequestConfig<T = AxiosResponse> extends AxiosRequestConfig {
interceptors?: HYInterceptors<T>
}
service/index.ts:
import { BASE_URL, TIME_OUT } from './config'
import HYRequest from './request'
const hyRequest = new HYRequest({
baseURL: BASE_URL,
timeout: TIME_OUT
})
export default hyRequest
4.2使用封装后的axios
在Login.vue中做测试:
<template>
<div class="login">
<h2>login</h2>
</div>
</template>
<script setup lang="ts">
import hyRequest from '@/service'
hyRequest
.get({
url: '/home/multidata'
})
.then((res) => {
console.log(res)
})
</script>
<style lang="less" scoped>
.login {
color: red;
}
</style>
运行项目看看控制台有没有打印出相应的结果。
这样子说明已经成功。
下一章节https://blog.csdn.net/fageaaa/article/details/145513384我将详细讲述一下vue实战项目中开发环境和生产环境的区别。