# 微信小程序开发环境
# 微信小程序工具下载
# 小程序代码构成
.json 后缀的 JSON 配置文件
.wxml 后缀的 WXML 模板文件
.wxss 后缀的 WXSS 样式文件
.js 后缀的 JS 脚本逻辑文件
# JSON 配置
主要的 json 配置为 app.json
, project.config.json
和每个页面下的 json 文件
# 小程序配置 app.json
app.json
是当前小程序的全局配置,包括了小程序的所有页面路径、界面表现、网络超时时间、底部 tab 等。
{
"pages": ["pages/index/index", "pages/logs/logs"],
"window": {
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "Weixin",
"navigationBarTextStyle": "black"
}
}
2
3
4
5
6
7
8
9
- pages 字段 —— 用于描述当前小程序所有页面路径,这是为了让微信客户端知道当前你的小程序页面定义在哪个目录。
- window 字段 —— 定义小程序所有页面的顶部背景颜色,文字颜色定义等。
其他配置可参考小程序文档
# 工具配置 project.config.json
通常大家在使用一个工具的时候,都会针对各自喜好做一些个性化配置,例如界面颜色、编译配置等等,当你换了另外一台电脑重新安装工具的时候,你还要重新配置。
考虑到这点,小程序开发者工具在每个项目的根目录都会生成一个project.config.json
,你在工具上做的任何配置都会写入到这个文件,当你重新安装工具或者换电脑工作时,你只要载入同一个项目的代码包,开发者工具就自动会帮你恢复到当时你开发项目时的个性化配置,其中会包括编辑器的颜色、代码上传时自动压缩等等一系列选项。
# 页面配置 page.json
这里的 page.json
其实用来表示 pages/logs
目录下的 logs.json
这类和小程序页面相关的配置。开发者可以独立定义每个页面的一些属性。
# WXML 模板
类似于 html,用来描述页面结构的文件,和 HTML 非常相似,WXML 由标签、属性等等构成。但是也有很多不一样的地方。例如标签的名称,能使用 wx:if
, wx:for
等属性和{{}}
的表达式,具体参考https://developers.weixin.qq.com/miniprogram/dev/reference/wxml/
。如<text></text>
Js 文件通过这种方式渲染变量
this.setData({ msg: "Hello World" })
# WXSS 样式
WXSS 具有 CSS 大部分的特性,小程序在 WXSS 也做了一些扩充和修改。
- 新增了尺寸单位。在写 CSS 样式时,开发者需要考虑到手机设备的屏幕会有不同的宽度和设备像素比,采用一些技巧来换算一些像素单位。WXSS 在底层支持新的尺寸单位 rpx ,开发者可以免去换算的烦恼,只要交给小程序底层来换算即可,由于换算采用的浮点数运算,所以运算结果会和预期结果有一点点偏差。
- 提供了全局的样式和局部样式。和前边 app.json, page.json 的概念相同,你可以写一个 app.wxss 作为全局样式,会作用于当前小程序的所有页面,局部页面样式 page.wxss 仅对当前页面生效。
- 此外 WXSS 仅支持部分 CSS 选择器
更详细的文档可以参考 WXSS (opens new window) 。
JS 逻辑交互
负责用户交互,响应用户的点击、获取用户的位置等等。此外你还可以在 JS 中调用小程序提供的丰富的 API,利用这些 API 可以很方便的调起微信提供的能力,例如获取用户信息、本地存储、微信支付等。
# 宿主环境
# 渲染层和逻辑层
小程序的运行环境分成渲染层和逻辑层,其中 WXML 模板和 WXSS 样式工作在渲染层,JS 脚本工作在逻辑层。
小程序的渲染层和逻辑层分别由 2 个线程管理:渲染层的界面使用了 WebView 进行渲染;逻辑层采用 JsCore 线程运行 JS 脚本。一个小程序存在多个界面,所以渲染层存在多个 WebView 线程,这两个线程的通信会经由微信客户端(图中 Native 代指微信客户端)做中转,逻辑层发送网络请求也经由 Native 转发,小程序的通信模型下图所示。
# 程序与页面
微信客户端在打开小程序之前,会把整个小程序的代码包下载到本地。
紧接着通过 app.json 的 pages 字段就可以知道你当前小程序的所有页面路径:
{
"pages": ["pages/index/index", "pages/logs/logs"]
}
2
3
写在 pages 字段的第一个页面就是这个小程序的首页(打开小程序看到的第一个页面)。
于是微信客户端就把首页的代码装载进来,通过小程序底层的一些机制,就可以渲染出这个首页。
小程序启动之后,在 app.js 定义的 App 实例的 onLaunch 回调会被执行:
App({
onLaunch: function () {
// 小程序启动之后 触发
}
})
2
3
4
5
整个小程序只有一个 App 实例,是全部页面共享的。
页面的实现是这样的,以 pages/logs/logs 为例,微信客户端会先根据 logs.json 配置生成一个界面,顶部的颜色和文字你都可以在这个 json 文件里边定义好。紧接着客户端就会装载这个页面的 WXML 结构和 WXSS 样式。最后客户端会装载 logs.js,你可以看到 logs.js 的大体内容就是:
Page({
data: { // 参与页面渲染的数据
logs: []
},
onLoad: function () {
// 页面渲染后 执行
}
})
2
3
4
5
6
7
8
Page 是一个页面构造器,这个构造器就生成了一个页面。在生成页面的时候,小程序框架会把 data 数据和 index.wxml 一起渲染出最终的结构,于是就得到了你看到的小程序的样子。
在渲染完界面之后,页面实例就会收到一个 onLoad 的回调,你可以在这个回调处理你的逻辑。
# 组件
和 HTML 的 div,p 标签一样,在小程序里边,你只需要在 WXML 写上对应的组件标签名字就可以把该组件显示在界面上,组件的内部行为也会通过事件的形式让开发者可以感知,当然你也可以通过 style 或者 class 来控制组件的外层样式,以便适应你的界面宽度高度等等。
# API
为了让开发者可以很方便的调起微信提供的能力,例如获取用户信息、微信支付等等,小程序提供了很多 API 给开发者去使用。
需要注意的是:多数 API 的回调都是异步,你需要处理好代码逻辑的异步问题。
# 架构
# 逻辑层
小程序开发框架的逻辑层使用 JavaScript 引擎为小程序提供开发 JavaScript 代码的运行环境以及微信小程序的特有功能。开发者写的所有代码最终将会打包成一份 JavaScript 文件,并在小程序启动的时候运行,直到小程序销毁。这一行为类似 ServiceWorker,所以逻辑层也称之为 App Service。小程序框架的逻辑层并非运行在浏览器中,因此 JavaScript 在 web 中一些能力都无法使用,如 window,document 等。
# 小程序注册
// app.js
App({
onLaunch(options) {
// Do something initial when launch.
},
onShow(options) {
// Do something when show.
},
onHide() {
// Do something when hide.
},
onError(msg) {
console.log(msg);
},
globalData: "I am global data",
});
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
整个小程序只有一个 App 实例,是全部页面共享的。开发者可以通过 getApp 方法获取到全局唯一的 App 实例,获取 App 上的数据或调用开发者注册在 App 上的函数。
// xxx.js
const appInstance = getApp();
console.log(appInstance.globalData); // I am global data
2
3
# 页面注册
//index.js
Page({
data: {
text: "This is page data.",
},
onLoad: function (options) {
// 页面创建时执行
},
onShow: function () {
// 页面出现在前台时执行
},
onReady: function () {
// 页面首次渲染完毕时执行
},
onHide: function () {
// 页面从前台变为后台时执行
},
onUnload: function () {
// 页面销毁时执行
},
onPullDownRefresh: function () {
// 触发下拉刷新时执行
},
onReachBottom: function () {
// 页面触底时执行
},
onShareAppMessage: function () {
// 页面被用户分享时执行
},
onPageScroll: function () {
// 页面滚动时执行
},
onResize: function () {
// 页面尺寸变化时执行
},
onTabItemTap(item) {
// tab 点击时执行
console.log(item.index);
console.log(item.pagePath);
console.log(item.text);
},
// 事件响应函数
viewTap: function () {
this.setData(
{
text: "Set some data for updating view.",
},
function () {
// this is setData callback
}
);
},
// 自由数据
customData: {
hi: "MINA",
},
});
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# 生命周期
# 模块化
类似 java 中的工具类,将一些公共代码抽成单独的 js 文件
// common.js
function sayHello(name) {
console.log(`Hello ${name} !`);
}
function sayGoodbye(name) {
console.log(`Goodbye ${name} !`);
}
module.exports.sayHello = sayHello;
exports.sayGoodbye = sayGoodbye;
// 使用
var common = require("common.js");
Page({
helloMINA: function () {
common.sayHello("MINA");
},
goodbyeMINA: function () {
common.sayGoodbye("MINA");
},
});
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
小程序不支持引入 node_module,不过小程序支持 npm,跟一般前端开发使用的 npm 方式有略微不同。
# 视图层
框架的视图层由 WXML 与 WXSS 编写,由组件来进行展示。
将逻辑层的数据反映成视图,同时将视图层的事件发送给逻辑层。
# WXML
# WXSS
https://developers.weixin.qq.com/miniprogram/dev/framework/view/wxss.html
wxss 相比 css 主要是在尺寸单位和样式导入上。
# 事件
事件是视图层到逻辑层的通讯方式。
# 绑定方式:
组件中的属性 bind***
,参数携带 data-xxx
Page({
tapName: function(event) {
console.log(event)
}
})
2
3
4
5
# 事件类型
https://developers.weixin.qq.com/miniprogram/dev/framework/view/wxml/event.html
# uni-app 介绍
uni-app 是一个使用 Vue.js 开发所有前端应用的框架,开发者编写一套代码,可发布到 iOS、Android、Web(响应式)、以及各种小程序(微信/支付宝/百度/头条/飞书/QQ/快手/钉钉/淘宝)、快应用等多个平台。
所以说,可以通过 uni-app,使用 vue.js 来开发小程序。使用 HBuilder 进行 uni-app 的开发,当编写好代码后,点击小程序运行,程序会自动打开微信开发者工具并进行编译,之后就可以在微信开发者工具中进行调试。
除了能一套代码多端运行之外,uni-app 还提供和微信小程序云开发一样的 uniCloud 的服务。微信小程序在 2022 年已经停止了开发版的云开发,现在要使用微信小程序的云开发至少得需要 19.9 的费用。同微信小程序的云开发相比,uniCloud 除了腾讯云之外还能使用阿里云的开发版云服务空间,这个服务空间是免费的,能很好的满足开发需求。
# uni-app 使用
下载开发 uni-app 配套的工具 HbuilderX: https://www.dcloud.io/hbuilderx.html
打开 HbuiderX,新建项目,选择 uni-app 类型,输入工程名,选择模版,点击创建。
# 项目结构
一个 uni-app 工程,默认包含如下目录及文件:
┌─uniCloud 云空间目录,支付宝小程序云为 uniCloud-alipay,阿里云为 uniCloud-aliyun,腾讯云为 uniCloud-tcb(详见 uniCloud) │─components 符合 vue 组件规范的 uni-app 组件目录 │ └─comp-a.vue 可复用的 a 组件 ├─utssdk 存放 uts 文件 ├─pages 业务页面文件存放的目录 │ ├─index │ │ └─index.vue index 页面 │ └─list │ └─list.vue list 页面 ├─static 存放应用引用的本地静态资源(如图片、视频等)的目录,注意:静态资源都应存放于此目录 ├─uni_modules 存放 uni_module 详见 ├─platforms 存放各平台专用页面的目录,详见 ├─nativeplugins App 原生语言插件 详见 ├─nativeResources App 端原生资源目录 │ ├─android Android 原生资源目录 详见 | └─ios iOS 原生资源目录 详见 ├─hybrid App 端存放本地 html 文件的目录,详见 ├─wxcomponents 存放小程序组件的目录,详见 ├─unpackage 非工程代码,一般存放运行或发行的编译结果 ├─main.js Vue 初始化入口文件 ├─App.vue 应用配置,用来配置 App 全局样式以及监听 应用生命周期 ├─pages.json 配置页面路由、导航条、选项卡等页面类信息,详见 ├─manifest.json 配置应用名称、appid、logo、版本等打包信息,详见 ├─AndroidManifest.xml Android 原生应用清单文件 详见 ├─Info.plist iOS 原生应用配置文件 详见 └─uni.scss 内置的常用样式变量
重点是 pages 文件夹里,每一个.vue 文件就是一个页面,换言之现在是用 vue 语法写小程序页面。
# uni-app 和小程序开发上的不同
uni-app 中一个页面由一个.vue 文件构成,微信小程序中一个页面由 wxml,xwss 和 js 文件构成,.vue 文件中有三个一级节点,template,script,style,分别对应了 wxml,wxss,js。语法选用 vue 语法,控件使用小程序控件和 uni-app 自己的控件 ui,API 也是使用 uni-app 自己的 api,同时也兼容小程序的 api,其他方面并无本质上的区别。
# 在 uni-app 上运行微信小程序
进入项目,点击工具栏的运行 -> 运行到小程序模拟器 -> 微信开发者工具,即可在微信开发者工具里面体验 uni-app,也可如图所示运行:
这样系统会自动打开微信小程序并且运行 uni-app 代码。(注意,通过 uni-app 运行小程序需要开放微信开发者工具的端口访问)
# uni-app 云服务
# 创建服务空间
打开这个网址https://unicloud.dcloud.net.cn/, 创建服务空间(需要 DCloud 账号,并且要实名认证)。服务空间类型选择阿里云(也可以选择支付宝云,DCloud 提供阿里云和支付宝云的免费版),选择免费版点击创建,等待几分钟等待服务空间初始化即可。
# 创建项目
打开 HBuilderX,点击创建项目,选择创建 uni-app 项目,里面有个选项为启用 uniCloud,点击启用并选择阿里云。
创建好项目后需要关联服务空间,右键 uniCloud 文件夹,选择云服务空间或项目,选择新创建的服务空间即可。
# 云服务的简单使用(详细可看这个文档https://doc.dcloud.net.cn/uniCloud/)
云对象能够直接导入到前端进行使用,可以在云对象中编写函数,云对象在 cloudfunctions 目录下创建,目录结构如图:
图中的云对象名称为 co1,逻辑写在 index.obj.js 中,代码如下:
module.exports = {
_before: function () {
// 通用预处理器
},
say(text) {
console.log("console: " + text);
return {
status_code: 0,
data: "hello uniCloud",
};
},
};
2
3
4
5
6
7
8
9
10
11
12
通过 uniCloud.importObject("对象名")调用,云对象里的方法都为异步方法,代码如下:
async callco1(){
const co1 = uniCloud.importObject("co1")
let res = await co1.say("这是客户端传递到云服务器的参数")
console.log(res)
}
2
3
4
5
同样前端也可以直接调用云数据库中的数据,代码如下:
callDB(){
const db = uniCloud.database();
db.collection("test1").get().then(res => {
console.log(res)
this.data = res.result.data
}).catch(err => {
console.log(err)
})
}
2
3
4
5
6
7
8
9
# 命令行创建 uni-app 项目并用 VSCode 开发
npx degit dcloudio/uni-preset-vue#vite-ts 项目名称
通过上述命令能够创建一个 vue3+ts 版的 uni-app 项目,然后通过 vscode 打开项目,进入命令行终端,输入 pnpm i 下载依赖。依赖下载完成后,接下来就要在微信小程序中跑起来,我们使用 pnpm dev:mp-weixin 就能进行代码编译,编译完成后会多出来一个 dist 目录,里面就是微信小程序的代码,通过微信小程序开发者工具打开 dist 目录里面的 mp-weixin 文件,即可运行代码。同时如果你在 vscode 中修改了代码,开发者工具中也会同步进行实时的更新。
# 基于 Vue3+TS+uni-app 的小程序开发
# 创建 uni-app(vue3+ts 模版)项目
vue3+ts 版: npx degit dcloudio/uni-preset-vue#vite-ts
通过上述命令可以下载到 vue3+ts+uni-app 的模版文件,使用 vscode 打开项目,输入命令 pnpm install 下载依赖。依赖下载完成后,接下来就要在微信小程序中跑起来,我们使用 pnpm dev:mp-weixin 就能进行代码编译,编译完成后会多出来一个 dist 目录,里面就是微信小程序的代码,通过微信小程序开发者工具打开 dist 目录里面的 mp-weixin 文件,即可运行代码。同时如果你在 vscode 中修改了代码,开发者工具中也会同步进行实时的更新。
# vscode 工具的配置
# 安装 uni-app 插件
# 快速创建页面
下载上图插件,即可快速创建页面,创建方式如下, 在文件夹上右键多出了一个新建 uniapp 页面的选项,输入名称就会自动创建一个页面需要的文件, 同时 pages.json 中也会注册相应的信息。
# uni-helper
uni 相关的代码提示
# uniapp 小程序扩展
鼠标悬停能够直接查看相应控件的文档
# TS 类型校验
# 安装类型声明文件
pnpm i -D miniprogram-api-typings @uni-helper/uni-app-types
配置 tsconfig.json,在 types 中添加这两个包,并添加 vue 编译器的配置。
"compilerOptions": {
......
"types": [
"@dcloudio/types",
"miniprogram-api-typings", //添加的包
"@uni-helper/uni-app-types", //添加的包
]
},
"vueCompilerOptions": {
// experimentalRuntimeMode 已废弃,现调整为 nativeTags,请升级 Volar 插件至最新版本
"nativeTags": ["block", "component", "template", "slot"]
},
2
3
4
5
6
7
8
9
10
11
12
项目中有一些 json 文件会有注释,配置 vscode 使相关 json 文件支持注释
在 vscode 中打开设置,如下图所示设置
# 导入 uni-ui 组件库
# 安装 uni-ui
pnpm i @dcloudio/uni-ui
在 pages.json 中配置 easycom
// 组件自动引入规则
"easycom": {
// 是否开启自动扫描
"autoscan": true,
"custom": {
// uni-ui 规则如下配置
"^uni-(.*)": "@dcloudio/uni-ui/lib/uni-$1/uni-$1.vue"
}
},
2
3
4
5
6
7
8
9
配置 uni-ui 的类型校验,安装依赖 pnpm i -D @uni-helper/uni-ui-types
在 tsconfig.json 中配置
"types": [
"@dcloudio/types",
"miniprogram-api-typings",
"@uni-helper/uni-app-types",
"@uni-helper/uni-ui-types" //添加的包
]
2
3
4
5
6
# Pinia 持久化
创建 pinia 实例并导出给 main.ts 使用
import { createPinia } from "pinia";
import persist from "pinia-plugin-persistedstate";
// 创建 pinia 实例
const pinia = createPinia();
// 使用持久化存储插件
pinia.use(persist);
// 默认导出,给 main.ts 使用
export default pinia;
// 模块统一导出
export * from "./modules/member";
2
3
4
5
6
7
8
9
10
11
12
13
在 mian.ts 中加上 app.use(pinia)
定义 store 的代码如下:
import { defineStore } from 'pinia'
import { ref } from 'vue'
// 定义 Store
export const useMemberStore = defineStore(
'member',
() => {
// 会员信息
const profile = ref<any>()
// 保存会员信息,登录时使用
const setProfile = (val: any) => {
profile.value = val
}
// 清理会员信息,退出时使用
const clearProfile = () => {
profile.value = undefined
}
// 记得 return
return {
profile,
setProfile,
clearProfile,
}
},
// TODO: 持久化
{
persist: {
storage: {
getItem(key) {
return uni.getStorageSync(key)
},
setItem(key, value) {
uni.setStorageSync(key, value)
},
}
}
},
)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# 请求工具封装
# 请求拦截器
/**
* 1. 非 http 开头需拼接地址
* 2. 请求超时
* 3. 添加小程序端请求头标识
* 4. 添加 token 请求头标识
*/
import { useMemberStore } from "@/stores";
const baseURL = "https://pcapi-xiaotuxian-front-devtest.itheima.net";
const httpInterceptor = {
invoke(options: UniApp.RequestOptions) {
// 1. 非 http 开头需拼接地址
console.log(options.url);
if (!options.url.startsWith("http")) {
var new_url: string = options.url.startsWith("/") ? options.url : "/" + options.url;
options.url = baseURL + new_url;
}
// 2. 请求超时
options.timeout = 10000;
// 3. 添加小程序端请求头标识
options.header = {
...options.header,
"source-client": "miniapp",
};
// 4. 添加 token 请求头标识
const memberStore = useMemberStore();
const token = memberStore.profile?.token;
if (token) {
options.header.Authorization = token;
}
console.log(options);
},
};
uni.addInterceptor("request", httpInterceptor);
uni.addInterceptor("uploadFile", httpInterceptor);
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# 请求函数封装
/**
* 请求函数
* @param UniApp.RequestOptions
* @returns Promise
* 1. 返回 Promise 对象
* 2. 获取数据成功
* 2.1 提取核心数据 res.data
* 2.2 添加类型,支持泛型
* 3. 获取数据失败
* 3.1 401 错误 -> 清理用户信息,跳转到登录页
* 3.2 其他错误 -> 根据后端错误信息轻提示
* 3.3 网络错误 -> 提示用户换网络
*/
type Data<T> = {
code: string
msg: string
result: T
}
// 2.2 添加类型,支持泛型
export const http = <T>(options: UniApp.RequestOptions) => {
// 1. 返回 Promise 对象
return new Promise<Data<T>>((resolve, reject) => {
uni.request({
...options,
// 响应成功
success(res) {
// 状态码 2xx, axios 就是这样设计的
if (res.statusCode >= 200 && res.statusCode < 300) {
// 2.1 提取核心数据 res.data
resolve(res.data as Data<T>)
} else if (res.statusCode === 401) {
// 401 错误 -> 清理用户信息,跳转到登录页
const memberStore = useMemberStore()
memberStore.clearProfile()
uni.navigateTo({ url: '/pages/login/login' })
reject(res)
} else {
// 其他错误 -> 根据后端错误信息轻提示
uni.showToast({
icon: 'none',
title: (res.data as Data<T>).msg || '请求错误',
})
reject(res)
}
},
// 响应失败
fail(err) {
uni.showToast({
icon: 'none',
title: '网络错误,换个网络试试',
})
reject(err)
},
})
})
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# 隐藏默认导航栏
在 pages.json 文件的页面样式中添加"navigationStyle": "custom",即可隐藏导航栏。
# typescript 和相关用法
?.: 可选链操作符,允许读取位于连接对象链深处的属性的值,而不必明确验证链中的每个引用是否有效。
const obj = {
name: "ceshi",
detail: {
cat: "huahua",
},
};
const name = obj.dog?.name;
console.log(name); // undefined
const detail = obj.detail?.cat;
console.log(detail); //huahua
2
3
4
5
6
7
8
9
10
11
key!:非空断言, 它用来告诉编译器该变量的值不会为 null。
例如,假设有一个函数 foo 返回一个字符串类型,它不会返回 null:
tsfunction foo(): string {
return 'hello';
}
const myString: string = foo()!;
2
3
4
5
在这个例子中,! 表示断言该值不会是 null,因此编译器不会检查 foo() 是否为 null,而会将其视为非空字符串。
# 全局组件导入
在 components 文件夹下写自定义组件可以在 pages.json 中的 easycom 中进行配置,
"easycom": {
// 是否开启自动扫描
"autoscan": true,
// 以正则方式自定义组件匹配规则
"custom": {
// uni-ui 规则如下配置
"^uni-(._)": "@dcloudio/uni-ui/lib/uni-$1/uni-$1.vue",
// 以 Xtx 开头的组件,在 components 文件夹中查找引入(需要重启服务器)
"^Xtx(._)": "@/components/Xtx$1.vue"
}
},
2
3
4
5
6
7
8
9
10
11
并在 types 文件夹下创建一个.d.ts 文件做组件类型定义。
import XtxSwiper from "@/components/XtxSwiper.vue";
import XtxGuess from "@/components/XtxGuess.vue";
declare module "vue" {
export interface GlobalComponents {
XtxSwiper: typeof XtxSwiper;
XtxGuess: typeof XtxGuess;
}
}
// 组件实例类型
export type XtxGuessInstance = InstanceType<typeof XtxGuess>;
export type XtxSwiperInstance = InstanceType<typeof XtxSwiper>;
2
3
4
5
6
7
8
9
10
11
12
13
# Uni-app+ts 中事件的类型
通过 UniHelper.xxxx 能得到 uni-app 中大多数事件的类型
// 当 swiper 下标发生变化时触发
const onChange: UniHelper.SwiperOnChange = (ev) => {
activeIndex.value = ev.detail.current;
};
2
3
4