Table of Contentsgenerated with DocToc
Vue3-Vite-Vant-TS-H5
基于Vue3 + Vite + Vant + Sass+ rem适配方案 + Axios封装,构建手机端模板脚手架
预览
查看 demo 建议手机端查看
关注我的掘金
掘金:Vue3 Vite Vant TS rem 移动端H5框架方案
贡献代码
使用过程中发现任何问题都可以提Issue 给我,也非常欢迎 PR 或 Pull Request
Node 版本要求
Vite 需要 Node.js 12.0.0 或更高版本 (推荐 14.0.0+)。你可以使用 nvm 或 nvm-windows 在同一台电脑中管理多个 Node 版本。
本示例 Node.js 14.18.1
启动项目
- ``` sh
- git clone https://github.com/talktao/Vue3-Vite-Vant-TS-H5.git
- cd Vue3-Vite-Vant-TS-H5
- yarn
- npm run dev
- 复制代码
- ```
目录
rem适配方案
VantUI组件按需加载
安装插件
Sass 全局样式
目录结构
父组件改变子组件样式 深度选择器
全局变量
Vuex 状态管理
Pinia 状态管理
1.安装
2. 创建Pinia的Store
3.在main.ts文件中引用
3. 定义State
i. 传统的options API方式
ii.Vue3 setup的编程模式
4.获取/修改 state
Vue-router
自动化导入路由
普通设置
Axios 封装及接口管理
接口管理
如何调用
vite.config.ts 基础配置
检查文件中的env路径
配置 alias 别名
配置 proxy 跨域
Eslint+Pettier 统一开发规范
批量全局注册公共组件
rem适配方案
Vant 中的样式默认使用px 作为单位,如果需要使用rem 单位,推荐使用以下两个工具:
postcss-pxtorem 是一款 postcss 插件,用于将单位转化为 rem
lib-flexible 用于设置 rem 基准值
更多详细信息: vant
VantUI组件按需加载
项目采 用Vant 自动按需引入组件 (推荐) 下 面安装插件介绍:
安装插件
- ``` sh
- yarn add vite-plugin-style-import -D
- 复制代码
- ```
在 vite.config.ts 设置
- ``` sh
- import vue from '@vitejs/plugin-vue';
- import styleImport, { VantResolve } from 'vite-plugin-style-import';
- export default {
- plugins: [
- vue(),
- styleImport({
- resolves: [VantResolve()],
- }),
- ],
- };
- ```
但是每次页面使用的时候还是要引入,很麻烦,项目在 src/plugins/vant.ts 下统一管理组件,无需在main.ts文件中多次use()
Sass 全局样式
首先 你可能会遇到 node-sass 安装不成功,别放弃多试几次!!!
每个页面自己对应的样式都写在自己的 .vue 文件之中 scoped 它顾名思义给 css 加了一个域的概念。
- ``` sh
- <style lang="scss">
- /* global styles */
- </style>
- <style lang="scss" scoped>
- /* local styles */
- </style>
- 复制代码
- ```
目录结构
vue-h5-template 所有全局样式都在 @/src/assets/css 目录下设置
- ``` sh
- ├── assets
- │ ├── scss
- │ │ ├── index.scss # 全局通用样式
- │ │ ├── mixin.scss # 全局mixin
- │ │ └── reset.scss # 清除标签默认样式
- │ │ └── variables.scss # 全局变量
- 复制代码
- ```
父组件改变子组件样式 深度选择器
当你子组件使用了 scoped 但在父组件又想修改子组件的样式可以 通过 >>> 来实现:
- ``` sh
- <style scoped>
- .a >>> .b { /* ... */ }
- </style>
- 复制代码
- ```
全局变量
- ``` sh
- // 引入全局样式
- import '@/assets/css/index.scss'
- ```
Vuex 状态管理
目录结构
- ``` sh
- ├── store
- │ ├── index.ts
- 复制代码
- ```
main.ts 引入
使用
Pinia 状态管理
1.安装
node版本需>=14.0.0
- ``` js
- yarn add pinia
- # or with npm
- npm install pinia
- ```
2. 创建Pinia的Store
在src/store/index.ts 文件中,导出 piniaStore
- ``` js
- // src/store/index.ts
- import { createPinia } from 'pinia'
- export const piniaStore = createPinia()
- ```
3.在main.ts文件中引用
3. 定义State
在src/store 目录下新建有个testPinia.ts 文件
i. 传统的options API方式
- ``` js
- import { defineStore } from "pinia"
- export const usePiniaState = defineStore({
- id: 'textPinia',
- state: () => {
- return {
- userName: ''
- }
- },
- getters: {
- },
- actions: {
- getUserNmae(data) {
- this.userName = data
- }
- }
- })
- ```
ii.Vue3 setup的编程模式
- ``` js
- import { ref } from 'vue'
- import { defineStore } from "pinia"
- export const usePiniaState = defineStore('pinia', ()=>{
- const userName = ref('')
- // 修改userName的方法
- const getUserNmae = (data) => {
- userName.value = data
- }
- return { userName, getUserNmae}
- })
- ```
4.获取/修改 state
- ``` js
- <script setup lang="ts">
- import { storeToRefs } from 'pinia'
- import { usePiniaState } from '@/store/testPinia'
- // pinia
- const piniaStore = usePiniaState()
- // 通过storeToRefs方法将存储在pinia里的数据解构出来,保持state响应性
- const { userName } = storeToRefs(piniaStore)
- const { getUserNmae } = piniaStore
- const handleBtn = () =>{
- // pinia
- getUserNmae('真乖,如果对您有帮助请在github上点个星星哦~')
- }
- </script>
- ```
Vue-router
本案例采用 hash 模式,开发者根据需求修改 mode base
自动化导入路由
- ``` js
- import { createRouter, createWebHashHistory, RouteRecordRaw } from "vue-router";
- // 通过Vite的import.meta.glob()方法实现自动化导入路由
- const mainRouterModules = import.meta.glob('../layout/*.vue')
- const viewRouterModules = import.meta.glob('../views/**/*.vue')
- // 子路由
- const childRoutes = Object.keys(viewRouterModules).map((path)=>{
- const childName = path.match(/\.\.\/views\/(.*)\.vue$/)[1].split('/')[1];
- return {
- path: `/${childName.toLowerCase()}`,
- name: childName,
- component: viewRouterModules[path]
- }
- })
- console.log(childRoutes,'childRouter');
- // 根路由
- const rootRoutes = Object.keys(mainRouterModules).map((path) => {
- const name = path.match(/\.\.\/layout\/(.*)\.vue$/)[1].toLowerCase();
- const routePath = `/${name}`;
- if (routePath === '/index') {
- return {
- path: '/',
- name,
- redirect: '/home',
- component: mainRouterModules[path],
- children: childRoutes
- };
- }
- })
- const routes: Array<RouteRecordRaw> = rootRoutes
- const router = createRouter({
- history: createWebHashHistory(),
- routes,
- });
- export default router
- ```
普通设置
- ``` js
- import { createRouter, createWebHashHistory, RouteRecordRaw } from "vue-router";
- const routes: Array<RouteRecordRaw> = [
- {
- path: '/',
- name: 'Index',
- component: () => import ('@/layout/index.vue'),
- redirect: '/home',
- meta: {
- title: '首页',
- keepAlive:false
- },
- children: [
- {
- path: '/home',
- name: 'Home',
- component: () => import('@/views/home/Home.vue')
- },
- {
- path: '/about',
- name: 'About',
- component: () => import('@/views/about/About.vue')
- },
- ]
- },
- ]
- const router = createRouter({
- history: createWebHashHistory(),
- routes,
- });
- export default router
- ```
更多:Vue Router
Axios 封装及接口管理
utils/request.js 封装 axios ,开发者需要根据后台接口做修改。
接口管理
在src/api 文件夹下统一管理接口
通过引入axios库的ts版本即可配置
- ``` js
- import axiosInstance, { AxiosResponseProps } from '@/uitls/request'
- export const getList = (params: any) => {
- return axiosInstance.get("/common/code/logisticsInfo/getOrderByPhone", { params: params || {} });
- }
- ```
如何调用
- ``` sh
- // 请求接口
- import { getUserInfo } from '@/api/home'
- const params = {user: 'talktao'}
- getUserInfo(params)
- .then(() => {})
- .catch(() => {})
- 复制代码
- ```
vite.config.ts 基础配置
检查文件中的env路径
配置 alias 别名
- ``` sh
- resolve: {
- alias:{
- // 配置src目录
- "@": path.resolve(__dirname,"src"),
- // 导入其他目录
- "components": path.resolve(__dirname, "components")
- }
- },
- ```
配置 proxy 跨域
如果你的项目需要跨域设置,你需要打开 vite.config.ts proxy 注释 并且配置相应参数
注意:你还需要将 src/env.development 里的 VITE_BASE_URL 设置成 '/'
- ``` sh
- module.exports = {
- // 跨域代理
- server:{
- proxy:{
- //这里是通过请求/api 来转发到 https://api.pingping6.com/
- //假如你要请求https://api.*.com/a/a
- //那么axios的url,可以配置为 /api/a/a
- '/api': ''
- }
- }
- }
- ```
Eslint+Pettier 统一开发规范
VScode安装 eslint prettier vetur 插件 .vue 文件使用 vetur 进行格式化,其他使用prettier
批量全局注册公共组件
文件地址在 src/plugins/components
- ``` js
- const modules = import.meta.globEager('../components/*.vue')
- export default {
- install(app) {
- Object.keys(modules).forEach(componentPath => {
- let splitPart1 = componentPath.split("/")
- let componentName = splitPart1[splitPart1.length - 1].split(".vue")[0]
- // 获取所有组件的实例对象,它是个数组
- let modulesData = Object.values(modules).map((v) => v.default)
- // 过滤出当前组件的实例对象与注册组件匹配一致
- let curComponent = modulesData.filter(
- item=>item.__file.split("/")[item.__file.split("/").length-1].split(".vue")[0] === componentName
- )[0]
- app.component(componentName, curComponent);
- })
- }
- }
- ```
上面的批量全局注册公共组件在本地启动中正常,但是上生产打包后,会有问题,具体是__file该组件路径找不到,可以修改成如下代码:
- ``` js
- const modules = import.meta.globEager('../components/*.vue')
- export default {
- install(app) {
- Object.keys(modules).forEach(componentPath => {
- // 获取遍历的当前组件实例对象
- let curComponent = modules[componentPath]?.default
- app.component(curComponent.name, curComponent);
- })
- }
- }
- ```
注意:
由于sfc语法糖没有携带组件的name属性,上面的curComponent.name会报curComponent下没有name属性,此时需要在注册的公共组件中加上如下代码,比如在src/components/CustomHeader.vue中加上如下代码,这样组件的实例对象中就会有name属性
关于我
如果对你有帮助送我一颗小星星(づ ̄3 ̄)づ╭❤~
转载请联系作者!