uni-app 之 跨平台开发
![](/assets/blank.gif)
一、概念
1. 原生 VS 跨平台
原生开发
优点
性能稳定,使用流畅,用户体验好、功能齐全,安全性有保证,兼容性好,可使用手机所有硬件功能等
缺点
开发周期长、维护成本高、迭代慢、部署慢、新版本必须重新下载应用
不支持跨平台,必须同时开发多端代码
跨平台开发
优点
可以跨平台,一套代码搞定iOS、Android、微信小程序、H5应用等
开发成本较低,开发周期比原生短
适用于跟系统交互少、页面不太复杂的场景
缺点
对开发者要求高,除了本身JS的了解,还必须熟悉一点原生开发
不适合做高性能、复杂用户体验,以及定制高的应用程序。比如:抖音、微信、QQ等
同时开发多端兼容和适配比较麻烦、调试起来不方便
2. 跨平台框架对比
![](/assets/blank.gif)
3. 认识uni-app
![](/assets/blank.gif)
4. uni-app VS 微信小程序
相同点
都是接近原生的体验、打开即用、不需要安装
都可开发微信小程序、都有非常完善的官方文档
不同点
跨平台
uni-app : 支持跨平台,编写一套代码,可以发布到多个平台
微信小程序 : 不支持
工程化
uni-app : 纯Vue体验、高效、统一、工程化强
微信小程序 : 工程化弱、使用小程序开发语言
复杂程度
uni-app : 适合不太复杂的应用,因为需要兼容多端,多端一起兼容和适配增加了开发者心智负担
微信小程序 : 适合较复杂、定制性较高、兼容和稳定性更好的应用
如何选择
需要跨平台、不太复杂的应用选 uni-app,复杂的应用使用uni-app反而增加了难度。
不需要跨平台、较复杂、对兼容和稳定性要求高的选原生微信小程序
5. uni-app架构图
![](/assets/blank.gif)
二、uni-app初体验
1. 开发工具
Hbuilder X : 是通用的前端开发工具,但为 uni-app 做了特别强化
网址 : hbuilderxps : 用Vue3的Composition API 建议用 HBuilder X最新Alpha版,旧版有兼容问题
2. 创建项目
可视化界面创建 ( 推荐 )
点工具栏里的文件 -> 新建 -> 项目 ( 快捷键Ctrl+N )
选择uni-app类型,输入工程名,选择模板,选择Vue版本,点击创建即可
![](/assets/blank.gif)
Vue-CLI 命令行创建
![](/assets/blank.gif)
3. 运行uni-app
在 浏览器 运行
点击工具栏的运行 -> 运行到浏览器 -> 选择浏览器
![](/assets/blank.gif)
在 微信开发者工具 运行
如果自动启动失败,可用微信开发者工具手动打开项目
项目在unpackage/dist/dev/mp-weixin路径下
01 - 开启服务端口
微信开发者工具需要开启服务端口:
小程序开发工具设置 -> 安全(目的是让HBuilder可以启动微信开发者工具)
![](/assets/blank.gif)
02 - 运行
![](/assets/blank.gif)
在 手机或模拟器 运行
这里是mac电脑 + ios手机环境
ps : 之所以要用XCode新建一个项目,先打开模拟器,再用hbuilderx打开相同的模拟器
是为了减少bug,不这么做容易有奇奇怪怪的小问题
XCode 设置
01 - 安装XCode
![](/assets/blank.gif)
02 - 新建Xcode项⽬
![](/assets/blank.gif)
03 - 选择项⽬类型
![](/assets/blank.gif)
04 - 填写项⽬信息
![](/assets/blank.gif)
05 - 选择路径
![](/assets/blank.gif)
06 - 启动Xcode项⽬生成一个IOS模拟器
![](/assets/blank.gif)
07 - 运⾏Xcode项⽬的效果
![](/assets/blank.gif)
Hbuilderx-Alpha 设置
01 - 安装手机模拟器插件
![](/assets/blank.gif)
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 - 选择模拟器
![](/assets/blank.gif)
04 - 选择模拟器
![](/assets/blank.gif)
05 - 效果
![](/assets/blank.gif)
有个很严重的问题,我的这样没有热更新,每次改完得重新运行,我要崩溃,有没有大佬指点迷津
ios模拟器问题 : 未修复
![](/assets/blank.gif)
三、uni-app的架构和配置
1. 目录结构
![](/assets/blank.gif)
2. 开发规范
为了实现多端兼容,综合考虑编译速度、运行性能等因素,uni-app 约定了如下开发规范:
页面文件遵循
Vue 单文件组件 (SFC) 规范
组件标签靠近小程序规范
uni-app 组件规范 => 使用小程序的标签
接口能力(JS API)
靠近微信小程序规范 => 但需将前缀 wx 替换为 uni
uni-app接口规范
数据绑定及事件处理
同 Vue.js 规范 => 例如使用@click
生命周期
可用小程序的
也可用vue的
为兼容多端运行
建议使用flex布局
推荐使用rpx单位
uni-app的官网文档
uni-app官网文档
3. main.js
main.js是 uni-app 的入口文件,主要作用是:
初始化vue实例
定义全局组件
定义全局属性
安装插件,如:pinia、vuex 等
01 - 初始化vue实例
![](/assets/blank.gif)
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 {appPinia // 此处必须将 Pinia 返回}
}
4. App.vue
App.vue : 入口组件
App.vue是uni-app的入口组件,所有页面都是在App.vue下进行切换
App.vue本身不是页面,这里不能编写视图元素,也就是没有<template>元素
App.vue的作用是 :
应用的生命周期
编写全局样式
定义全局数据 globalData
01 - 应用生命周期
注意:应用生命的周期仅可在App.vue中监听,在页面监听无效。
![](/assets/blank.gif)
<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获取globalDataconsole.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内置的样式变量
![](/assets/blank.gif)
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端相关的配置
微信小程序相关配置
......
![](/assets/blank.gif)
四、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 账号才能安装
![](/assets/blank.gif)
方式二 : uni_modules全部安装
![](/assets/blank.gif)
方式三 : 创建项目时安装
ps: 该方式使得全部组件都下载了
![](/assets/blank.gif)
方式四 : npm 安装
2. 定制 uni-ui 主题风格
安装dart-sass插件(一般都会提示,并自动安装)
在项目根目录的uni.scss文件中引入uni-ui组件库的variable.scss变量文件
然后就可以使用或修改对应的scss变量
变量主要定义的是主题色
![](/assets/blank.gif)
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 - 具体语法
![](/assets/blank.gif)
// #ifdef %PLATFORM%
平台特有的API实现
// #endif
02 - 支持的文件
![](/assets/blank.gif)
<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 H5document.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 来获取平台信息
![](/assets/blank.gif)
六、页面 - Page
1. 新建页面
01 - 新建页面
可直接新建页面,不用新建目录,会带同名目录
![](/assets/blank.gif)
02 - 在pages.json中配置
一般会自动生成,如果没有,手写即可
![](/assets/blank.gif)
03 - 配置tabBar
![](/assets/blank.gif)
2. 页面路由
uni-app 有两种页面路由跳转方式:和小程序一模一样
使用navigator组件跳转
调用API跳转(类似小程序,与vue-router不同)
![](/assets/blank.gif)
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跳转
![](/assets/blank.gif)
跳转到 tabBar 页面
open-type="switchTab" 对应 uni.switchTab 的功能
<navigator open-type="switchTab" url="../profy/profy">跳转到个人</navigator>
跳转到 普通 页面
![](/assets/blank.gif)
路由跳转中相互传值
若有特殊字符
传递时 : 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. 拿到上一个页面的实例 当前页面为最后一个,所以上一个页面是减2const 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'}})// 拿到当前实例,可以理解为thisconst 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
移除全局自定义事件监听器
![](/assets/blank.gif)
// 注 : 这样并不能清除监听过的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. 网络请求
![](/assets/blank.gif)
简单使用
偷个懒,文档上复制的~
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 - 进行封装
目录结构
![](/assets/blank.gif)
request目录
index.js
/*** 封装请求*/import { BASE_URL, TIME_OUT } from './config.js'// 封装成类
class StarRequest {// 设定公共URL + 超时时间constructor(url, timeout) {this.baseUrl = urlthis.timeout = timeout}request({ url, method = 'GET', data } = {}) {// 返回一个promisereturn 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 : 同步,不存储完,不会执行后续代码
![](/assets/blank.gif)
八、Vue文档总结
Vue2 - Options API
![](/assets/blank.gif)
Vue3 - Composition API
![](/assets/blank.gif)
九、打包配置
H5 - 打包配置
1. 修改manifest.json的配置
![](/assets/blank.gif)
2. 发行 - 打包H5
![](/assets/blank.gif)
3. 部署到服务器即可
可看我的另一篇文章 : 云原生 之 docker
微信小程序 - 打包配置
1. 拿到小程序appId
![](/assets/blank.gif)
2. 修改manifest.json的配置
![](/assets/blank.gif)
3. 发行-微信小程序
![](/assets/blank.gif)
4. 在微信开发者工具中进行上传
![](/assets/blank.gif)
APP - 配置
待更新,未操作~
uni-app 之 跨平台开发相关推荐
- uni app和php开发微信登录代码,uniapp如何实现微信授权登录
uniapp实现微信授权登录的方法:首先获取对应的appid和appsecret:然后在uniapp项目的manifest.json中进行APP SDK配置和模块权限配置.最后实现编码. 本教程操作环 ...
- andorid 手机APP应用程序开发介绍
注意:此处的应用程序是一个app应用程序,而不是我们通常指的移动应用程序. 1.结束比较 本机应用 传统的本机应用程序开发模型中有两个主要系统,即iOS和Android,开发自己的应用程序需要使用每种 ...
- 原生革命--跨平台开发技术解析
这篇文章,我将着重分析当前主流跨平台开发解决方案(偏架构)如Flutter.RN.Weex.Hybrid App,并对新晋跨端解决方案Fusion和Chameleon做一些分析,在传统原生开发不断被唱 ...
- 【iOS开发】跨平台开发再次袭来
转自喵神博客:点击打开链接 这篇文章主要想谈谈最近又刮起的移动开发跨平台之风,并着重介绍和对比一下像是Xamarin,NativeScript 和 React Native 之类的东西.不会有特别深入 ...
- 跨平台开发时代的 (再次) 到来?
这篇文章主要想谈谈最近又刮起的移动开发跨平台之风,并着重介绍和对比一下像是Xamarin,NativeScript .React Native和 DeviceOne 之类的东西.不会有特别深入的技术讨 ...
- 切换 uniapp_万能前端框架uni app初探03:底部导航开发
前言 本节我们使用uni app的底部导航功能,点击不同tab会显示不同页面,这个功能在实际项目开发中几乎是必备的. 一.基础知识 1.tabBar 如果应用是一个多 tab 应用,可以通过 tabB ...
- 跨平台APP JQuery Mobile开发-张晨光-专题视频课程
跨平台APP JQuery Mobile开发-1170人已学习 课程介绍 jQuery Mobile 是创建移动 web 应用程序的框架: 适用于所有流行的智能手机和平板电脑,使用 H ...
- App跨平台开发方案与抉择
内心强大才敢于承认错误,但是首先你要敢于去试错. 现在做客户端开发的公司都会面临一个巨大的问题,那么就是跨平台.对于目前上市面上的移动设备来说.Android.IOS.WindowsPhone.Bla ...
- 推荐几款App跨平台开发工具
众所周知开发App比较复杂,不仅要懂多种编程语言还要考虑高额的成本.作为开发者需要找到一个既节省成本又能快速开发App的最佳解决方案.不少跨平台开发工具便应运而生,选择一款适合自己的工具尤为重要,下面 ...
- uni app 开发微信小程序及上线体验
uni app 开发微信小程序及上线体验 项目创建及微信小程序AppId的申请 本次开发的是电商类的微信小程序,这里用到的是HBuilderX这个编辑器.之前用的Visual Studio Code ...
最新文章
- add svn 多个文件_深圳信狮SVN技术文档
- CodeForces - 1368F Lamps on a Circle(交互+贪心)
- python测试开发实战_《python测试开发实战》基于pytest基础部分实例1-Hello
- lisp java_从Java调用的LISP代码
- php关闭gd库,详解php开启gd库的两种方法
- linux安装mysql5.6整套_Linux安装Mysql5.6
- element table多选表格_关于layui表格obj.update();无法重渲模板引擎问题
- 如何控制局域网网速_科普 | 路由器网速突然变慢怎么办?
- vue 下配置标题栏 title 图标及文字的具体步骤
- 升序输出三个数_C语言入门经典例题:求100~999的水仙花数
- 基于互联网的摄像测量系统(D 题)-- 2021 年全国大学生电子设计竞赛
- 建立桌面文件管理格子_win10桌面分区,win10如何创建桌面格子
- Mimics三维建模
- 浅谈mian函数的参数解析
- 从MP3到种子王者海盗湾, 鬼知道今天的去中心化都经历了些什么
- 具有催眠作用的螺旋图
- python3如何实现一行输入,空格隔开
- python 异步io 写excel_python异步IO编程(二)
- checkbox多选框,radio单选框
- 基频分析方法汇总【笔记】
热门文章
- Energia使用入门 总体介绍和I2C的使用-基于MSP432P402R
- Bootstrap File Input,最好用的文件上传组件
- python语言表白语句简单_100句简短表白情话 表白语句大全
- mysql设置id值为索引值_MySQL 索引
- 远离负能量,才能获得正能量
- ElementUI - <el-image> src 属性使用本地图片加载失败解决方案
- iphone14全系列参数对比 苹果14防水吗
- day02 JavaScript
- Android 颜色金属效果,5种颜色金属机身仅6.7毫米_三星 GALAXY A5_手机Android频道-中关村在线...
- 2、Python量化交易-三剑客之pandas