文章目录
前言-课程背景
大前端时代背景下,前端开发人员掌握单一的 Web 端开发能力已经远远不够了,微信小程序、安卓 APP、IOS APP,甚至是 Windows 桌面端,还有最近出的鸿蒙系统开发,都成了我们成长需要掌握的技能。所以,市面上各种「跨平台」开发解决方案层出不穷,比较有代表性的就是: UniAPP 、 Flutter、 React Native、Taro、Weex 等等。
uni-app 是基于「 Vue + 微信小程序 」语言体系,开发人员学习成本低上手快,同时随着如今 UniAPP 生态也逐步趋于成熟。所以,基于 UniAPP 开发多端项目,已经是很多中小型企业常用的技术解决方案。
一、uni-app介绍
1 概念
uni-app 是一个使用 Vue.js 开发所有前端应用的框架,开发者编写一套代码,可发布到 iOS、Android、H5,以及各种小程序(微信/支付宝/百度/头条/ QQ /钉钉)等多个平台,方便开发者快速交付,不需要转换开发思维,不需要更改开发习惯。
2 优势
- 开发者/案例数量更多
几十万应用、uni 统计月活12亿、70+ 微信 / QQ群 - 平台能力不受限
在跨端的同时,通过条件编译 + 平台特有 API 调用,可以优雅的为某平台写个性化代码,调用专有能力而不影响其他平台 - 性能体验优秀
加载新页面速度更快、自动 diff 更新数据,App 端支持原生渲染支撑更流畅的用户体验,小程序端的性能优于市场其他框架 - 周边生态丰富
插件市场数千款插件,支持 NPM、支持小程序组件和SDK,微信生态的各种 sdk 可直接用于跨平台 APP - 学习成本低
基于通用的前端技术栈,采用 vue 语法+微信小程序 api,无额外学习成本
3 功能框架
4 搭建开发环境
4.1 安装开发工具
4.2 创建 uni-app 项目
-
在HbuilderX中新建项目,选择uni-app,设置项目名称和目录,选择模板,Vue版本选择Vue3,点击新建即可。
uni-app自带的模板有 Hello uni-app ,是官方的组件和API示例。
还有一个重要模板是 uni ui项目模板,日常开发推荐使用该模板,已内置大量常用组件。 -
安装编译器,在菜单栏选择工具,插件安装,安装新插件,下载uni-app(vue3)编译器。
4.3 运行 uni-app
主要包括:浏览器运行、真机运行、小程序运行等
- 运行到浏览器中,在HbuilderX菜单栏点击运行,运行到浏览器,选择相应浏览器即可。
- 运行到微信开发者工具,在HbuilderX菜单栏选择运行,运行到小程序模拟器,微信开发者工具。
在HbuilderX中修改代码,微信开发者工具中的运行结果也会相应更新。
注:(1) 第一次运行需要配置小程序ide的相关路径。
在菜单栏,点击工具,设置,选择运行设置,找到小程序运行设置,添加微信开发者工具路径。
(2) 出现如下错误需要在微信开发者工具中开启服务端口。
在微信开发者工具中,点击设置,安全,开启服务端口。
4.4 发布 uni-app
主要包括:云端原生 APP 、离线原生 APP、H5、各种小程序
5 uni-app初始化相关配置
-
工程目录结构
┌─components uni-app组件目录(自建) │ └─comp-a.vue 可复用的a组件 ├─hybrid 存放本地网页的目录(自建) ├─platforms 存放各平台专用页面的目录(自建) ├─pages 业务页面文件存放的目录 │ ├─index │ │ └─index.vue index页面 │ └─list │ └─list.vue list页面 ├─static 存放应用引用静态资源(如图片、视频等)的目录,注:静态资源只能存放于此 ├─wxcomponents 存放小程序组件的目录(自建) ├─common 公共资源(自建) ├─api 请求封装(自建) ├─store 状态管理(自建) ├─main.js Vue初始化入口文件 ├─App.vue 根组件,应用配置,用来配置App全局样式以及监听 应用生命周期 ├─index.html H5 端模板 ├─manifest.json 配置应用名称、appid、logo、版本等打包信息 ├─pages.json 配置页面路由、导航条、选项卡等页面类信息 └─uni.scss 全局样式
提示:static下目录的 js 文件不会被 webpack 编译,里面如果有 es6 的代码,不经过转换直接运行,在手机设备上会报错,所以 js、less、scss等资源不要放在 static 目录下
-
应用配置 manifest.json
manifest.json
文件是应用的配置文件,用于指定应用的名称、图标、权限等,也可以在这里为 Vue 为H5 设置跨域拦截处理器 -
编译配置 vue.config.js
vue.config.js 是一个可选的配置文件,如果项目的根目录中存在这个文件,那么它会被自动加载,一般用于配置 webpack 等编译选项。 -
全局配置 page.json
pages.json 文件用来对 uni-app 进行全局配置,决定页面文件的路径、窗口样式、原生的导航栏、底部的原生tabbar 等。类似微信小程序中app.json
的页面管理部分。属性 类型 必填 描述 globalStyle Object 否 设置默认页面的窗口表现 pages Object Array 是 设置页面路径及窗口表现 easycom Object 否 组件自动引入规则 tabBar Object 否 设置底部 tab 的表现 condition Object 否 启动模式配置 subPackages Object Array 否 分包加载配置 preloadRule Object 否 分包预下载规则 -
全局样式 uni.scss
uni.scss 文件的用途是为了方便整体控制应用的风格。比如按钮颜色、边框风格,uni.scss
文件里预置了一批scss变量预置。
uni-app
官方扩展插件(uni ui)及 插件市场 上很多三方插件均使用了这些样式变量。
uni.scss
是一个特殊文件,在代码中无需 import 这个文件即可在scss代码中使用这里的样式变量。uni-app的编译器在webpack配置中特殊处理了这个uni.scss
,使得每个 scss 文件都被注入这个uni.scss,达到全局可用的效果。 -
主组件 App.vue
App.vue
是uni-app的主组件,所有页面都是在App.vue
下进行切换的,是页面入口文件。但App.vue
本身不是页面,不能编写视图元素。
这个文件的作用包括:调用应用生命周期函数、配置全局样式、配置全局的存储globalData,应用生命周期仅可在App.vue
中监听,在页面监听无效。 -
入口文件 main.js
main.js 是uni-app的入口文件,主要作用是初始化vue
实例、定义全局组件、使用需要的插件,如vuex。
6 uni-app 开发规范及资源路径
6.1 开发规范约定
- 页面文件向导 Vue单文件组件(SFC)规范
- 组件 标签靠近小程序规范
- 互连能力(JS API)靠近微信小程序规范,但需要将替换替换 wx 为 uni ,详见 uni-app接口规范
- 数据绑定及事件处理同 Vue.js 规范,同时补充了 App 和页面的生命周期
- 为兼容多端运行,建议使用 flex 布局进行开发
6.2. 资源路径说明
-
template 内静态资源,如 image,video 等标签的 src 属性时,可以使用相对路径或绝对路径,形式如下:
<!-- 绝对路径,/static指根目录下的static目录,在cli项目中/static指src目录下的static目录 --> <image class="logo" src="/static/logo.png"></image> <image class="logo" src="@/static/logo.png"></image> <!-- 相对路径 --> <image class="logo" src="../../static/logo.png"></image>
-
js 文件或 script 标签内,可以使用相对路径和绝对路径,形式如下:
// 绝对路径,@指向项目根目录,在cli项目中@指向src目录 import add from '@/common/add.js' // 相对路径 import add from '../../common/add.js'
-
css 文件或 style 标签内,可以使用相对路径和绝对路径,形式如下:
/* 绝对路径 */ @import url('/common/uni.css'); @import url('@/common/uni.css'); background-image: url(@/static/logo.png); /* 相对路径 */ @import url('../../common/uni.css'); background-image: url(../../static/logo.png);
开发中建议使用 @/ 绝对路径 方式
二、uni-app 学习
1 uni-app 生命周期
学习一个工具的目的核心是为了解决核心业务逻辑问题,业务逻辑很多时候简单的解释为一句话:“在合适的时机干合适的事情”。简单的说,页面运行过程中,各个阶段的回调函数就是页面中的时机,称为“生命周期钩子函数”。
1.1 应用生命周期
函数名 | 说明 |
---|---|
onLaunch | 当 uni-app 初始化完成时触发(全局只触发一次) |
onShow | 当 uni-app 启动,或从后台进入前台显示 |
onHide | 当 uni-app 从前台进入后台 |
onError | 当 uni-app 报错时触发 |
onUniNViewMessage | 对 nvue 页面发送的数据进行监听,可参考 nvue 向 vue 通讯 |
onUnhandledRejection | 对未处理的 Promise 拒绝事件监听函数 |
onPageNotFound | 页面不存在监听函数 |
onThemeChange | 监听系统主题变化 |
// App.vue
onLaunch: function() {
console.log('App Launch')
},
// 页面不存在时跳转 404 页面
onPageNotFound() {
uni.navigateTo({
url:'/pages/404/404'
})
}
1.2 页面生命周期
函数名 | 说明 |
---|---|
onLoad | 监听页面加载,其参数为上个页面传递的数据,参数类型为Object(用于页面传参),参考示例 |
onShow | 监听页面显示。页面每次出现在屏幕上都触发,包括从下级页面点返回露出当前页面 |
onReady | 监听页面初次渲染完成。注意如果渲染速度快,会在页面进入动画完成前触发 |
onHide | 监听页面隐藏 |
onUnload | 监听页面卸载 |
onResize | 监听窗口尺寸变化 |
onPullDownRefresh | 监听用户下拉动作,一般用于下拉刷新,参考示例 |
onReachBottom | 页面滚动到底部的事件(不是scroll-view滚到底),常用于下拉下一页数据。具体见下方注意事项 |
onTabItemTap | 点击 tab 时触发,参数为Object,具体见下方注意事项 |
onShareAppMessage | 用户点击右上角分享 |
onPageScroll | 监听页面滚动,参数为Object |
onNavigationBarButtonTap | 监听原生标题栏按钮点击事件,参数为Object |
onBackPress | 监听页面返回 |
onNavigationBarSearchInputChanged | 监听原生标题栏搜索输入框输入内容变化事件 |
onNavigationBarSearchInputConfirmed | 监听原生标题栏搜索输入框搜索事件,用户点击软键盘上的“搜索”按钮时触发。 |
onNavigationBarSearchInputClicked | 监听原生标题栏搜索输入框点击事件 |
onShareTimeline | 监听用户点击右上角转发到朋友圈 |
onAddToFavorites | 监听用户点击右上角收藏 |
// pages/404/404.vue
// 404页面自动跳转回主页面
onLoad() {
let timer = setTimeout(()=>{
clearTimeout(timer)
uni.switchTab({
url:'/pages/index/index'
})
},2000)
}
2 uni-app 页面路由
2.1 路由配置
uni-app 页面路由全部交给框架统一管理,开发者需要在 pages.json 里配置每个路由页面的路径及页面样式(类似小程序在 app.json 中配置页面路由)。
"pages": [
{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "首页",
"navigationBarBackgroundColor": "#FFFFFF",
"navigationBarTextStyle": "black",
"backgroundColor": "#FFFFFF",
"enablePullDownRefresh": true
}
},
{
"path": "pages/user/user",
"style": {
"navigationBarTitleText": "用户",
"navigationBarBackgroundColor": "#FFFFFF",
"navigationBarTextStyle": "black",
"backgroundColor": "#FFFFFF",
"enablePullDownRefresh": true
}
}
]
page.json 自定义标题栏
不同终端,自定义标题栏
"pages": [
{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "首页",
"enablePullDownRefresh": true,
"h5":{
"titleNView":"H5首页",
"backgroundColor":"#36f",
"titleColor":"#fff",
"titleAlign":"left",
},
"app-plus":{ //app端不显示标题栏
"titleNView":false,
"navigationBarTextStyle": "white",
}
}
}
]
避免 app 端顶部与手机状态栏重叠,需要设置padding-top
uni-app 提供了内置 CSS 变量 --status-bar-height--
为系统状态栏高度
/* #ifdef APP */
.title{
padding-top: var(--status-bar-height--)
}
/* #endif */
2.2 底部导航栏
tabBar": {
"color": "#777",
"selectedColor": "#1afa29",
"list": [
{
"pagePath": "pages/index/index",
"text": "微信",
"iconPath": "static/tabbar-icons/wx.png",
"selectedIconPath": "static/tabbar-icons/wx_s.png"
},{
"pagePath": "pages/list/list",
"text": "通讯录",
"iconPath": "static/tabbar-icons/list.png",
"selectedIconPath": "static/tabbar-icons/list_s.png"
},{
"pagePath": "pages/finder/finder",
"text": "发现",
"iconPath": "static/tabbar-icons/find.png",
"selectedIconPath": "static/tabbar-icons/find_s.png"
},{
"pagePath": "pages/me/me",
"text": "我",
"iconPath": "static/tabbar-icons/me.png",
"selectedIconPath": "static/tabbar-icons/me_s.png"
}
]
},
2.2 路由跳转
uni-app
有两种页面路由跳转方式
- 使用 navigator 组件跳转(标签式导航)
<!-- 切换到导航栏 open-type="switchTab" --> <navigator url="pages/index/index" open-type="navigate">主页</navigator> <navigator open-type="navigateBack">返回</navigator>
- 调用 API 跳转(编程式导航)
//跳转到index.vue页面 uni.navigateTo({ url: 'pages/index/index' });
框架以栈的形式管理当前所有页面, 当发生路由切换的时候,页面栈的表现如下:
路由方式 | 页面栈表现 | 触发时机 |
---|---|---|
初始化 | 新页面入栈 | uni-app 打开的第一个页面 |
打开新页面 | 新页面入栈 | 调用 API uni.navigateTo 、使用组件 <navigator open-type="navigate" /> |
页面重定向 | 当前页面出栈,新页面入栈 | 调用 API uni.redirectTo 、 使用组件 redirect |
页面返回 | 页面不断出栈,直到目标返回页 | 调用 API uni.navigateBack 、 使用组件 navigateBack 、用户按左上角返回按钮、安卓用户点击物理back按键 |
Tab 切换 | 页面全部出栈,只留下新的 Tab 页面 | 调用 API uni.switchTab 、 使用组件 switchTab 、用户切换 Tab |
重加载 | 页面全部出栈,只留下新的页面 | 调用 API uni.reLaunch 、 使用组件 relauch |
2.3 获取当前页面栈
getCurrentPages()
函数用于获取当前页面栈的实例,以数组形式按栈的顺序给出,第一个元素为首页,最后一个元素为当前页面。
注:getCurrentPages() 仅用于展示页面栈的情况,请勿修改页面栈,以免造成页面状态错误。
2.4 路由传参与接收
页面生命周期的 onLoad()监听页面加载,其参数为上个页面传递的数据
// 页面跳转并传递参数
uni.navigateTo({
//url 为将要跳转的页面路径,路径后可以带参数。参数与路径之间使用`?`分隔,参数键与参数值用`=`相连,不同参数用`&`分隔
url: 'pages/user/user?name=xdk&message=Hello'
});
// 接收参数
onLoad: function (option) {
// option为object类型,会序列化上个页面传递的参数
console.log(option.name);
console.log(option.message);
}
注:url 有长度限制,太长的字符串会传递失败,并且不规范的字符格式也可能导致传递失败,所以对于复杂参数建议使用
encodeURI
、decodeURI
进行处理后传递
2.5 小程序路由分包配置
因小程序有体积和资源加载限制,各个小程序平台提供了分包方式,优化小程序的下载和启动速度。
主包,即放置默认启动页面及 TabBar 页面,而分包则是根据subPackages
属性的配置进行划分。
// pages.json
"pages": [
// ...省略
],
"subPackages": [
{
"root": "pagesA", //子包的根目录
"pages": [{ // 同根结构下 pages
"path": "other/other", // 相对路径
"style": {
"navigationBarTitleText": "其他",
"navigationBarBackgroundColor": "#FFFFFF",
"navigationBarTextStyle": "black",
"backgroundColor": "#FFFFFF"
}
}]
},{
"root": "pagesB",
"pages": [{
"path": "detail/detail",
"style": { ...}
}],
}
],
// 预下载分包设置
"preloadRule": {
"pagesA/other/other": {
"network": "all", //在指定网络下预下载,all(不限网络)、wifi(仅wifi下预下载)
"packages": ["__APP__"] //在进入某个页面后继续预下载,__APP__表示主包
},
"pagesB/other/other": {
"network": "all",
"packages": ["pagesA"]
}
}
在小程序启动时,默认会下载主包并启动主包内页面,当用户进入分包内某个页面时,会把对应分包自动下载下来,下载完成后再进行展示,此时终端界面会有等待提示。
3 运行环境判断与跨端兼容
3.1 开发环境和生产环境
uni-app
可通过 process.env.NODE_ENV
判断当前环境是开发环境还是生产环境,一般用于连接测试服务器或生产服务器的动态切换。
在HBuilderX 中,点击「运行」编译出来的代码是开发环境,点击「发行」编译出来的代码是生产环境
if(process.env.NODE_ENV === 'development'){
console.log('开发环境')
}else{
console.log('生产环境')
}
3.2 判断平台
平台判断有2种场景,一种是在编译期判断,一种是在运行期判断。
- 编译期判断,即条件编译,不同平台在编译出包后已经是不同的代码,
// #ifdef H5 alert("只有h5平台才有alert方法") // #endif // 如上代码只会编译到H5的发行包里,其他平台的包不会包含如上代码。
- 运行期判断是指代码已经打入包中,仍然需要在运行期判断平台,此时可使用
uni.getSystemInfoSync().platform
判断客户端环境是 Android、iOS 还是小程序开发工具switch(uni.getSystemInfoSync().platform){ case 'android': console.log('运行Android上') break; case 'ios': console.log('运行iOS上') break; default: console.log('运行在开发者工具上') break; }
3.3 跨端兼容
uni-app 已将常用的组件、JS API 封装到框架中,开发者按照 uni-app 规范开发即可保证多平台兼容,大部分业务均可直接满足,但每个平台有自己的一些特性,因此会存在一些无法跨平台的情况。
- 大量写 if else,会造成代码执行性能低下和管理混乱。
- 编译到不同的工程后二次修改,会让后续升级变的很麻烦。
在 C 语言中,通过 #ifdef、#ifndef 的方式,为 windows、mac 等不同 os 编译不同的代码。 uni-app
参考这个思路,为 uni-app
提供了条件编译手段,在一个工程里优雅的完成了平台个性化实现。
条件编译是用特殊的注释作为标记,在编译时根据这些特殊的注释,将注释里面的代码编译到不同平台。
写法: 以 #ifdef
或 #ifndef
加 PLATFORM 开头,以#endif
结尾。
#ifdef
:if defined 仅在某平台存在#ifndef
:if not defined 除了某平台均存在- PLATFORM :平台名称
PLATFORM 可取值如下:
值 | 平台 |
---|---|
APP-PLUS | App |
APP-PLUS-NVUE | App nvue |
H5 | H5 |
MP-WEIXIN | 微信小程序 |
MP-ALIPAY | 支付宝小程序 |
MP-BAIDU | 百度小程序 |
MP-TOUTIAO | 字节跳动小程序 |
MP-QQ | QQ小程序 |
MP-360 | 360小程序 |
MP | 微信小程序/支付宝小程序/百度小程序/字节跳动小程序/QQ小程序/360小程序 |
QUICKAPP-WEBVIEW | 快应用通用(包含联盟、华为) |
QUICKAPP-WEBVIEW-UNION | 快应用联盟 |
QUICKAPP-WEBVIEW-HUAWEI | 快应用华为 |
条件注释可在html、js、css、pages.json中使用
vue 语法
template
- 文本标签
支持{{}}
、v-html
小程序不支持v-text
,H5和app支持 - 条件渲染
v-if v-else-if v-else
<!-- #ifndef MP-WEIXIN --> <view v-text = 'msg'></view> <!-- #endif -->
- 遍历
v-for
<!-- 可遍历数字、字符串、对象 --> <view v-for='(value,key) in obj' :key='key'>{{key}}:{{value}}<view>
- 单选框和多选框
<radio-group @change="city=$event.detail.value"> <label > <radio value="上海" /><text>上海</text> </label> <label > <radio value="北京" /><text>北京</text> </label> </radio-group> <checkbox-group @change="fav=$event.detail.value"> <label> <checkbox value="羽毛球" checked="true" /><text>羽毛球</text> </label> <label> <checkbox value="跑步" /><text>跑步</text> </label> </checkbox-group>
- 事件绑定
@click
@tap
<button @tap='test'>事件响应函数</button> <button @click='test()'>事件响应函数带()</button> <button @click='test'>事件响应函数不带()</button> <button @click='test($event)'>事件响应函数带($event)</button>
function test(e){ console.log('事件参数', e) // 事件响应函数带() e = undefined // 事件响应函数不带() e = {type: "click" ...} // 事件响应函数带($event) e = {type: "click" ...} }
- 事件修饰符
.once
响应一次
.prevent
阻止默认事件
.stop
停止时间冒泡
表单修饰符
.number
转换为数字
.lazy
change事件触发,默认input事件
.trim
过滤首尾空格
按键修饰符
.up .right .bottom .left .space .delete .enter .esc
选项式API
- 计算属性
export default { data(){ return {num: 5} } computed:{ doubleNum:function(){ // 计算的数据是只读 return this.num*2 }, priceNum:{ get(){ return this.num * 1.5 }, set(v){ this.num = v/1.5 } } } }
- 监听
watch:{ num:{ handler(val, oval){ // 值类型 val新值, oval 旧值 // 引用类型 两个值一样 uni.setStorageSync('num', val) }, // 引用类型加 deep deep: true } }
- 组件
uni 采用easycom
技术,自定义组件不需要导入和注册
自定义组件存放位置:components/组件/组件.vue
组合式API
- setup
<script> import { ref } from 'vue' export default { setup(props, context){ const num = ref(5) const setNum = (v) =>{ num.value = v } return {num, setNum } } } </script>
- setup 语法糖
<script setup> // ref 定义响应数据类型,reactive 引用类型 import { ref, reactive } from 'vue' const num = ref(5) const setNum = (v) =>{ num.value = v } const list = reacitve([1, 2, 3]) </script>
- computed
const num = ref(5) // computed 从现有数据计算新数据 const cnum = computed( () => num.value*2 ) computed({ get(){ //获取cum1执行get return um.value*2 }, set(v){ //设置cum1执行set num.value = v/5 } })
- watch
const list= reactive([1,2,3]) // wathc 监听数据变化 watch( list, (val, oldVal) => { uni.setStorageSync('list', list) }, {deep: true})
- watchEffect 监听副作用
const list= reactive([1,2,3]) const num= ref(5) // watchEffect 方法中引用的所有数据发生变化都会触发 watchEffect((val, oldVal) => { console.log(num.value) uni.setStorageSync('list', list) }, {deep: true})
- readonly 只读
const num= readonly(5)
- defineProps 父组件向子组件传值
//父组件 <Child props="child"></Child> // 子组件 defineProps({ "props":{ type:[Number,String], default:"", required:false } })
- defineEmits 创建事件,接收子组件传递过来的数据
// 父组件 <Child @add="add"></Child > const add= (val) => { num.value = num.value + val } // 子组件 // 调用defineEmits并定义要发射给父组件的方法 const emits = defineEmits(['add']) // 在子组件要触发的方法中,调用emits并传入发射给父组件的方法以及参数 emits('add', 1)
- defineExpose 子组件抛出函数,变量给父组件
// 父组件 <Child ref="childeRef"/> <script setup> const childeRef = ref() onMounted(() => { childeRef.value.loadList([{ id: 1, name: '22' }]) // 调用子组件函数 }) </script> // 子组件 const a = ref(2) const loadList = (item)=>{ // 函数体 } defineExpose({ a, loadList })
Pinia 状态管理
pinia 大菠萝,下一代vuex,省略mutations,支持setup与options两套语法
vue3官方认可的全局状态管理器
当pinia的数据更新时,引用pinia组件的视图会自动更新
-
安装
如果项目中没有pinia,运行npm install pinia -S
安装 -
配置
// main.js // 导入Pinia import * as Pinia from 'pinia' // #ifdef VUE3 export function createApp() { const app = createSSRApp(App) // 创建pinia实例 const pinia =Pinia.createPinia(); // 使用pinia app.use(pinia) return { app, Pinia } } // #endif
-
使用——选项式
新建stores目录,添加 useCounterStore.js 文件// useCounterStore.js import { defineStore } from 'pinia' export const useCounterStore = defineStore('counter', { // state为全局的共享状态 跟vuex不同 写法为函数返回对象 state: () => ({ count: 4 }), // getters为计算属性 接收第一个参数为state getters: { doubleCount: state => state.count * 2 }, // 动作支持异步 actions: { setCount( val ){ this.count = val; } } })
// index.vue // 1. mapState 映射状态,mapState 映射动作 // 2. mapStores 映射整个仓库 import { mapActions, mapState, mapStores } from 'pinia' import { useCounterStore } from '@/stores/useCounterStore.js' export default { data() { return {} }, computed:{ ...mapState(useCounterStore,['count' ,'doubleCount']) // 导入整个仓库,使用counterStore.count ...mapStores (useCounterStore) }, methods: { ...mapActions(useCounterStore,["setCount"]) } }
-
使用——组合式
// useColorStore.js import { defineStore } from 'pinia' // 导入响应式和方法 import{ref, computed} from 'vue' const useColorStore = defineStore('color',()=>{ // 定义一个状态颜色 const color = ref('red'); // 定义设置状态的方法 const setColor = v =>{ color.value=v } return {color , setColor} }) export default useColorStore
// index.vue import useColorStore from "@/stores/useColorStore.js" // 1. 使用 colorStore.color, colorStore.setColor('#fff') const colorStore = useColorStore(); // 2. 解构方式,但状态 color 不是响应式 const {color, setColor} = useColorStore();
uni-ui
需要在 page.json 中配置 easycom 规则,让组件支持 easycom 自动导入,如果还出现组件没有正常显示情况,在vue页面中手动导入
发布
微信小程序:发行-小程序 微信-上传
H5:mainfest.json-web配置-路由(hash),运行的基本路径(./)-发行-网站 PC Web或手机H5-
APP:mainfest.json-基本配置-图标配置-模块配置-发行-原生APP 云打包,一天5次机会
APP上线:小米开放平台-管理中心-分发服务-应用游戏-创建应用
3 uni-app 常用组件简介
uni-app 为开发者提供了一系列基础组件,类似 HTML 里的基础标签元素,但 uni-app 的组件与 HTML 不同,而是与小程序相同,更适合手机端使用。
虽然不推荐使用 HTML 标签,但实际上如果开发者写了div
等标签,在编译到非H5平台时也会被编译器转换为 view
标签,类似的还有 span
转 text
、a
转navigator
等,包括 css 里的元素选择器也会转,但为了管理方便、策略统一,写代码时仍然建议使用view等组件。
开发者可以通过组合这些基础组件进行快速开发,基于内置的基础组件,可以开发各种扩展组件,组件规范与vue组件相同。
4 uni-app 常用 API 简介
uni-app
的 js 代码,h5 端运行于浏览器中,非 h5 端 Android 平台运行在 v8 引擎中,iOS 平台运行在 iOS 自带的 jscore 引擎中。所以,uni-app
的 js API 由标准 ECMAScript 的 js API 和 uni 扩展 API 这两部分组成。
ECMAScript 由 Ecma 国际管理,是基础 js 语法。浏览器基于标准 js 扩充了window、document 等 js API;Node.js 基于标准 js 扩充了 fs 等模块;小程序也基于标准 js 扩展了各种 wx.xx、my.xx、swan.xx 的 API。
标准 ecmascript 的 API 非常多,比如:console、settimeout等等。
非 H5 端,虽然不支持 window、document、navigator 等浏览器的 js API,但也支持标准 ECMAScript。所以 uni-app 的非 H5 端,一样支持标准 js,支持 if、for 等语法,支持字符串、数组、时间等变量及各种处理方法,仅仅是不支持浏览器专用对象。
5 uni-app 自定义组件与通信
5.1 自定义组件概念
组件是 vue
技术中非常重要的部分,可以大幅提升 vue使用者的开发效率,在项目的component
目录下存放组件,uni-app
只支持 vue
单文件组件(.vue 组件)
组件可以使用「全局注册」和「页面引入」两种方式进行使用,使用分为三步:
导入 import xxx from 'xxx'
注册 Vue.use('xx',xx)
components:{ xxx }
使用 <xx />
5.2 父子组件通信
- 父组件通过自定义属性向子组件传递数据
- 子组件通过
props
接收父组件传递的数据 - 父组件通过自定义事件标签向子组件传递事件
- 子组件通过触发父组件定义事件方式修改父组件数据
5.3 slot 数据分发与作用域插槽
- 父组件通过调用子组件内部嵌套 html 内容作为
slot
分发给子组件 - 子组件通过在
slot
标签上添加属性,向父组件通信数据,作用域插槽
5.4 全局事件定义及通信
- 在整个应用的任何地方均可以使用
uni.$on
创建一个全局事件 - 在整个应用的任何地方也均可以使用
uni.$emit
来触发全局事件,实现多组件见的数据通信
6 uni-app Vuex 状态管理
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
- 应用场景
Vue多个组件之间需要共享数据或状态。 - 关键规则
State:存储状态数据
Getter:从状态数据派生数据,相当于 State 的计算属性
Mutation:存储用于同步更改状态数据的方法,默认传入的参数为 state
Action:存储用于异步更改状态数据,但不是直接更改,而是通过触发 Mutation 方法实现,默认参数为context
Module:Vuex 模块化 - 交互关系
- 使用方式
import {
mapState,
mapActions
} from 'vuex'
export default {
computed: {
...mapState(['loginState', 'userInfo'])
},
methods: {
...mapActions(['userLoginAction', 'userLogoutAction']),
}
}
注意:配合使用 Storage 来实现刷新页面后状态持续保持的业务需求
持续更新中
HbulderX 快捷输入 u+要输入内容
学习视频 千锋教育前端uniapp入门到实战项目教程(微信小程序+H5+安卓APP+IOS APP)