一、概念
1. 原生 VS 跨平台
原生开发
优点
性能稳定,使用流畅,用户体验好、功能齐全,安全性有保证,兼容性好 ,可使用手机所有硬件功能等
缺点
开发周期长、维护成本高、迭代慢、部署慢、新版本必须重新下载应用
不支持跨平台,必须同时开发多端代码
跨平台开发
优点
可以跨平台,一套代码搞定iOS、Android、微信小程序、H5应用等
开发成本较低,开发周期比原生短
适用于跟系统交互少、页面不太复杂的场景
缺点
对开发者要求高,除了本身JS的了解,还必须熟悉一点原生开发
不适合做高性能、复杂用户体验,以及定制高的应用程序。比如:抖音、微信、QQ等
同时开发多端兼容和适配比较麻烦、调试起来不方便
2. 跨平台框架对比
3. 认识uni-app
4. uni-app VS 微信小程序
相同点
都是接近原生的体验、打开即用、不需要安装
都可开发微信小程序、都有非常完善的官方文档
不同点
跨平台
uni-app : 支持跨平台,编写一套代码,可以发布到多个平台
微信小程序 : 不支持
工程化
uni-app : 纯Vue体验、高效、统一、工程化强
微信小程序 : 工程化弱、使用小程序开发语言
复杂程度
uni-app : 适合不太复杂的应用,因为需要兼容多端,多端一起兼容和适配增加了开发者心智负担
微信小程序 : 适合较复杂、定制性较高、兼容和稳定性更好的应用
如何选择
需要跨平台、不太复杂的应用选 uni-app,复杂的应用使用uni-app反而增加了难度。
不需要跨平台、较复杂、对兼容和稳定性要求高的选原生微信小程序
5. uni-app架构图
二、uni-app初体验
1. 开发工具
Hbuilder X : 是通用的前端开发工具,但为 uni-app 做了特别强化
网址 : hbuilderx
ps : 用Vue3的Composition API 建议用 HBuilder X最新Alpha版,旧版有兼容问题
2. 创建项目
可视化界面创建 ( 推荐 )
点工具栏里的文件 -> 新建 -> 项目 ( 快捷键Ctrl+N )
选择uni-app类型,输入工程名,选择模板,选择Vue版本,点击创建即可
Vue-CLI 命令行创建
3. 运行uni-app
在 浏览器 运行
点击工具栏的运行 -> 运行到浏览器 -> 选择浏览器
在 微信开发者工具 运行
如果自动启动失败,可用微信开发者工具手动打开项目
项目在unpackage/dist/dev/mp-weixin路径下
01 - 开启服务端口
微信开发者工具需要开启服务端口:
小程序开发工具设置 -> 安全(目的是让HBuilder可以启动微信开发者工具)
02 - 运行
在 手机或模拟器 运行
这里是mac电脑 + ios手机环境
ps : 之所以要用XCode新建一个项目,先打开模拟器,再用hbuilderx打开相同的模拟器
是为了减少bug,不这么做容易有奇奇怪怪的小问题
XCode 设置
01 - 安装XCode
02 - 新建Xcode项⽬
03 - 选择项⽬类型
04 - 填写项⽬信息
05 - 选择路径
06 - 启动Xcode项⽬生成一个IOS模拟器
07 - 运⾏Xcode项⽬的效果
Hbuilderx-Alpha 设置
01 - 安装手机模拟器插件
02 - 配置adb路径(可跳过)
可不配 : 不配会自动去寻找默认的
HBuilderX正式版adb目录位置 :
windows : 安装路径下的 tools/adbs 目录
mac : HBuilderX.app/Contents/tools/adbs目录;
HBuilderX Alpha版的adb目录位置:
windows : 安装路径下的 plugins/launcher/tools/adbs 目录
mac下 : /Applications/HBuilderX-Alpha.app/Contents/HBuilderX/plugins/launcher/tools/adbs目录
在adbs目录下运行./adb ,即可使用adb命令(Win和Mac一样)
03 - 选择模拟器
04 - 选择模拟器
05 - 效果
有个很严重的问题,我的这样没有热更新,每次改完得重新运行,我要崩溃,有没有大佬指点迷津
ios模拟器问题 : 未修复
三、uni-app的架构和配置
1. 目录结构
2. 开发规范
为了实现多端兼容,综合考虑编译速度、运行性能等因素,uni-app 约定了如下开发规范:
页面文件遵循
组件标签靠近小程序规范
uni-app 组件规范 => 使用小程序的标签
接口能力(JS API)
靠近微信小程序规范 => 但需将前缀 wx 替换为 uni
数据绑定及事件处理
同 Vue.js 规范 => 例如使用@click
生命周期
可用小程序的
也可用vue的
为兼容多端运行
建议使用flex布局
推荐使用rpx单位
uni-app的官网文档
3. main.js
main.js是 uni-app 的入口文件,主要作用是:
初始化vue实例
定义全局组件
定义全局属性
安装插件,如:pinia、vuex 等
01 - 初始化vue实例
02 - 定义全局组件
import { createSSRApp } from 'vue'
//引入组件
import myComponent from './components/my-component/my-component.vue'
export function createApp() {
const app = createSSRApp(App)
//调用app.component方法全局注册组件
app.component('my-component', myComponent)
return {
app
}
}
03 - 定义全局属性
// vue2
Vue.prototype.$http = () => {}
// vue3
export function createApp() {
const app = createSSRApp(App);
app.config.globalProperties.$http = () => {}
return {
app
}
}
04 - 安装插件,如:pinia、vuex 等
import { createSSRApp } from 'vue'
// 当然这里要自己先封一下 Pinia
import pinia from '.stores'
export function createApp() {
const app = createSSRApp(App);
app.use(pinia);
return {
app
Pinia // 此处必须将 Pinia 返回
}
}
4. App.vue
App.vue : 入口组件
App.vue是uni-app的入口组件,所有页面都是在App.vue下进行切换
App.vue本身不是页面,这里不能编写视图元素,也就是没有<template>元素
App.vue的作用是 :
应用的生命周期
编写全局样式
定义全局数据 globalData
01 - 应用生命周期
注意:应用生命的周期仅可在App.vue中监听,在页面监听无效。
<script>
export default {
/*
* App应用的生命周期
*/
onLaunch: function(option) {
// 可以获取到小程序设置的启动参数
console.log('App Launch')
},
onShow: function() {
console.log('App Show')
},
onHide: function() {
console.log('App Hide')
}
}
</script>
<style >
/*每个页面公共css */
</style>
02 - 编写全局样式
全局样式 : App.vue 中style的样式,作用于每一个页面(style标签不支持scoped)
App.vue 中通过 @import 语句可以导入外联样式,一样作用于每一个页面
局部样式 : 在 pages 目录下 的 vue 文件的style中的样式为局部样式,只作用对应的页面,并会覆盖 App.vue 中相同的选择器
style标签不支持scoped,默认就是局部样式
<script>
export default {
onLaunch: function() {
},
onShow: function() {
},
onHide: function() {
}
}
</script>
<!-- 这里不支持写scoped属性 -->
<style lang='scss'>
/*每个页面公共css */
/* 这个文件中定义的变量 */
@import '@/static/css/init.scss';
@import '@/static/css/base.css';
.title{
color: red;
/* 这里可以使用变量,但是其他页面无法使用,若想使用,那个页面也得导入scss文件 */
border: 2rpx solid $mainColor;
}
</style>
03 - 定义全局数据 globalData
<script>
export default {
// 定义全局变量
globalData: {
text: 'text'
},
onLaunch: function() {
// getApp对象还未获取,暂时可以使用this.globalData获取globalData
console.log('App Launch', this.globalData) // App Launch {text: 'text'}
},
onShow: function() {
// 可通过 getApp().globalData.* 来操作,其他页面也是这样调用
console.log('App Show', getApp().globalData) // App Show {text: 'text'}
},
onHide: function() {
console.log('App Hide')
}
}
</script>
// 页面使用
onShow() {
// getApp() => 全部页面自带,都可以使用
console.log('page', getApp().globalData);
}
5. uni.scss
uni.scss 全局样式文件
为了方便整体控制应用风格,默认定义了uni-app框架内置全局变量,也可以存放自定义的全局变量等
在uni.scss中定义的变量,无需 @import 就可以在任意组件中直接使用。
使用uni.scss中的变量,需在 HBuilderX 里面安装 scss 插件(dart-sass插件),
然后在该组件的 style 上加 lang=“scss”,重启即可生效
注意事项 :
这里的uni-app框架内置变量和后面uni-ui组件库的内置变量是不一样的。
uni.scss定义的变量是全局可以直接使用,App.vue定义的变量只能在当前组件中使用
uni.scss的作用 :
定义自定义的全局的样式变量
重写uni-app内置的样式变量
重写uni-un内置的样式变量
6. page.json
page.json : 全局页面配置(兼容h5、weapp、app )
pages.json 文件用来对 uni-app 进行全局配置,类似微信小程序中app.json
决定页面的路径、窗口样式、原生的导航栏、底部的原生tabbar 等
{
"pages": [
// 页面窗口的配置,优先级比全局的要高
// 首页
{
"path": "pages/index/index",
"style": {
// 相当于配置页面样式
"navigationBarTitleText": "空我,核弹踢!"
}
}
],
// 相当于整个小程序的顶部窗口
"globalStyle": {
// 导航栏标题的颜色 black/white
"navigationBarTextStyle": "black",
// 导航栏标题的文字,整体的,会被上面的单个页面配置的覆盖
"navigationBarTitleText": "迪迦奥特曼,冲啊",
// 顶部背景颜色
"navigationBarBackgroundColor": "#ff8198",
// 下拉刷新时可以看到的那个
"backgroundColor": "#F8F8F8"
}
}
7. manifest.json
manifest.json : 应用配置
Android平台相关配置
iOS平台相关配置
Web端相关的配置
微信小程序相关配置
......
四、uni-ui组件库
uni-ui是DCloud提供的一个UI组件库,一套基于Vue组件、flex布局的跨全端UI框架
uni-ui不包括uni-app框架提供的基础组件,而是基础组件的补充
网址 : uni-ui
1. 安装 uni-ui 组件库
方式一 : uni_modules按需安装
通过 uni_modules(插件模块化规范)单独安装组件
1. 官网找到扩展组件清单,然后将所需要的组件导入到项目,导入后直接使用,无需import和注册
2. 若想切换应用风格,可以在uni.scss导入uni-ui提供的内置scss变量,然后重启应用
ps :需要登录 DCloud 账号才能安装
方式二 : uni_modules全部安装
方式三 : 创建项目时安装
ps: 该方式使得全部组件都下载了
方式四 : npm 安装
2. 定制 uni-ui 主题风格
安装dart-sass插件(一般都会提示,并自动安装)
在项目根目录的uni.scss文件中引入uni-ui组件库的variable.scss变量文件
然后就可以使用或修改对应的scss变量
变量主要定义的是主题色
3. 组件样式穿透
// 小程序 和 app 有效果
.uni-forms-item_label{
color:red !important;
}
// 小程序 和 app 和 h5
:deep(.uni-forms-item_label){
color:red !important;
}
// 小程序 和 app 和 h5
:global(.uni-forms-item_label){
color:red !important;
}
五、跨端兼容实现
uni-app能实现一套代码、多端运行,核心是通过编译器 + 运行时实现的:
编译器:将uni-app统一代码编译生成每个平台支持的特有代码
如在小程序平台,编译器将.vue文件拆分生成wxml、wxss、js等。
运行时:动态处理数据绑定、事件代理,保证 Vue和对应宿主平台 数据的一致性
1. 存在的问题
跨平台存在的问题:
uni-app 已将常用的组件、JS API 封装到框架中,按照 uni-app 规范开发即可保证多平台兼容
大部分业务均可直接满足。
但每个平台有自己的一些特性,因此会存在一些无法跨平台的情况
大量写 if else,会造成代码执行性能低下和管理混乱
编译到不同的工程后二次修改,会让后续升级变的很麻烦
跨平台兼容解决方案:
在 C 语言中,通过 #ifdef、#ifndef 的方式,为 windows、mac 等不同 os 编译不同的代码
uni-app 参考这个思路,为 uni-app 提供了条件编译手段,在一个工程里优雅的完成了平台个性化实现
2. 条件编译
01 - 具体语法
// #ifdef %PLATFORM%
平台特有的API实现
// #endif
02 - 支持的文件
<template>
<view class="content">
页面!!!!
<!-- 只在h5中显示 -->
<!-- #ifdef H5 -->
<view>
<uni-badge text="1" type="primary"></uni-badge>
</view>
<!-- #endif -->
<!-- 在微信中 或 app中显示 -->
<!-- #ifdef MP-WEIXIN || APP-PLUS -->
<view class="img"></view>
<!-- #endif -->
</view>
</template>
<script>
export default {
data() {
return {
title: '1999888'
}
},
onLoad() {
// #ifdef H5
document.title = 'h5 !!!!!!!'
// 可以在这里操作dom
// #endif
// #ifdef MP-WEIXIN
// pages.json中设定的优先级比较高
wx.setNavigationBarTitle({
title: 'WXapp'
})
// #endif
// #ifdef APP-PLUS
// 这个是跨端的
uni.setNavigationBarTitle({
title: 'APP'
})
// #endif
},
onShow() {
console.log('page', getApp().globalData);
},
}
</script>
<style lang="scss">
/* #ifdef H5 */
.uni-badge--x {
background-color: blue;
}
/* #endif */
/* #ifdef APP-PLUS || MP-WEIXIN */
.img {
height: 200rpx;
background: url("~@/static/abc/logo.png") no-repeat;
background-size: contain;
}
/* #endif */
</style>
03 - 注意事项
Android 和 iOS 平台不支持条件编译
如需区分 Android、iOS 平台,请通过调用 uni.getSystemInfo 来获取平台信息
六、页面 - Page
1. 新建页面
01 - 新建页面
可直接新建页面,不用新建目录,会带同名目录
02 - 在pages.json中配置
一般会自动生成,如果没有,手写即可
03 - 配置tabBar
2. 页面路由
uni-app 有两种页面路由跳转方式: 和小程序一模一样
使用navigator组件跳转
调用API跳转(类似小程序,与vue-router不同)
API跳转
跳转到 TabBar 页面
uni.switchTab
跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面
<template>
<view class="content">
<button type="primary" @click="jumpFn">switchTab</button>
</view>
</template>
<script>
export default {
methods: {
jumpFn() {
uni.switchTab({
// 需要跳转的 tabBar 页面的路径(需在 pages.json 的 tabBar 字段定义的页面),路径后不能带参数
url: '/pages/about/about',
success: (res) => {
console.log('success', res); // success {errMsg: 'switchTab:ok'}
},
fail: (err) => {
console.log('fail', err);
},
complete: (res) => {
console.log('complete', res); // complete {errMsg: 'switchTab:ok'}
}
})
}
}
}
</script>
跳转到 普通 页面
uni.navigateTo
保留当前页面,跳转到应用内的某个页面,使用uni.navigateBack可以返回到原页面
<template>
<view class="content">
<button type="primary" @click="jumpFn">navigateTo</button>
</view>
</template>
<script>
export default {
methods: {
jumpFn() {
uni.navigateTo({
// 需要跳转的应用内非 tabBar 的页面的路径 , 路径后可以带参数
url: '/pages/detail/detail?name=coder&age=18',
// 仅支持在app端看到运动 效果
animationType: 'fade-in',
animationDuration: 2000,
success: (res) => {
console.log('success:', res);
},
fail: (err) => {
console.log('fail:', err);
},
complete: (res) => {
console.log('complete:', res);
},
})
}
}
}
</script>
uni.navigateBack
关闭当前页面,返回上一页面或多级页面
可通过 getCurrentPages() 获取当前的页面栈,决定需要返回几层
// 此处是A页面
uni.navigateTo({
url: 'B?id=1'
});
// 此处是B页面
uni.navigateTo({
url: 'C?id=1'
});
// 在C页面内 navigateBack,将返回A页面
uni.navigateBack({
delta: 2,
success: (res) => {
console.log('success:', res);
},
fail: (err) => {
console.log('fail:', err);
},
complete: (res) => {
console.log('complete:', res);
},
});
uni.redirectTo
关闭当前页面,跳转到应用内的某个页面
uni.redirectTo({
url:'test?id=1',
success: (res) => {
console.log('success:', res);
},
fail: (err) => {
console.log('fail:', err);
},
complete: (res) => {
console.log('complete:', res);
},
});
uni.reLaunch
关闭所有页面,打开到应用内的某个页面
uni.reLaunch({
url:'test?id=1',
success: (res) => {
console.log('success:', res);
},
fail: (err) => {
console.log('fail:', err);
},
complete: (res) => {
console.log('complete:', res);
},
});
Navigator跳转
跳转到 tabBar 页面
open-type="switchTab" 对应 uni.switchTab 的功能
<navigator open-type="switchTab" url="../profy/profy">跳转到个人</navigator>
跳转到 普通 页面
路由跳转中相互传值
若有特殊字符
传递时 : encodeURIComponent 编码
接受时 : decodeURIComponent 解码
url查询字符 和 直接修改值
首页 => 详情页
jumpFn() {
uni.navigateTo({
// 需要跳转的应用内非 tabBar 的页面的路径 , 路径后可以带参数
url: '/pages/detail/detail?name=coder&age=18',
// 仅支持在app端看到运动 效果
animationType: 'fade-in',
animationDuration: 2000,
success: (res) => {
console.log('success:', res);
},
fail: (err) => {
console.log('fail:', err);
},
complete: (res) => {
console.log('complete:', res);
},
})
}
详情页 => 首页
export default {
// 可在这获取到首页传递过来的值
onLoad(option) {
console.log(option); // {name: 'coder', age: '18'}
},
/**
* 写在这里的理由 : 用户可能点击顶部状态栏中的返回键,写在这不管怎么返回,都会触发
*/
// 页面被注销时调用
onUnload() {
// 1. 获取到已经存在的所有页面
const pages = getCurrentPages()
// 2. 拿到上一个页面的实例 当前页面为最后一个,所以上一个页面是减2
const prePage = pages[pages.length - 2]
/**
* 3. 设置值
*/
// H5端
// #ifdef H5
prePage.arr[1].name = 'ccc'
// #endif
// 微信端,有个$vm
// #ifdef MP-WEIXIN
prePage.$vm.arr[1].name = 'ccc'
// #endif
// app端,上述两种都可满足,奇怪
// #ifdef APP-PLUS
// prePage.arr[1].name = 'ccc'
prePage.$vm.arr[1].name = 'ccc'
// #endif
}
}
url查询字符 和 EventChannel修改
只有 uni.navigateTo 才能使用这个哦
首页 => 详情页
jumpFn() {
uni.navigateTo({
// 需要跳转的应用内非 tabBar 的页面的路径 , 路径后可以带参数,如果有特殊字符记得编码
url: `/pages/detail/detail?name=${encodeURIComponent('coder')}&age=18`,
events: {
// 为指定事件添加一个监听器,获取被打开页面传送到当前页面的数据
acceptDataFromOpenedPage: (data) => {
console.log('acceptDataFromOpenedPage',
data) // acceptDataFromOpenedPage {name: 'coder'}
},
someEvent: (data) => {
console.log('someEvent', data) // someEvent {age: 10}
}
},
success: (res) => {
console.log('success:', res);
// 通过eventChannel向被打开页面传送数据,用此方式可不用在url上拼接参数
res.eventChannel.emit('acceptDataFromOpenerPage', { data: 'data from starter page' })
},
fail: (err) => {
console.log('fail:', err);
},
complete: (res) => {
console.log('complete:', res);
},
})
}
详情页 => 首页
export default {
// 可在这获取到首页传递过来的值
onLoad(option) {
console.log(option, decodeURIComponent(option.name)); // {name: 'coder', age: '18'}
},
/**
* 写在这里的理由 : 用户可能点击顶部状态栏中的返回键,写在这不管怎么返回,都会触发
*/
// 页面被注销时调用
onUnload() {
// 1. 拿到eventChanner渠道
const eventChanner = this.getOpenerEventChannel()
// 2. 通过渠道,传递数据给上一个页面
eventChanner.emit('acceptDataFromOpenedPage', {
name: 'coder'
})
eventChanner.emit('someEvent', {
age: 10
})
// 3. 监听上一个页面传递过来的数据
eventChanner.on('acceptDataFromOpenerPage', function(data) {
console.log(data) // {data: 'data from starter page'}
})
}
}
vue3写法
首页 => 详情页
<template>
<view class="content">
<button type="primary" @click="jumpFn">navigateTo</button>
</view>
</template>
<script setup>
import { ref } from 'vue'
const arr = ref([{
name: 'coder',
age: 12
},
{
name: 'star',
age: 18
},
])
const age = ref(-1)
const jumpFn = () => {
uni.navigateTo({
// 需要跳转的应用内非 tabBar 的页面的路径 , 路径后可以带参数,如果有特殊字符记得编码
url: `/pages/detail/detail?name=${encodeURIComponent('coder——饿$12${}')}&age=18`,
events: {
// 为指定事件添加一个监听器,获取被打开页面传送到当前页面的数据
acceptDataFromOpenedPage: (data) => {
console.log('acceptDataFromOpenedPage',
data) // acceptDataFromOpenedPage {name: 'coder'}
},
someEvent: (data) => {
console.log('someEvent', data) // someEvent {age: 10}
age.value = data.age
}
},
success: (res) => {
console.log('success:', res);
},
fail: (err) => {
console.log('fail:', err);
},
complete: (res) => {
console.log('complete:', res);
},
})
}
</script>
详情页 => 首页
<template>
<view>
detail-view
</view>
</template>
<script setup>
import { ref, getCurrentInstance } from 'vue'
import { onLoad, onUnload } from "@dcloudio/uni-app";
// 方式二 : 也可在defineProps中拿到传递过来的值
const props = defaineProps({
name: String,
age: Number
})
console.log(option.name,option.age)
// 方式一 : 可在这获取到首页传递过来的值
onLoad((option) => {
console.log(option, decodeURIComponent(option.name)); // {name: 'coder', age: '18'}
})
// 拿到当前实例,可以理解为this
const instance = ref(getCurrentInstance().proxy)
/**
* 写在这里的理由 : 用户可能点击顶部状态栏中的返回键,写在这不管怎么返回,都会触发
*/
// 页面被注销时调用
onUnload(() => {
// 1. 拿到eventChanner渠道
const eventChanner = instance.value.getOpenerEventChannel()
// const eventChanner = getCurrentInstance().proxy.getOpenerEventChannel()
// 2. 通过渠道,拿到回调函数,并且传递数据给上一个页面
eventChanner.emit('acceptDataFromOpenedPage', {
name: 'coder'
})
eventChanner.emit('someEvent', {
age: 10
})
})
</script>
3. 事件总线
01 - 注意事项
需先监听,再触发事件,比如:你在A界面触发,然后跳转到B页面后才监听是不行的
通常on 和 off 是同时使用,可以避免多次重复监听
适合页面返回传递参数、适合跨组件通讯,不适合界面跳转传递参数
02 - 页面通讯
uni.$emit
触发全局的自定义事件,附加参数都会传给监听器回调
uni.$emit('emitFn',{msg:'页面更新'})
uni.$on
监听全局的自定义事件
事件可以由 uni.$emit 触发,回调函数会接收所有传入事件触发函数的额外参数
uni.$on('emitFn',(data) => {
console.log('监听到事件来自 emitFn ,携带参数 msg 为:' + data.msg);
})
uni.$once
监听全局的自定义事件
事件可以由 uni.$emit 触发,但是只触发一次,在第一次触发之后移除监听器
uni.$once('emitFn',(data) => {
console.log('监听到事件来自 emitFn ,携带参数 msg 为:' + data.msg);
})
uni.$off
移除全局自定义事件监听器
// 注 : 这样并不能清除监听过的emitFn
uni.$off('emitFn',(data) => {
console.log('监听到事件来自 emitFn ,携带参数 msg 为:' + data.msg);
})
03 - 代码示例
需先监听,再触发事件 ,比如:你在A界面触发,然后跳转到B页面后才监听是不行的
A监听,B发射,A再监听才能拿到值
A组件监听
<template>
<view class="content">
<button type="primary" @click="jumpFn">navigateTo</button>
</view>
</template>
<script setup>
import { onLoad, onUnload } from "@dcloudio/uni-app";
// 跳转到详情页
const jumpFn = () => {
uni.navigateTo({
url: `/pages/detail/detail`,
})
}
const emitFn = (res) => {
console.log('emitFn', res);
}
onLoad(() => {
// 监听
uni.$on('emitFn', emitFn)
})
onUnload(() => {
// 移除
uni.$off('emitFn', emitFn)
})
</script>
B组件发射
<template>
<view>
detail-view
</view>
</template>
<script setup>
import { onUnload } from "@dcloudio/uni-app";
onUnload(() => {
uni.$emit('emitFn', {
msg: '冲啊,迪迦奥特曼!!!'
})
})
</script>
4. 生命周期
tabBar的页面不会销毁,不会触发onUnload
Options API
export default {
/**
* 都会触发
* */
// 1.页面的生命周期
onLoad(options) {
console.log('onLoad');
},
onShow() {
console.log('onShow');
console.log(this);
},
onReady() {
console.log('onReady');
},
onHide() {
console.log('onHide');
},
onUnload() {
console.log('onUnload');
},
onPullDownRefresh() {
console.log('onPullDownRefresh');
setTimeout(() => {
uni.stopPullDownRefresh()
}, 1000)
},
onReachBottom() {
console.log('onReachBottom');
},
// 2.Vue组件的生命周期
beforeCreate() {
console.log('beforeCreate');
},
created() {
console.log('created');
},
beforeMount() {
console.log('beforeMount');
},
mounted() {
console.log('mounted');
},
beforeDestroy() {
console.log('beforeDestroy');
},
destroyed() {
console.log('destroyed');
}
}
Composition API
<script setup>
import { ref, onBeforeMount, onMounted } from 'vue'
import {
onLoad,
onShow,
onReady,
onHide,
onUnload,
onPullDownRefresh,
onReachBottom
} from '@dcloudio/uni-app'
// 1.页面的生命周期
onLoad((options) => {
console.log('onLoad');
})
onShow(() => {
console.log('onShow');
})
onReady(() => {
console.log('onReady');
})
onHide(() => {
console.log('onHide');
})
onUnload(() => {
console.log('onUnload');
})
onPullDownRefresh(() => {
console.log('onPullDownRefresh');
setTimeout(() => {
uni.stopPullDownRefresh()
}, 1000)
})
onReachBottom(() => {
console.log('onReachBottom');
})
// 2.Vue组件的生命周期
onBeforeMount(() => {
console.log('onBeforeMount');
})
onMounted(() => {
console.log('onMounted');
})
</script>
七、系统API调用
1. 网络请求
简单使用
偷个懒,文档上复制的~
uni.request({
url: 'https://www.example.com/request', //仅为示例,并非真实接口地址。
data: {
text: 'uni.request'
},
header: {
'custom-header': 'hello' //自定义请求头信息
},
success: (res) => {
console.log(res.data);
this.text = 'request success';
}
});
01 - 进行封装
目录结构
request目录
index.js
/**
* 封装请求
*/
import { BASE_URL, TIME_OUT } from './config.js'
// 封装成类
class StarRequest {
// 设定公共URL + 超时时间
constructor(url, timeout) {
this.baseUrl = url
this.timeout = timeout
}
request({ url, method = 'GET', data } = {}) {
// 返回一个promise
return new Promise((resolve, reject) => {
uni.request({
url: this.baseUrl + url,
timeout: this.timeout,
method,
data,
success: (res) => {
resolve(res.data)
},
fail: reject
})
})
}
get() {
return this.request(option)
}
post() {
return this.request({ ...option, method: 'POST' })
}
}
// 可创建多个实例,请求不同的地址
export const sRequest = new StarRequest(BASE_URL, TIME_OUT)
config.js
/**
* 设定常量
*/
export const BASE_URL = 'http://www.baidu.com/api'
export const TIME_OUT = 10000
modules目录
common.js
/**
* 封装公共逻辑
*/
import { sRequest } from '@/service/request/index.js'
// 获取公共的字典数据
export const getAllDics = () => {
return sRequest.request({
url: '/common/dic'
})
}
统一导出index.js
/**
* 作统一导出
*/
// 公共数据
export { getAllDics } from './modules/common'
// ...
02 - 使用
import { onLoad, onUnload } from "@dcloudio/uni-app";
import { getAllDics } from '@/service/index.js'
// 封装一下请求,可以写在utils中,这里为了方便写在这
const awaitWrap = (promise) => {
// 就不用写try...catch了
return promise.then(res => [res, null]).catch(err => [null, err])
}
onLoad(async () => {
// 使用请求
const [res, err] = await awaitWrap(getAllDics())
// 如果不为空,说明抛出了异常,返回即可
if (err !== null) return console.log('请求错误');
// 拿到数据
console.log(res);
})
2. 数据缓存
sync : 同步,不存储完,不会执行后续代码
八、Vue文档总结
Vue2 - Options API
Vue3 - Composition API
九、打包配置
H5 - 打包配置
1. 修改manifest.json的配置
2. 发行 - 打包H5
3. 部署到服务器即可
可看我的另一篇文章 : 云原生 之 docker
微信小程序 - 打包配置
1. 拿到小程序appId
2. 修改manifest.json的配置
3. 发行-微信小程序
4. 在微信开发者工具中进行上传
APP - 配置
待更新,未操作~