- Node:
14.14.0
- npm:
6.14.8
- Vue:
^2.6.11
- VueX:
^3.2.0
- node-sass:
^4.14.1
- sass-loader:
^10.1.1
- dayjs:
^1.11.7
- uview-ui:
^2.0.35
- uni-read-pages:
^1.0.5
@vue/cli 5.0.8 - postcss-loader、autoprefixer:(解决报错:
Error: PostCSS plugin autoprefixer requires PostCSS 8.·)
npm i postcss-loader [email protected]` - uniapp-weapp-starter-template
yarn install
yarn serve
yarn build
tuoyingtao-applet-starter-template
├── elemtn-ui -- 第三方UI组件
├── expand-components -- 扩展组件
├ ├── drag -- 拖拽组件
├── public -- 公用文件,不经过webpack处理
├── src -- 核心模块
├ ├── api -- 请求接口配置模块
├ ├── common -- 公共css/js模块
├ ├── components -- 公共组件模块
├ ├── config -- 全局配置模块
├ ├── enum -- 枚举模块
├ ├── event -- 监听事件模块
├ ├── pages -- 小程序业务主包目录
├ ├── pages_* -- 小程序业务分包目录
├ ├── static -- 小程序主包静态文件
├ ├── store -- vuex存储模块
├ ├── utils -- 工具模块
├ ├ └── request -- 请求工具模块
├ ├── wxcomponents -- 小程序第三方组件模块
├ ├── App.vue -- 项目入口文件
├ ├── main.js -- 项目主入口
├ ├── manifest.json -- uniapp 小程序配置应用名称、appid、logo、版本等打包信息,详见
├ ├── pages.json -- 小程序配置页面路由、导航条、选项卡等页面类信息,详见
├ └── uni.scss -- uniapp 全局css样式
├── .gitignore -- git排除文件配置
├── package.json -- npm配置
├── package-lock.json -- npm配置锁文件
└── vue.config.js -- vue脚手架配置
放在wxcomponents
目录中的一切文件,无论是否使用,都会被打包。
整个 vant 所有组件体积为374k,可使用小程序的依赖分析查看
考虑到体积优化问题,本仓库将完整的vant组件放在外层的 `/elemtn-ui/vant-weapp` 目录中。
如需使用里面的组件,再自行Copy到 `/wxcomponents/vant/` 目录中
例如使用 <van-button>
组件
- 从
/elemtn-ui/vant-weapp
中复制 button 目录到/src/wxcomponents/vant/
中 - 在
/src/page.json
中配置
"globalStyle": {
"usingComponents": {
"van-button": "/wxcomponents/vant/button/index",
}
}
- 检查该组件的依赖项有些组件依赖了
common/
下的js,有些组件则依赖了其他组件可通过该组件中的xxx.json
查看,或直接看编译器提示这里button
组件这里依赖了loading
和icon
组件,也需要一并移入并在page.json
中配置 一般来说,这几个目录是所有组件都依赖的common
、wxs
、mixins
。 - 页面中使用 按钮
在 Config 文件夹下的config.js
中配置请求域名地址、不同平台的小程序 APPID 以及 COS 云存储对象地址。最终config.js
对外暴露的的只有GLOBAL_CONFIG
对象,而GLOBAL_CONFIG
对象下的所有属性都将加入到应用环境中(process.env
)。
APPLET_MAP
小程序各平台的AppID。COS_DATA
云存储对象桶与地域信息配置。REQUEST_PATH
请求域名地址。UNI_STATISTICS
是否开启uni统计。OPTIMIZATION
分包优化。
process.env
下的所有属性包含上面的那几个:
VUE_APP_NAME
:应用程序名称(取自package.json
下的name
)。APP_VERSION
:应用程序版本号(取自package.json
下的version
)。VUE_APP_PLATFORM
:当前是那个平台的小程序。NODE_ENV
:当前应用环境。VUE_APP_DEBUG
:DEBUG 模式启动。API_BASE_URL
:域名地址。APPLET_APPID
:小程序APPID。BASE_URL
:默认API。PREVIEW_PICTURE_URL
:COS 云存储对象域名。VUE_APP_DARK_MODE
:暗黑模式也被称为夜间模式或深色模式。(在框架中不做任何处理,对暗黑模式感兴趣的请前往官网介绍)
// 使用方式
process.env.VUE_APP_NAME
前言:在项目开发过程中通常会有多种状态类型处理,我们会大量的使用【0,1】作为状态的标识,如果项目体系较大会导致我们在维护阅读时成本提高。
为解决这个问题,我在本框架中自定义了一个Enum.js
(枚举类)以及GlobalEnums.js
(枚举实现工具)作为全局枚举统一管理。
-
Enum.js
类中提供getEnumInstance(definition)
静态方法用于初始化枚举对象,接收的参数为对象。definition
:参数对象的值为数组getValue(enumKey)
:enumKey
枚举属性名称,返回枚举状态Value值。getDescMessage(enumValue)
:enumValue
枚举状态Value值,返回枚举详情信息。
-
GlobalEnums.js
引入了Enum.js
所有在开发的过程中我们只需要通过Enum.getEnumInstance(definition)
来创建我们的枚举实现工具。export const NaiveCardEnum = Enum.getEnumInstance({ PATH_PAGE: [1, "页面路径"], PATH_APPLET: [2, "小程序路径"], });
在项目业务逻辑中使用方式:
/** 获取枚举状态值 */
NaiveCardEnum.PATH_PAGE // 1
NaiveCardEnum.getValue('PATH_PAGE') // 1
/** 获取枚举状态值 */
NaiveCardEnum.getDescMessage(status) // 页面路径
let status = 1;
if (NaiveCardEnum.PATH_PAGE == status) // true
注意事项:
BUG:definition
属性名尽量不要同名,这会导致同名属性值被覆盖。(有解决方案的小伙伴还请 Issues)
// 错误案例
export const NaiveCardEnum = Enum.getEnumInstance({
PATH_PAGE: [1, "页面路径"],
PATH_APPLET: [2, "小程序路径"],
});
export const PagePathEnum = Enum.getEnumInstance({
PATH_PAGE: [4, "PagePath页面路径"],
PATH_APPLET: [5, "PagePath小程序路径"],
});
前言:页面之间的跳转有时会携带一些特点的参数,但在有些业务场景下使用页面路径携带参数进行跳转,会显得特别的臃肿。我在这里举一个简单的例子:在页面A中存在一个count
属性默认值为0,用于记录页面B商品预览次数。如果页面B触发了商品预览则页面A中的count
属性加1。这时候我们就需要在页面A中定义一个监听事件,用于捕获页面B所触发的预览事件。(当然这上面的业务场景你们可以用Store
或者本地缓存都能实现)
Event.js
事件类:对uni.$emit(key,data)
、uni.$on(key,callback)
等方法做了一层封装。
EVENT_LIST
静态属性:用于记录已存在的事件。getEnumInstance(eventName)
静态方法:获取新的Event
实例,传递事件名参数。getEventList()
分别提供一个公用、静态方法:用于获取已存在的事件。$emit(data)
触发事件:传递一个事件参数。$on(callback)
监听事件:监听$emit(data)
所触发的事件,callback
回调函数接收事件参数。$once(callback)
一次性使用事件,触发后将其移除:监听$emit(data)
所触发的事件,callback
回调函数接收事件参数。$off(callback)
移除监听事件:监听$emit(data)
所触发的事件,callback
回调函数接收事件参数。
GlobalEvents.js
引入了Event.js
所有在开发的过程中我们只需要通过Event.getEnumInstance(eventName)
来创建我们的事件监听器。
export const eventUserLogin = Event.getEnumInstance("user_login");
在项目业务逻辑中使用方式:
// 页面A
eventUserLogin.$on((e) => {
console.log("事件触发:" + data)
})
eventUserLogin.$once((e) => {
console.log("一次性事件触发:" + data)
})
eventUserLogin.$off((e) => {
console.log("移除事件触发:" + data)
})
// 页面B
eventUserLogin.$emit("页面B的事件参数");
注意事项:
在使用事件监听工具类时,事件接收器($on
、$once
、$off
)一定要优先于事件触发器($emit
)加载,否则事件接收器将失效。
在这个框架中的request
文件夹下,定义了请求工具类,用于服务端与客户端之间的交互。
一、Reqeust.js
config
:uni.request()
官网的配置。
options
:requestOptions
配置信息。
Reqeust.js
请求类,它是在uni.request()
基础上做了一层封装,里面含有基本的请求方式等一些功能。
-
get
、post
、put
、delete
、patch
:在这些方法中都接收两个参数分别是config
、options
(这两个参数的详细内容,后续在做介绍) -
getRequest()
:获取Request
实例,通过这种方式获取的请求实例,可更具自己的需要选择性的配置。import { request } from "@/utils/request"; const requestInstance = request.getRequest(); const instance = requestInstance({ url: '/home', method: 'GET', data: {}, }, { /** options 配置 */ }); instance.then((response) => {}); instance.catch((error) => {});
-
setConfigRequest(options)
:设置Request
配置参数,这里的配置参数是指options
。 -
executor(config, options)
:核心执行方法。
二、RequestConstant.js
Request 请求常量信息:
REQUEST_STATUS_CODE
:服务端请求响应code
常量。CONTENT_TYPE_MAP
:Reqeust 请求content-type
常量。RESPONSE_TYPE_MAP
:uni.request()
请求响应类型。(参照uni.request()
官方文档)DATA_TYPE_MAP
:uni.request()
请求数据类型。(参照uni.request()
官方文档)
三、ResponseErrorHandler.js
Request 请求错误异常类:
NetworkError
:网络异常类。RequestError
:Http 请求异常类。ResponseError
:Request 响应异常类。
四、index.js配置
isSilenceLock
:静默锁;用于小程序静默登录控制。onAccessTokenFetched
:在静默登录成功后,重新发起之前没有通过的请求。transform
:Request 请求处理方法,在这个对象中有请求、响应的前后置处理。transformRequestHook(response, options)
:响应处理;beforeRequestHook(config, options)
:请求前置处理;requestInterceptors(config, options)
:请求前的拦截器;responseInterceptors([error, response], conf)
:响应拦截器;responseInterceptorsCatch(error)
:响应错误拦截;
createRequest(options)
:创建 Request 请求实例对象。在这个方法中new VRequest(options)
并将其返回。而这个options
则是基本请求配置信息。
五、使用方法
除了上面通过getRequest()
获取请求实例与new VRequest()
的两种方式;还有一种最常规的写法,则是通过createRequest(options)
返回的请求实例:
import { request } from "@/utils/request";
export function homeApi(param) {
return request.get({
url: "/api/homeData",
params: param
}, {
urlPrefix: '/admin',
fieldToken: 'token',
// ...requestOptions
})
}
function getList() {
homeApi({ page: 1 }).then(data => {});
}
async function getList() {
try {
const data = await homeApi({ page: 1 });
// 只有请求成功了才会执行下面的代码。
console.log(data);
} catch (error) {
// 错误执行
}
}