一、什么是uni-app
uni-app
是一个使用 Vue.js 开发所有前端应用的框架,开发者编写一套代码,可发布到iOS、Android、H5、以及各种小程序(微信/支付宝/百度/头条/QQ/钉钉)等多个平台。
即使不跨端,uni-app
同时也是更好的小程序开发框架。
具有vue和微信小程序的开发经验,可快速上手uni-app
。
相对开发者来说,减少了学习成本,因为只学会uni-app
之后,即可开发出iOS、Android、H5、以及各种小程序的应用,不需要再去学习开发其他应用的框架,相对公司而言,也大大减少了开发成本。
【uni-app
官网】:https://uniapp.dcloud.io/ 链接地址
二、环境搭建
- 安装编辑器HbuilderX 【网站】https://www.dcloud.io/hbuilderx.html 下载地址
- 安装微信开发者工具 【网站】https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html 下载地址
HBuilderX是通用的前端开发工具,但为uni-app
做了特别强化;下载App开发版,可开箱即用。
三、初始化项目
- 点击
HbuilderX
菜单栏文件>项目>新建 - 选择
uni-app
,填写项目名称,项目创建的目录
注意:这里创建的是个项目不是目录,目录后边用到;一个项目有很多目录。
随后可以运行,导航栏可以选择运行到不同的平台上,注意如果第一次运行到”微信小程序“需要配置微信小程序的路径;路径到启动项的上级文件夹。
3.1、介绍项目目录及作用
pages.json
文件用来对 uni-app 进行全局配置,决定页面文件的路径、窗口样式、原生的导航栏、底部的原生tabbar 等。
manifest.json
文件是应用的配置文件,用于指定应用的名称、图标、权限等。
App.vue
是我们的根组件,所有页面都是在App.vue
下进行切换的,是页面入口文件,可以调用应用的生命周期函数。
main.js
是我们的项目入口文件,主要作用是初始化vue
实例并使用需要的插件。
uni.scss
文件的用途是为了方便整体控制应用的风格。比如按钮颜色、边框风格,uni.scss
文件里预置了一批scss变量预置。
unpackage
就是打包目录,在这里有各个平台的打包文件。
pages
所有的页面存放目录。
static
静态资源目录,例如图片等。
components
组件存放目录。
3.2开发规范
为了实现多端兼容,综合考虑编译速度、运行性能等因素,uni-app
约定了如下开发规范:
- 页面文件遵循 Vue 单文件组件 (SFC) 规范
- 组件标签靠近小程序规范,详见uni-app 组件规范
- 接口能力(JS API)靠近微信小程序规范,但需将前缀
wx
替换为uni
,详见uni-app接口规范 - 数据绑定及事件处理同
Vue.js
规范,同时补充了App及页面的生命周期 - 为兼容多端运行,建议使用flex布局进行开发
3.3全局配置和页面配置
全局配置在pages.json
里边,3.1中提到的文件都可以在uni-app
官网查到很详细的文件配置项目和说明。
注意官网左侧的层次,就是写程序的层次。例如:
3.4创建新的message页面
右键pages
新建message
目录,在message
目录下右键新建vue
文件,并选择基本模板。
四、全局配置项目索引(基于课程)
pages.json
配置的项目:
- 页面的路径
path
;每在pages里新建的页面都要在这里进行路径的补充。 - 通过
style
修改页面的标题和导航栏背景色。 - 通过
globalStyle
来设置默认页面的窗口表现。 - 通过
tabBar
来配置底部导航栏。 - 通过
condition
启动模式配置(用户点击直达的页面,如转发什么的),仅开发者模式。
具体见uni-app官网-框架。
五、组件的使用索引(基于课程)
uni-app
提供了丰富的基础组件给开发者,开发者可以像搭积木一样,组合各种组件拼接称自己的应用。
详细见uni-app官网-组件。
5.1 text组件的使用:
<tempiate>
<view>
<view>
<text >来了老弟</text>
</view>
<view>
<text >来了老弟</text>
</view>
</view> <!-- 根组件 -->
</tempiate>
如果是一个view
中放两个text
的效果就是两个text
同行显示;放在两个view
中就是两行独占显示;并且两个view
需要一个根组件。
<view>
<text selectable='true'>来了老弟</text>
<!-- ture后边不用加分号 -->
<text selectable='true' space='ensp' style=font-size':30px;>来了 老弟</text>
<!-- 长按文本是否可选;中文字符空格一半大小;字符大小30px -->
</view>
5.2 view组件的使用
<template>
<view class="outbox" hover-class="outbox-active">
<view class="box" hover-class="box-active" hover-stop-propagation="true" hover-start-time="2000" hover-stay-time="2000">
我是一个盒子
</view>
</view> <!-- 绑定叫box的样式;按下去的样式;阻止父节点出现点击态;按住后多久出现点击态,单位毫秒;手指松开后点击态保留时间 -->
</template>
<style>
.box{
width: 100px;
height: 100px;
background: green;
}
.box-active{
width: 100px;
height: 100px;
background: red;
}
.outbox{
width: 200px;
height: 200px;
background: blue;
}
.outbox-active{
width: 200px;
height: 200px;
background: pink;
}
</style>
注意这里的两个view
是嵌套的,所以200* 200的区域是包裹住100* 100的区域的。
效果:100*100的绿色区域被 200 *200的蓝色区域包裹住,然后点击内层两秒后变成红色,再过两秒红色变回绿色,外层不变;点击外层同理。
5.3 button按钮
button
组件默认独占一行,设置 size
为 mini
时可以在一行显示多个。
<button size='mini' type='primary'>前端</button>
<button size='mini' type='default' disabled='true'>前端</button>
<button size='mini' type='warn' loading='true'>前端</button>
button组件后续还有介绍,很多接口。
5.4 image组件
插入图像的组件,image·
组件默认宽度 300px、高度 225px;app-nvue
平台,暂时默认为屏幕宽度.
src
可以支持线上网址;注意:线上的网址结尾是图片的格式,并不是网页,复制过来的应该是图片的地址!
<view>
<image src="../../static/121.jpg"></image>
</view>
<view>
<image src="https://scpic.chinaz.net/files/pic/pic9/202104/hpic3876.jpg"></image>
</view>
六、uni-app中的样式
6.1 rpx自适应单位
详见uni-app
官网-框架简介-页面布局与样式-尺寸单位
rpx
即响应式px
,一种根据屏幕宽度自适应的动态单位。以750宽的屏幕为基准,750rpx恰好为屏幕宽度。屏幕变宽,rpx 实际显示效果会等比放大;也可以用在文字上。
<template>
<view>
<view class="newbox">样式学习</view>
</view>
</template>
<style>
.newbox{
width: 375rpx;
height: 375rpx;
background: #FFC0CB;
color: #4CD964;
font-size: 50rpx;
}
</style>
这里的375就是750基准的一半,实际显示过程中根据屏幕尺寸显示屏幕的一半。
6.2 @import
使用@import
语句可以导入外联样式表,@import
后跟需要导入的外联样式表的相对路径,用;
表示语句结束。
<template>
<view>
<view>nishiwo</view>
<view class="newbox">样式学习</view>
<view>1213241</view>
</view>
</template>
<style>
@import url("./style.css");
.newbox{
width: 375rpx;
height: 750rpx;
background: #FFC0CB;
color: #4CD964;
font-size: 50rpx;
}
</style>
注意以上代码,除了“样式学习”绑定了class
样式,其他两行文字没有绑定,就全都用了css
文件的样式。
6.3 全局样式与局部样式
官网-介绍-框架简介-页面样式与布局-全局样式与局部样式
定义在App.vue
中的样式为全局样式,作用于每一个页面。在 pages
目录下 的vue
文件中定义的样式为局部样式,只作用在对应的页面,并会覆盖App.vue
中相同的选择器。
选择器种类可以看uni-app
官网-框架简介-页面布局与样式-选择器。
意思就是在app.vue
中写的.class
类会被页面中.vue
文件的.class
类覆盖掉;这里的class
类名要一样。
app.vue 中代码
<style>
.newbox{
background:blue ;
}
</style>
某一页面中的vue
<style>
.newbox{
width: 375rpx;
height: 750rpx;
background: #FFC0CB;
color: #4CD964;
font-size: 50rpx;
}
</style>
以上代码类名相同为newbox
,这时页面的会覆盖整体的;如果把页面中的background
注释掉,那么整体的蓝色background
会生效,并且页面中的newbox
类的其他属性一样生效!如果类名不同那么就无法覆盖。
app.vue
补充的是其他页面的相同类名中的相同设置项!可以理解为App.vue
是全部页面vue
文件的整体设置。
并且,在app.vue
中添加好的样式什么的,不在具体的页面上引用的话,也不会显示。它的作用就是先放在整体的vue
中之后就可以在各个页面vue
进行引用了。
6.4 字体图标的使用
官网-介绍-框架简介-页面样式与布局-字体图标
字体图标简单的说,就是一种特殊的字体,通过这种字体,显示给用户的就像一个个图片一样,字体图标最大的好处,在于它不会变形和加载速度快。字体图标可以像文字一样,随意通过CSS
来控制它的大小和颜色。
使用本地路径图标字体需注意:
为方便开发者,在字体文件小于 40kb 时,uni-app
会自动将其转化为 base64
格式;
字体文件大于等于 40kb,仍转换为 base64
方式使用的话可能有性能问题,如开发者必须使用,则需自己将其转换为 base64 格式使用,或将其挪到服务器上,从网络地址引用;
字体文件的引用路径推荐使用以 ~@ 开头的绝对路径。
使用方法:先把本地的字体图标文件添加到项目中,再更改字体图标的css
文件里边的路径为~@形式;然后可以在页面定义class
类别引用图标了。
<template>
<view>
<view class="iconfont icon-tupian"></view>
</view>
</template>
<style>
@import url("../../static/fontpicture/iconfont.css");
</style>
或者是在app.vue
中总体载入。
<style>
/*每个页面公共css */
@import url("./static/fontpicture/iconfont.css");
</style>
导入字体图标的文件进项目
iconfont
组件中的四个字体图标及名字。
6.5 使用scss全局变量
官网-介绍-框架简介-页面样式与布局-全局样式与局部样式
使用的是uni.scss
文件,uni.scss
文件的用途是为了方便整体控制应用的风格。比如按钮颜色、边框风格,uni.scss文件里预置了一批scss
变量预置。
在使用lang="scss"
之前要安装scss
插件;在工具中的插件安装。
页面的vue文件中
<template>
<view>
<view class="newbox">样式学习
<text>新学习</text>
</view>
<view>1213241</view>
</view>
</template>
<style lang="scss"> //这里引用scss全局样式文件
@import url("./style.css"); //这里是引用外部css样式
.newbox{
width: 375rpx;
height: 750rpx;
background: $uni-color-primary; //使用了预置的颜色变量
color: #4CD964;
font-size: 50rpx;
text{
color:pink; //注意这里的text是在newbox样式下的,可以单独给text设置样式
} //不单独设置text的颜色,默认使用的是color: #4CD964;
}
</style>
以上代码background
使用了uni.scss
的预置变量,颜色变量可在uni.scss
文件中查看。
6.6 数据绑定{{}}的用法
官网-介绍-vue教程-基础-模板语法-插值
<template>
<view>
<view> {{msg}} msg </view> <!-- Hello Vue msg -->
<view>数据的拼接:{{number+'我是你爸爸'}}</view> <!-- 1我是你爸爸 -->
<view>三目运算:{{flag?'我是真':'我是假'}}</view> <!-- 结果是 我是真 -->
<view>运算{{1+2}}</view> <!-- 结果为 3 -->
</view>
</template>
<script>
export default {
data() {
return {
msg: 'Hello Vue!',
flag:true,
number:1
}
}
}
</script>
{{msg}}里的内容将会被替代为对应数据对象上msg
的值。无论何时,绑定的数据对象上msg
发生了改变,插值处的内容都会更新。
6.7 v-bind v-for v-on指令
v-bind
:官网-介绍-vue教程-基础-模板语法-指令
v-for
:官网-介绍-vue教程-基础-列表渲染
v-on
:官网-介绍-vue教程-基础-模板语法-指令
6.7.1 v-bind指令
v-bind
是可以动态的绑定一个或者多个属性。
<template>
<view>
<image src="path"></image> <!-- v-bind:src="path" --> <!-- :src="path" -->
</view>
<script>
export default {
data() {
return {
path:"https://scpic.chinaz.net/files/pic/pic9/202104/hpic3876.jpg",
}
}
}
</script>
</template>
上述代码,显示的时候path
并不会被解析成网址,只是一个字符串;加上v-bind
才会被解析成网址。
v-bind
的缩写:
,以上注释的两种写法都可。
6.7.2 v-for指令
v-for
指令可以实现基于一个数组来渲染一个列表。
<template>
<view>
<view v-for="(item,index) in array">
默认索引:{{index}},姓名:{{item.name}},年龄:{{item.age}},序号:{{item.number}}
</view>
</view>
</template>
<script>
export default {
data() {
return {
array:[
{
name:"宋小宝",
age:"18",
number:1
},
{
name:"小沈阳",
age:22,
number:2
},
{
name:"赵四",
age:33,
number:3
}
]
}
}
}
</script>
以上item
就是对象,item in array
指的是数组中的对象。效果如下图所示:
6.7.3 v-on指令
v-on 指令,它用于监听 DOM 事件。v-on缩写为‘ @ ’,下文简称为 @事件
<template>
<view>
<button @click="clickhandle(25,$event)">我是个绑定了点击事件的按钮</button>
</view>
</template>
<script>
export default {
data() {
return {
}
},
methods:{
clickhandle(number,e){
console.log('点击我了',number,e)
}
}
}
</script>
console.log
是打印的意思,在页面的调试中可以看到。以上代码用v-on
指令为按钮绑定了点击事件,同时此事件clickhandle
传回参数,一个是25
,另一个是 事件对象
七、生命周期
官网-框架-框架接口-生命周期
生命周期的概念:一个对象从创建、运行、销毁的整个过程被成为生命周期。
生命周期函数:在生命周期中每个阶段会伴随着每一个函数的触发,这些函数被称为生命周期函数
生命周期分app的和页面的,app的在App.vue中设置,页面的在页面vue中设置。
<script>
export default {
onLaunch: function() {
console.log('App Launch')
},
onShow: function() {
console.log('App Show')
},
onHide: function() {
console.log('App Hide')
}
}
</script>
八、下拉刷新
uni官网-API-界面-下拉刷新
曾经在pages.json
中的globalStyle
定义过"enablePullDownRefresh":true
,这是全局的所有页面都可以进行下拉的刷新。
在uni-app
中有两种方式开启下拉刷新
- 需要在
pages.json
里,找到的当前页面的pages
节点,并在style
选项中开启enablePullDownRefresh
,页面的下拉刷新 - 通过调用
uni.startPullDownRefresh
方法来开启下拉刷新
onPullDownRefresh
:在 js 中定义 onPullDownRefresh 处理函数(和onLoad
等生命周期函数同级),监听该页面用户下拉刷新事件。
uni.startPullDownRefresh(OBJECT)
:开始下拉刷新,调用后触发下拉刷新动画,效果与用户手动下拉刷新一致。
uni.stopPullDownRefresh()
:停止当前页面下拉刷新。
<template>
<view>
<view v-for="item in array">
{{item}}
</view>
<button @click="refresh">刷新按钮</button>
</view>
</template>
<script>
export default{
data(){
return {
array:['1','2','3','4','1','2','3','4']
}
},
onPullDownRefresh() {
console.log('监听到下拉刷新了'),
setTimeout( ()=>{
this.array = ['4','3','2','1'],
uni.stopPullDownRefresh()},2000
)
},
methods:{
refresh(){
uni.startPullDownRefresh()
}
}
}
</script>
<style>
</style>
注意上述延时函数的写法:
setTimeout( ()=>{ },2000
)
上述代码实现的效果:
8.2上拉加载
官网-框架-框架接口-生命周期
<template>
<view>
<view class="ibox" v-for="item in array">
{{item}}
</view>
</view>
</template>
<script>
export default{
data(){
return {
array:['1','2','3','4','1','2','3','4']
}
},
onReachBottom() {
console.log("触底了"),
this.array = [...this.array,...['45','99','77','96']] <!-- 加载的数组就是原数组的基础上新加的 -->
},
}
</script>
<style>
.ibox{
height: 100px;
line-height: 600px;
}
</style>
九、发起网络请求
官网-API-网络-发起请求
本地请求步骤:
- 打开phpstudy启动
- 在D:\SKK\uniapp黑马教程\uniapp\素材\heima_shop_server 路径下启动windows powershell
- 运行node ./src/app.js
- 得到地址
- 在浏览器输入地址 localhost:8082/api/getlunbo
<template>
<view>
<button @click="get">发送get请求</button>
<view class="ibox" v-for="item in array">
{{item}}
</view>
</view>
</template>
<script>
methods:{
get(){
uni.request({
url:"http://localhost:8082/api/getlunbo",
success(rrr) {
console.log(rrr)
}
})
}
}
}
</script>
十、数据缓存
官网-API-数据缓存
<template>
<view>
<button @click="set">存储数据</button>
<button @click="getdata">获取数据</button>
<button @click="remove">删除数据</button>
</view>
</template>
<script>
export default{
methods:{
set(){
uni.setStorage({
key:"id",
data:100
}) <!-- uni.setStorageSync("id",100)-->
},
getdata(){
uni.getStorage({
key:"id",
success(ew){
console.log(ew.data)
}
})
},
remove(){
uni.removeStorage({
key:"id",
success() {
console.log('删除成功')
}
})
}
}
}
</script>
一般用同步的更简略:uni.setStorageSync(KEY,DATA)
十一、图片上传及预览
uni-api-媒体-图片
思路:图片的上传利用uni.chooseImage
函数,并且返回一个图片的地址数组,我们用个空的数组去接收这个地址数组,然后利用image
组件进行动态显示出来,最后预览用uni.previewImage
函数,注意预览的是点击的那个图片,那么应该在点击事件发生时传回一个参数,这个参数就是点击的图片的地址。
<template>
<view>
<button @click="setup">图片上传</button>
<image :src="item" v-for="item in array" @click="preview(item)"></image>
</view> <!-- 注意这里是动态的绑定地址,冒号 --> <!-- 点击时传回一个当前点击的图片的地址的参数 -->
</template>
<script>
export default{
data(){
return{
array:[] /* 准备一个空数组进行保存图片地址数组 */
}
},
methods:{
setup(){
uni.chooseImage({
count:5,
success:res=>{
this.array = res.tempFilePaths /* 注意这个数组更新的写法 */
}
})
},
preview(current){ /* 这里预览的是点击的图片,需要点击的时候传递回来图片的地址 */
uni.previewImage({
current:'current', /* 键名和值一样,可以简写成 current, */
urls:this.array /* 这个是预览的图片组的地址,可以在预览的时候滑动预览其他图片 */
})
}
}
}
</script>
<style>
</style>
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210503151633422.gif
十二、差别编译,页面的跳转及参数传递
差别编译
uni-介绍-条件编译
条件编译是用特殊的注释作为标记,在编译时根据这些特殊的注释,将注释里面的代码编译到不同平台。
写法:以 #ifdef 或 #ifndef 加 %PLATFORM% 开头,以 #endif 结尾。
- #ifdef:if defined 仅在某平台存在
- #ifndef:if not defined 除了某平台均存在
- %PLATFORM%:平台名称
页面跳转
页面的跳转分两种方式:一是用组件的方式navigator
,二是用API函数跳转。
- uni-组件-页面路由与跳转-navigator
- uni-API-路由与页面跳转
注意,组件一般都是在template
结构体里边写,api
函数在script
里边写
<template>
<view>
<navigator url="../list/list?id=你好&age=23">跳转至普通页面</navigator><!-- 不关闭页面,可以返回 -->
<navigator url="../list/list" open-type="redirect">跳转至普通页面</navigator><!-- 关闭页面 -->
<navigator url="../index/index" open-type="switchTab">跳转到tablebar页面</navigator>
<!-- 跳转的页面区分类型,需要设置打开的类型 -->
<button @click="jump">跳转至普通页面</button>
<button @click="jump1">跳转到tablebar页面</button>
</view>
</template>
<script>
export default{
methods:{
jump(){
uni.navigateTo({
url:"../list/list"
})
},
jump1(){
uni.switchTab({
url:"../index/index"
})
}
}
}
</script>
<style>
</style>
list页面
<script>
export default{
onLoad(data) {
console.log(data)
}
}
数据的传递在url
地址后边加上?
引导即可,多数据用&
并列,参数的接收在跳转的页面内用onload
接收,页面生命周期里边的函数。
十三、组件的创建使用和组件的生命周期函数
uni-组件-组件概述
uni-框架-框架接口-生命周期-组件生命周期
只要组件安装在项目的components
目录下或uni_modules
目录下,并符合components/组件名称/组件名称.vue目录结构。就可以不用引用、注册,直接在页面中使用。例如 /components/uni-rate/uni-rate.vue
如果不使用easycom
,手动引用和注册vue
组件,则需要分3步写如下代码:
import
导入组件script
下import newtext from'../../components/newtext.vue'
components
里注册组件script
下的export default
下components: { newtext:newtext }
template
中使用组件
可以利用组件生命周期函数进行数据初始化获取数据等操作。
<script>
export default{
created() {
console.log('nimei')
},
data(){
return{
flag:true
}
},
</script>
十四、组件之间的参数传递
14.1 父组件向子组件传值
传数据通过属性绑定传递,接收通过props
接收。
以下的例子,jump
中引用了newtext
组件,所以前者为父组件后者为子组件。
在父组件中绑定一个属性,动态绑定才能解析成值,非字符串。
<template>
<view>
<newtext v-if="flag" :data221="data1"></newtext>
</template>
在子组件中用props
接收到,并且能在父组件显示出来,data1=555。
<template>
<view>
zheshinewtext{{data221}}
</view>
</template>
<script>
export default {
name:"newtext",
data() {
return {
};
},
props:['data221']
}
</script>
14.2 子组件向父组件传值
通过注册自定义事件实现。
uni-框架-框架接口-页面通讯
在子组件中定义一个事件叫myeven
<template>
<view>
zheshinewtext{{data221}}
<button @click="sendnum">给父组件传值</button>
</view>
</template>
<script>
export default {
name:"newtext",
data() {
return {
num:30
};
},
props:['data221'],
methods:{
sendnum(){
this.$emit('myeven',this.num)
}
}
}
</script>
在父组件中调用的子组件上绑定这个自定义事件并且调用的函数,定义函数体并且显示,实现点击按钮一次就将子组件传过来的值进行相加运算。
<template>
<view>
{{num}}
<newtext v-if="flag" :data221="data1" @myeven="getnum"></newtext> <!-- 绑定这个自定义事件和对应函数 -->
</view>
</template>
<script>
import newtext from'../../components/newtext.vue'
export default{
data(){
return{
flag:true,
data1:555,
num:0 /* 初始化值 */
}
},
methods:{
getnum(num){
this.num+=num /* 由子组件传过来的加和 */
}
},
components:{
newtext:newtext
}
}
</script>
14.3 兄弟组件之间传值
通过a1给b1组件改值
a1组件:
<template>
<view>
<button @click="change">修改b组件的数据</button>
</view>
</template>
<script>
export default {
name:"a1",
data() {
return {
};
},
methods:{
change(){
uni.$emit('xxx',20)
}
}
}
</script>
b1组件:
<template>
<view>
b组件的数据是{{num}}
</view>
</template>
<script>
export default {
name:"b1",
data() {
return {
num:0
};
},
created() {
uni.$on('xxx',num=>{this.num+=num})
}
}
</script>
如果按钮中的文字太长会导致按钮不显示,并且保存编译要每个文件都保存才可以,在某个文件保存,其余文件不执行保存的操作。