本文主要将如何利用搭建一个初始化的商城H5项目框架。初始化阶段使用的技术栈有:vue3.2、vue-router、 TS 、 Pinia 、 Vant4、Less、vite
node -v 检测是否有安装node.js,未安装请先去官网安装node.js
终端输入: npm init vite
自定义项目名称project name:demodemo
依次选择Vue + TypeScript创建项目
启动项目: cd demodemo
npm install
npm run dev
删除style.css文件,清空assets文件和components文件
新增request文件(配置网络请求和集中存储请求API),文件下新建index.ts和api.ts两个空文件
新增store文件(数据共享仓库),文件下新建index.ts和order.ts和address.ts三个空文件
新增views文件(集中存放各页面),文件下新建Home.vue和Login.vue和404.vue等空文件
新增types文件(声明TS类型),文件下新建api.d.ts一个空文件
处理App.vue文件
//App.vue
//路由占位符
处理main.ts文件
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
app.mount('#app')
npm i reset-css
//在main.ts中引入
import "reset-css" //样式初始化
npm i vant
//在main.ts中引入vant
import vant from "vant"
import "../node_modules/vant/lib/index.css"
npm i postcss-px-to-viewport --save -dev
新建文件postcss.config.cjs,配置设计稿的视口宽度:viewportWidth: 375,其余可选配置
//postcss.config.cjs文件
module.exports = {
plugins: {
'postcss-px-to-viewport': {
viewportWidth: 375, // 设计稿的视口宽度
unitPrecision: 5, // 单位转换后保留的精度
propList: ["*"], // 能转化为vw的属性列表
viewportUnit: "vw", // 希望使用的视口单位
fontViewportUnit: "vw", // 字体使用的视口单位
selectorBlackList: [], // 需要忽略的CSS选择器,不会转为视口单位,使用原有的px等单位。
minPixelValue: 1, // 设置最小的转换数值,如果为1的话,只有大于1的值会被转换
mediaQuery: false, // 媒体查询里的单位是否需要转换单位
replace: true, // 是否直接更换属性值,而不添加备用属性
exclude: undefined, // 忽略某些文件夹下的文件或特定文件,例如 'node_modules' 下的文件
include: undefined, // 如果设置了include,那将只有匹配到的文件才会被转换
landscape: false, // 是否添加根据 landscapeWidth 生成的媒体查询条件 @media (orientation: landscape)
landscapeUnit: "vw", // 横屏时使用的单位
landscapeWidth: 568, // 横屏时使用的视口宽度
},
},
};
npm i -D unplugin-auto-import
//在vite.config.ts中配置
import AutoImport from "unplugin-auto-import/vite"
export default defineConfig({
plugins: [
vue(),
AutoImport({
imports: [ 'vue', 'vue-router'] //自动导入相关函数
})
],
})
npm i axios
//在request文件下的index.ts配置
import axios from "axios"
const instance = axios.create({
baseURL: "https://XXXXXX.com",
timeout: 20000
})
//请求拦截器
instance.interceptors.request.use(
config => {
if(localStorage.getItem('token')){
config.headers.Authorization = localStorage.getItem('token')
}
return config
},
err => {
return Promise.reject(err)
}
)
// 响应拦截器
instance.interceptors.response.use(
res => {
return res.data
},
err => {
return Promise.reject(err)
}
)
export default instance
//在request文件下的api.ts配置
import request from "./index"
export const helpCenterRes = () => request.get('/helpcenter')
export const bannerAPIRes = ( params: BannerAPIReq ):Promise => request.get('/banner', {params})
interface BannerAPIReq {
title: string;
}
interface BannerListType {
detail_url: string;
picture: string;
url: string;
}
interface BannerAPIRes {
code: number;
message: string;
banner: BannerListType[];
}
//在Index.vue中使用封装的接口
npm i vue-router //下载vue-router插件第四版本
//main.ts中引入和挂载路由
import router from './router'
app.use(router)
//router/index.ts
import { createRouter, createWebHistory, RouteRecordRaw } from "vue-router";
import Home from "../views/Home.vue"
import Index from "../views/Index.vue"
const routes: Array = [
{
path: '/',
component: Home,
redirect: '/index', //路由重定向
children: [ //路由嵌套
{
path: 'index',
name: 'Index',
component: Index
},
{
name: 'Wash',
path: 'wash',
component: () => import('../views/Wash.vue')
},
{
name: 'Order',
path: 'order',
component: () => import('../views/Order.vue')
},
{
name: 'My',
path: 'my',
component: () => import('../views/My.vue')
}
]
},
{
name: 'Login',
path: '/login',
component: () => import('../views/Login.vue')
},
{
name: "404",
path: "/:pathMatch(.*)*",
component: () => import('../views/404.vue')
}
]
const router = createRouter({
history: createWebHistory(),
routes
})
router.beforeEach( ( news,old,next ) => {
next()
})
export default router
npm i pinia
npm i pinia-plugin-persist
//在store/index.ts配置pinia和共享数据持久化处理
import { createPinia } from "pinia";
import piniaPluginPersist from "pinia-plugin-persist"
const store = createPinia()
store.use(piniaPluginPersist)
export default store
//在mian.ts中引入并挂载pinia
import store from "../src/store/index"
app.use(store)
为了避免共享的数据混乱放在一个文件下,因此需模块化处理不同页面的共享数据
order.ts表示订单页面涉及到的共享数据及数据的处理方法
address.ts表示地址页面涉及到的共享数据及数据的处理方法
以order.ts为示例
import { defineStore } from "pinia";
export const orderStore = defineStore( "order", {
//存放需要共享的数据
state: () => {
return {
orderType: "takein",
count: 1
}
},
//Store 状态的计算值
getters: {
doubleCount: (state) => state.count * 2
},
//存放同步和异步方法
actions: {
countAdd(num: number){
this.count = this.count + num
}
},
//开启数据持久化存储
persist: {
enabled: true
}
})
//在页面使用store中的数据
state中的数据响应式展示: {{ count }}
getters中的数据响应式展示: {{ doubleCount }}
开启数据持久化存储后,刷新页面,数据不会变成原始数据
在index.html文件配置网站logo和网站名称
网站logo的是.ico格式,其他格式图片需要转成.ico文件
//配置logo
XXXXX有限公司官方网站 //配置网站名称
npm i less -D
//Home.vue中配置tabbar栏数据和跳转路由等,同时在router/index.ts中配置相应的路由
{{ item.title }}
效果图如下: