uni-app入门


前言-课程背景

大前端时代背景下,前端开发人员掌握单一的 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 优势

  1. 开发者/案例数量更多
    几十万应用、uni 统计月活12亿、70+ 微信 / QQ群
  2. 平台能力不受限
    在跨端的同时,通过条件编译 + 平台特有 API 调用,可以优雅的为某平台写个性化代码,调用专有能力而不影响其他平台
  3. 性能体验优秀
    加载新页面速度更快、自动 diff 更新数据,App 端支持原生渲染支撑更流畅的用户体验,小程序端的性能优于市场其他框架
  4. 周边生态丰富
    插件市场数千款插件,支持 NPM、支持小程序组件和SDK,微信生态的各种 sdk 可直接用于跨平台 APP
  5. 学习成本低
    基于通用的前端技术栈,采用 vue 语法+微信小程序 api,无额外学习成本

3 功能框架

在这里插入图片描述

4 搭建开发环境

4.1 安装开发工具

  1. 下载开发工具 HbuilderX
    HbuilderX 是通用的前端开发工具,但为 uni-app 做了特别优化。
  2. 安装 微信开发者工具

4.2 创建 uni-app 项目

  1. 在HbuilderX中新建项目,选择uni-app,设置项目名称和目录,选择模板,Vue版本选择Vue3,点击新建即可。
    在这里插入图片描述

    uni-app自带的模板有 Hello uni-app ,是官方的组件和API示例。
    还有一个重要模板是 uni ui项目模板,日常开发推荐使用该模板,已内置大量常用组件。

  2. 安装编译器,在菜单栏选择工具,插件安装,安装新插件,下载uni-app(vue3)编译器。
    在这里插入图片描述

4.3 运行 uni-app

主要包括:浏览器运行、真机运行、小程序运行等

  1. 运行到浏览器中,在HbuilderX菜单栏点击运行,运行到浏览器,选择相应浏览器即可。
    在这里插入图片描述
  2. 运行到微信开发者工具,在HbuilderX菜单栏选择运行,运行到小程序模拟器,微信开发者工具。
    在HbuilderX中修改代码,微信开发者工具中的运行结果也会相应更新。
    在这里插入图片描述
    注:(1) 第一次运行需要配置小程序ide的相关路径。
    在菜单栏,点击工具,设置,选择运行设置,找到小程序运行设置,添加微信开发者工具路径。
    在这里插入图片描述
    (2) 出现如下错误需要在微信开发者工具中开启服务端口。在这里插入图片描述
    在微信开发者工具中,点击设置,安全,开启服务端口。
    在这里插入图片描述

4.4 发布 uni-app

主要包括:云端原生 APP 、离线原生 APP、H5、各种小程序

5 uni-app初始化相关配置

  1. 工程目录结构

    ┌─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 目录下

  2. 应用配置 manifest.json
    manifest.json 文件是应用的配置文件,用于指定应用的名称、图标、权限等,也可以在这里为 Vue 为H5 设置跨域拦截处理器

  3. 编译配置 vue.config.js
    vue.config.js 是一个可选的配置文件,如果项目的根目录中存在这个文件,那么它会被自动加载,一般用于配置 webpack 等编译选项。

  4. 全局配置 page.json
    pages.json 文件用来对 uni-app 进行全局配置,决定页面文件的路径、窗口样式、原生的导航栏、底部的原生tabbar 等。类似微信小程序中app.json的页面管理部分。

    属性类型必填描述
    globalStyleObject设置默认页面的窗口表现
    pagesObject Array设置页面路径及窗口表现
    easycomObject组件自动引入规则
    tabBarObject设置底部 tab 的表现
    conditionObject启动模式配置
    subPackagesObject Array分包加载配置
    preloadRuleObject分包预下载规则
  5. 全局样式 uni.scss
    uni.scss 文件的用途是为了方便整体控制应用的风格。比如按钮颜色、边框风格,uni.scss文件里预置了一批scss变量预置。
    uni-app 官方扩展插件(uni ui)及 插件市场 上很多三方插件均使用了这些样式变量。
    uni.scss是一个特殊文件,在代码中无需 import 这个文件即可在scss代码中使用这里的样式变量。uni-app的编译器在webpack配置中特殊处理了这个uni.scss,使得每个 scss 文件都被注入这个uni.scss,达到全局可用的效果。

  6. 主组件 App.vue
    App.vue是uni-app的主组件,所有页面都是在App.vue下进行切换的,是页面入口文件。但App.vue本身不是页面,不能编写视图元素。
    这个文件的作用包括:调用应用生命周期函数、配置全局样式、配置全局的存储globalData,应用生命周期仅可在App.vue中监听,在页面监听无效。

  7. 入口文件 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 生命周期

学习一个工具的目的核心是为了解决核心业务逻辑问题,业务逻辑很多时候简单的解释为一句话:“在合适的时机干合适的事情”。简单的说,页面运行过程中,各个阶段的回调函数就是页面中的时机,称为“生命周期钩子函数”。

uni-app 完整支持 Vue 实例的生命周期,同时还新增 应用生命周期页面生命周期

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 有两种页面路由跳转方式

  1. 使用 navigator 组件跳转(标签式导航)
    <!-- 切换到导航栏 open-type="switchTab" -->
    <navigator url="pages/index/index" open-type="navigate">主页</navigator>
    <navigator open-type="navigateBack">返回</navigator>
    
  2. 调用 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 有长度限制,太长的字符串会传递失败,并且不规范的字符格式也可能导致传递失败,所以对于复杂参数建议使用encodeURIdecodeURI进行处理后传递

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种场景,一种是在编译期判断,一种是在运行期判断。

  1. 编译期判断,即条件编译,不同平台在编译出包后已经是不同的代码,
    // #ifdef H5
     alert("只有h5平台才有alert方法")
    // #endif
    // 如上代码只会编译到H5的发行包里,其他平台的包不会包含如上代码。
    
  2. 运行期判断是指代码已经打入包中,仍然需要在运行期判断平台,此时可使用 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-PLUSApp
APP-PLUS-NVUEApp nvue
H5H5
MP-WEIXIN微信小程序
MP-ALIPAY支付宝小程序
MP-BAIDU百度小程序
MP-TOUTIAO字节跳动小程序
MP-QQQQ小程序
MP-360360小程序
MP微信小程序/支付宝小程序/百度小程序/字节跳动小程序/QQ小程序/360小程序
QUICKAPP-WEBVIEW快应用通用(包含联盟、华为)
QUICKAPP-WEBVIEW-UNION快应用联盟
QUICKAPP-WEBVIEW-HUAWEI快应用华为

条件注释可在html、js、css、pages.json中使用

vue 语法

template

  1. 文本标签
    支持 {{}}v-html
    小程序不支持 v-text,H5和app支持
  2. 条件渲染 v-if v-else-if v-else
    <!-- #ifndef MP-WEIXIN -->
    <view v-text = 'msg'></view>
    <!-- #endif -->
    
  3. 遍历 v-for
    <!-- 可遍历数字、字符串、对象 -->
    <view v-for='(value,key) in obj' :key='key'>{{key}}:{{value}}<view>
    
  4. 单选框和多选框
    <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>
    
  5. 事件绑定 @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" ...}
    }
    
  6. 事件修饰符
    .once 响应一次
    .prevent 阻止默认事件
    .stop 停止时间冒泡
    表单修饰符
    .number 转换为数字
    .lazy change事件触发,默认input事件
    .trim 过滤首尾空格
    按键修饰符
    .up .right .bottom .left .space .delete .enter .esc

选项式API

  1. 计算属性
    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
    			}
    		}
    	}
    }
    
  2. 监听
    watch:{
    	num:{
    		handler(val, oval){
    			// 值类型 val新值, oval 旧值
    			// 引用类型 两个值一样	
    			uni.setStorageSync('num', val)
    		},
    		// 引用类型加 deep
    		deep: true
    	}
    }
    
  3. 组件
    uni 采用 easycom 技术,自定义组件不需要导入和注册
    自定义组件存放位置:components/组件/组件.vue

组合式API

  1. 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>
    
  2. 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>
    
  3. 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
    	}
    })
    
  4. watch
    const list= reactive([1,2,3])
    // wathc 监听数据变化
    watch( list, (val, oldVal) => {
    	uni.setStorageSync('list', list)
    }, {deep: true})
    
  5. 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})
    
  6. readonly 只读
    const num= readonly(5)
    
  7. defineProps 父组件向子组件传值
    //父组件
    <Child props="child"></Child>
    // 子组件
    defineProps({
    	"props":{
    		type:[Number,String],
    		default:"",
    		required:false
    	}
    })
    
  8. defineEmits 创建事件,接收子组件传递过来的数据
    // 父组件
    <Child @add="add"></Child >
    
    const add= (val) => {
        num.value = num.value + val
     }
    // 子组件
    // 调用defineEmits并定义要发射给父组件的方法
    const emits = defineEmits(['add'])
    // 在子组件要触发的方法中,调用emits并传入发射给父组件的方法以及参数
    emits('add', 1)
    
  9. 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组件的视图会自动更新

  1. 安装
    如果项目中没有pinia,运行 npm install pinia -S 安装

  2. 配置

    // 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
    
  3. 使用——选项式
    新建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"])
    	}
    }
    
  4. 使用——组合式

    // 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

  1. 直接导入HbuilderX
    在这里插入图片描述
  2. 其他导入方式
  3. 组件文档组件演示

需要在 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 标签,类似的还有 spantextanavigator等,包括 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 父子组件通信

  1. 父组件通过自定义属性向子组件传递数据
  2. 子组件通过 props 接收父组件传递的数据
  3. 父组件通过自定义事件标签向子组件传递事件
  4. 子组件通过触发父组件定义事件方式修改父组件数据

5.3 slot 数据分发与作用域插槽

  1. 父组件通过调用子组件内部嵌套 html 内容作为slot分发给子组件
  2. 子组件通过在 slot 标签上添加属性,向父组件通信数据,作用域插槽

5.4 全局事件定义及通信

  1. 在整个应用的任何地方均可以使用uni.$on创建一个全局事件
  2. 在整个应用的任何地方也均可以使用 uni.$emit 来触发全局事件,实现多组件见的数据通信

6 uni-app Vuex 状态管理

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

  1. 应用场景
    Vue多个组件之间需要共享数据或状态。
  2. 关键规则
    State:存储状态数据
    Getter:从状态数据派生数据,相当于 State 的计算属性
    Mutation:存储用于同步更改状态数据的方法,默认传入的参数为 state
    Action:存储用于异步更改状态数据,但不是直接更改,而是通过触发 Mutation 方法实现,默认参数为context
    Module:Vuex 模块化
  3. 交互关系
    在这里插入图片描述
  4. 使用方式
import {
		mapState,
		mapActions
} from 'vuex'
export default {
		computed: {
			...mapState(['loginState', 'userInfo'])
		},
		methods: {
			...mapActions(['userLoginAction', 'userLogoutAction']),
		}
}

注意:配合使用 Storage 来实现刷新页面后状态持续保持的业务需求

持续更新中

HbulderX 快捷输入 u+要输入内容
学习视频 千锋教育前端uniapp入门到实战项目教程(微信小程序+H5+安卓APP+IOS APP)

  • 18
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值