一.搭建环境
安装编辑器HBuilderX,他是通用的前端开发工具
- 我下载的是windows版的app开发版
安装微信开发者工具(默认,安装地址:C:\Program Files(x86)\Tencent\微信web开发者工具\) - 我下载的是稳定版 Stable Build的windows64
安装微信开发者工具链接
二.创建项目
文件->新建->项目->选择uni-app,输入项目名称,点击创建
运行在网页上:运行->运行到浏览器->chrome
运行到小程序:运行->运行到小程序模拟器->微信开发者工具
第一次运行小程序配置:
①需要在输入框输入微信开发者工具的安装路径
②微信开发者工具:设置->安全设置->服务端口:设为开启
四.修改全局的样式
在uni-app的官网上全局搜索globalStyle;或者在官网上的框架里面可以找到api
然后在package.json里面的globalStyle修改样式配置
"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
{
"path": "pages/index/index",
"style":{//这里单独设置某个有的样式
"navigationBarBackgroundColor":"#007AFF",
"h5":{
"pullToRefresh":{
"color":"#007AFF"
}
}
}
},
{
"path": "pages/message/message"
},
{
"path": "pages/contact/contact"
},
{
"path": "pages/detail/detail"
}
],
"globalStyle": {//这里是全局路由样式设置
"navigationBarTextStyle": "black",
"navigationBarTitleText": "uni-app系统",
"navigationBarBackgroundColor": "#ffaaff",
"backgroundColor": "#00aa00",
"enablePullDownRefresh":true,
"backgroundTextStyle":"light"
},
五.创建页面和配置路由
新建文件夹(目录)->新建.vue文件
想让他显示在页面显示,需要在pack.json的pages里面配置文件路径,style可设置独有样式;还可以在pack.json里面配置路由和路由的图标。
在package.json里面的pages里面引入路由的路径,然后在下面的tarBars里面配置路由,路由名称和对应的图标
"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
{
"path": "pages/index/index",
"style":{
"navigationBarBackgroundColor":"#007AFF",
"h5":{
"pullToRefresh":{
"color":"#007AFF"
}
}
}
},
{
"path": "pages/message/message"
},
{
"path": "pages/contact/contact"
},
{
"path": "pages/detail/detail"
}
],
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "uni-app系统",
"navigationBarBackgroundColor": "#ffaaff",
"backgroundColor": "#00aa00",
"enablePullDownRefresh":true,
"backgroundTextStyle":"light"
},
"tabBar":{
"color":"#000000",//路由字体的颜色
"selectedColor":"#ff0000",//路由字体点击高亮的颜色
"list":[
{
"text":"首页",
"pagePath":"pages/index/index",
"iconPath":"static/images/car.png",
"selectedIconPath":"static/images/car_active.png"
},
{
"text":"信息",
"pagePath":"pages/message/message",
"iconPath":"static/images/fly.png",
"selectedIconPath":"static/images/fly_active.png"
},
{
"text":"我的",
"pagePath":"pages/contact/contact",
"iconPath":"static/images/people.png",
"selectedIconPath":"static/images/people_active.png"
}
]
},
六.启动模式配置
在package.json里面进行配置,也即是非路由的页面跳转,通过condition属性配置
还是在package.json里面配置一个condition属性,配置非路由的页面
"condition":{
"current":0,
"list":[
{
"name":"详情页",
"path":"pages/detail/detail",
"query":"id=90"
}
]
}
在这里点击下拉才能找到对应的页面,如果没有这个下拉属性,可能需要重启
七.组件的基本使用
1.text组件
相当于div的text
<template>
<view>
<view>
<text>我是主页</text>
</view>
<view>
<text selectable="true">我是主页</text>
</view>
<view>
<text space="emsp">我是 主页</text>
</view>
<view>
<text space="ensp">我是 主页</text>
</view>
<view>
<text space="nbsp">我是 主页</text>
</view>
</view>
</template>
2.view组件
类似于传统的div
- hover-class按下去的样式
- hover-stop-propagation点击儿子的时候,阻止爸爸也会改变(组织冒泡)
- hover-start-time延迟出现效果
- hover-stay-time手松开延迟多久保留效果
<template>
<view>
<text>我是信息页</text>
<view class="boxFather" hover-class="boxFather-active">
<view class="box" :hover-start-time="2000" :hover-stay-time="2000" hover-class="box-active" hover-stop-propagation>我是一个大盒子</view>
</view>
</view>
</template>
<script>
</script>
<style>
.box{
width: 100px;
height: 100px;
background: #007AFF;
}
.boxFather{
width: 200px;
height: 200px;
background: #DD524D;
}
.box-active{
background: #4CD964;
}
.boxFather-active{
background: #fff3a9;
}
</style>
3.image组件
<img src="https://timgsa.baidu.com/src=http%3A%2F%2Fs9.sinaimg.cn%2Fbmiddle%2F5ceba31bg5d6503750788" alt="">
<img src="https://timgsa.baidu.com/src=http%3A%2F%2Fs9.sinaimg.cn%2Fbmiddle%2F5ceba31bg5d6503750788" alt="" mode="scaleToFill">
<img src="https://timgsa.baidu.com/src=http%3A%2F%2Fs9.sinaimg.cn%2Fbmiddle%2F5ceba31bg5d6503750788" alt="" mode="aspectFit">
图片有默认宽高: 组件默认宽度 300px、高度 225px
4.rpx尺寸单位
rpx是微信小程序中css的尺寸单位,可以根据屏幕宽度进行自适配。
规定屏幕宽度为750px,譬如iphone6,屏幕宽度为375px,共有750个物理像素,则1rpx = 0.5px。
uni-app 支持的通用 css 单位包括 px、rpx。
rpx 即响应式px,一种根据屏幕宽度自适应的动态单位。以750宽的屏幕为基准,750rpx恰好为屏幕宽度。屏幕变宽,rpx 实际显示效果会等比放大,但在 App 端和 H5 端屏幕宽度达到 960px 时,默认将按照 375px 的屏幕宽度进行计算
<template>
<view>
<view class="box"></view>
<view class="littleBox">
</view>
</view>
</template>
<script>
</script>
<style>
.box{
width: 750rpx;
height: 750rpx;
background: pink;
}
.littleBox{
width: 370rpx;
height: 370rpx;
background: blue;
}
</style>
在pages文件夹下创建一个新的文件夹uni-style,然后在里面创建一个文件uni-style.vue
5.uni-app的样式注意:
①page相当于body节点
②在uni-app中不能使用*选择器
③使用@import语句可以导入外联样式表,后面跟相对路径,用;表示结束语句
@import url("./a.css");
④定义在App.vue的样式是全局样式,作用域每一个页面,作用域其他.vue的组件的样式是局部样式,只作用于对应页面
⑤字体图表的引入
1)在阿里巴巴矢量图标库下载code,然后把文件都拷贝到static的fonts文件夹里面
2)在App.vue(或者其他.vue)组件引入iconfont.css
3)字体文件的引用路径推荐使用以 ~@ 开头的绝对路径,修改路径,加上~@/static/fonts
4)页面写字体图标
<template>
<view>
<view class="iconfont icon-ertongpiao"></view>
</view>
</template>
⑥引入sass
工具->插件安装->找到sass,点击安装->然后在浏览器登录安装sass
八.生命周期
网站Api->界面->下拉刷新
1.应用生命周期
应用生命周期仅可在App.vue中监听,在其它页面监听无效
2.页面生命周期
- onLoad 监听页面加载(仅一次)
- onShow 监听页面显示。页面每次出现在屏幕上都触发
- onReady 监听页面初次渲染完成(仅一次)
- onHide 监听页面隐藏。页面每次隐藏都触发
<template>
<view>
<view class="iconfont icon-ertongpiao"></view>
<view class="boxFather">
456
<view class="box">123</view>
</view>
</view>
</template>
<script>
export default{
data(){
return{
}
},
onLoad() {
console.log("页面加载了")
},
onShow() {
console.log("页面显示了")
},
onReady() {
console.log("页面初次渲染完了")
},
onHide() {
console.log("页面隐藏的")
}
}
</script>
<style lang="scss">
.boxFather{
color: green;
.box{
color: red;
}
}
.box{
width: 750rpx;
height: 750rpx;
background: pink;
}
.littleBox{
width: 370rpx;
height: 370rpx;
background: blue;
}
</style>
- onPullDownRefresh 下拉刷新触发
之前在package.json里面的globalStyle里面设置“enablePullDownRefresh”:true,这是开启全局,一般不推荐这样。我们希望是哪个页面需要下拉刷新就给那个页面开启。
1)首先在package.json里面的pages进行配置:
pages:[
{
"path": "pages/message/message",
"style":{
"enablePullDownRefresh":true
}
},
]
2)然后在需要的页面触发下拉更新
下来的方法有两种:
①一种是手动下拉的时候,自动触发onPullDownRefresh生命周期,然后在这个方法里面要结束loading的话,就用uni.stopPullDownRefresh()
②第二种就是button触发指定函数,函数里面触发uni.startPullDownRefresh()。这样也会自动触发onPullDownRefresh生命周期里的方法
<template>
<view>
<view class="content">
<view v-for="(item,index) in list" :key="index">{{item}}</view>
</view>
<button type="primary" @click="refreshBtn">按钮</button>
</view>
</template>
<script>
export default{
data(){
return {
list:["前端","JAVA","大数据","数据库"]
}
},
methods:{
/* 触发这个方法就会自动触发下面的onPullDownRefresh生命周期 */
refresh(){
uni.startPullDownRefresh()
}
},
onPullDownRefresh() {
setTimeout(()=>{
this.list.push("123")
uni.stopPullDownRefresh()
},1000)
}
}
</script>
- onReachBottom监听页面滚动到底部的事件,用于下拉下一页数据
1)距离底部多少就出发这个事件是可以设置的,在package,json里面
{
"path": "pages/message/message",
"style":{
"enablePullDownRefresh":true,
"onReachBottomDistance":100
}
},
2)在需要的页面直接写onReachBottom生命周期
onReachBottom() {
this.list.push("8888")
}
九.异步请求uni.request
Api->网络->发送请求
<template>
<view>
<button type="primary" @click="get">发送get请求</button>
</view>
</template>
<script>
export default{
data(){
return {
}
},
methods:{
get(){
uni.request({
url:"http://www.baidu.com",
success: (res) => {
console.log(res)
}
})
}
},
}
</script>
十.数据缓存
Api->数据缓存
1.异步接口
将数据存储在本地缓存中指定的 key 中,会覆盖掉原来该 key 对应的内容,这是一个异步接口。
存数据:uni.setStorage()
取数据:uni.getStorage()
删数据:uni.removeStorage()
<template>
<view>
<button type="primary" @click="setStorage">存数据</button>
<button type="primary" @click="getStorage">取数据</button>
<button type="primary" @click="removerStorage">删数据</button>
</view>
</template>
<script>
export default{
data(){
return {
}
},
methods:{
setStorage(){
uni.setStorage({
key:"id",
data:80,
success: () => {
console.log("我存好了")
}
})
},
getStorage(){
uni.getStorage({
key:"id",
success: (res) => {
console.log(res)
}
})
},
removerStorage(){
uni.removeStorage({
key:"id",
success: () => {
console.log("我把它删了")
}
})
}
},
}
</script>
小程序里面查看缓存在Storage里面:
控制台:
2.同步
存数据:uni.setStorageSync()
取数据:uni.getStorageSync()
删数据:uni.removeStorageSync()
<template>
<view>
<button type="primary" @click="setStorage">存数据</button>
<button type="primary" @click="getStorage">取数据</button>
<button type="primary" @click="removerStorage">删数据</button>
</view>
</template>
<script>
export default{
data(){
return {
}
},
methods:{
setStorage(){
uni.setStorageSync("id",666)
},
getStorage(){
var res=uni.getStorageSync("id");
console.log(res)
},
removerStorage(){
uni.removeStorageSync("id")
}
}
}
</script>
十一.图片的上传和预览
Api->媒体->图片
数据存在data里面,在小程序的appData中可以看到
<template>
<view>
<button type="primary" @click="chooseImg">上传图片</button>
<view>
<img v-for="item in picList" :src="item" @click="previewImg(item)" alt="">
</view>
</view>
</template>
<script>
export default{
data(){
return {
picList:[]
}
},
methods:{
/* 上传图片 */
chooseImg(){
uni.chooseImage({
count:8,
success: (res) => {
this.picList=res.tempFilePaths;
}
})
},
/* 放大图片轮播翻看 */
previewImg(item){
uni.previewImage({
current:item,//当前的图片路径
urls:this.picList//所有的图片路径
})
}
}
}
</script>
十二.条件注释,实现跨端兼容
介绍->条件编译 解决各端兼容问题 ->跨端兼容
<template>
<view class="contact">
<!-- #ifdef H5 -->
<view>我希望在H5中看见</view>
<!-- #endif -->
<!-- #ifdef MP-WEIXIN -->
<view>我希望在小程序中看见</view>
<!-- #endif -->
<view class="text">我是一只黄焖鸡</view>
</view>
</template>
<script>
export default{
onLoad (){
/* #ifdef H5 */
console.log("我希望在H5中看见")
/* #endif */
/* #ifdef MP-WEIXIN */
console.log("我希望在小程序中看见")
/* #endif */
}
}
</script>
<style lang="scss">
/* #ifdef H5 */
.text{
color: red;
}
/* #endif */
/* #ifdef MP-WEIXIN */
.text{
color: green;
}
/* #endif */
</style>
十三.uni中的导航跳转
1.声明式导航
组件->导航->navigator
navigator:只能跳转到普通页面(也就是非导航页面)
如果要跳转到tabbar页面,需要设置open-type=“switchTab”
<template>
<view class="contact">
<!-- 有返回上一页的箭头 -->
<navigator url="../details/details?id=80&age=18">跳转到详情页</navigator>
<!-- 没有返回上一页的箭头,上一页的文件被卸载了 -->
<navigator url="../details/details" open-type="redirect">跳转到详情页</navigator>
<navigator url="../message/message" open-type="switchTab">跳转到信息页</navigator>
</view>
</template>
<script>
export default{
onUnload() {
console.log("文件被卸载了")
}
}
</script>
<style lang="scss">
</style>
点击第一个按钮:
点击第二个按钮:
点击第三个按钮:
想这种跳转到的页面,接收参数就在onLoad生命周期里面:
onLoad(option) {
console.log(option)
}
2.编程式导航
Api->路由与页面跳转
<template>
<view>
<button @click="goDetail">跳转到详情页</button>
<button @click="redirectDetail">跳转到详情页</button>
<button @click="goMessage">跳转到信息页</button>
</view>
</template>
<script>
export default {
data() {
return {
}
},
methods: {
goDetail(){
uni.navigateTo({
url:"../details/details?id=8888888"
})
},
redirectDetail(){
uni.redirectTo({
url:"../details/details"
})
},
goMessage(){
uni.switchTab({
url:"../contact/contact"
})
}
}
}
</script>
第一个按钮:
第二个按钮:
第三个按钮:
十四.父子组件中子组件的生命周期
框架->框架接口->生命周期->组件生命周期
这里的组件指的是自组建的生命周期,一般子组件都创建在新建的文件夹components里面
son.vue:
<template>
<view>
<view id="son">
我是儿子
</view>
</view>
</template>
<script>
export default {
data() {
return {
num:88,
init:null
}
},
beforeCreate(){
console.log("beforeCreate",this.num)
console.log("实例刚刚实例化了")
},
created() {
console.log("created",this.num)
console.log("实例刚刚创建")
this.init=setInterval(()=>{
console.log("执行定时器")
},1000)
},
beforeMount() {
console.log("挂在开始之前")
console.log("beforeMount",document.getElementById("son"))//只有H5才能执行
},
mounted() {
console.log("刚刚挂载到实例")
console.log("mounted",document.getElementById("son"))//只有H5才能执行
},
destroyed() {
console.log("组件销毁了")
clearInterval(this.init)
},
methods: {
}
}
</script>
<style>
</style>
index.vue:
<template>
<view>
<Son v-if="isShow"></Son>
<button type="primary" @click="isShowBtn">按钮</button>
</view>
</template>
<script>
import Son from '../../components/son/son.vue'
export default {
data() {
return {
isShow:true
}
},
components:{Son},
methods: {
isShowBtn(){
this.isShow=false;
}
}
}
</script>
<style>
</style>
十五.父子组件之间的通讯方式
1.父传子
父组件传值冒号绑定,子组件props接受
2.子传父
$emit传值,@接受
父亲的组件:
<template>
<view>
<view>我是爸爸</view>
<Son v-if="isShow" :message="text" @loveBack="loveBack"></Son>
</view>
</template>
<script>
import Son from '../../components/son/son.vue'
export default {
data() {
return {
isShow:true,
text:"我是爸爸哦,爱你!"
}
},
components:{Son},
methods:{
loveBack(params){
console.log(params)
}
}
}
</script>
<style>
</style>
儿子的组件:
<template>
<view class="son">
<view@click="loveBack">
我是儿子
</view>
<view>"爸爸传过来的值:"{{message}}</view>
</view>
</template>
<script>
export default {
data() {
return {
text:"我也爱你,爸比!"
}
},
props:["message"],
methods: {
loveBack(){
this.$emit("loveBack",this.text)
}
}
}
</script>
<style>
.son{
width: 750rpx;
height: 200rpx;
background: pink;
}
</style>
3.兄弟组件之间的传值
这两个兄弟组件都是并列的子组件,如a组件和b组件。a组件uni.emit触发全局自定义事件
父组件:
<template>
<view>
<view>我是爸爸</view>
<A_son></A_son>
<B_son></B_son>
</view>
</template>
<script>
import A_son from '../../components/a/a.vue'
import B_son from '../../components/b/b.vue'
export default {
data() {
return {
}
},
components:{A_son,B_son}
}
</script>
<style>
</style>
a组件:
<template>
<view>
这是a组件:
<button type="primary" @click="addNum">修改b</button>
</view>
</template>
<script>
export default {
methods: {
addNum(){
uni.$emit("updateNum",10)
}
}
}
</script>
<style>
</style>
b组件:
<template>
<view>
这是组件B的数据:{{num}}
</view>
</template>
<script>
export default {
data() {
return {
num:0
}
},
created() {
uni.$on("updateNum",num=>{
this.num+=num
})
}
}
</script>
<style>
</style>
十六.下载且引入扩展组件
组件->扩展组件->uni-ui整体介绍
uni-ui不包括基础组件,他是基础组件的补充。那我们使用这些组件时这样操作。
步骤:
1.下载插件,导入成功
components里面就会多一组相关组件
2.根据官网提示,import引入组件,components挂载组件,页面上使用组件
如:
十七.黑马商城项目
1.onShow()只要页面隐藏,再次出现,就会触发这个生命周期
onReady()监听的时候页面以及渲染完成了
所以一般进入页面获取数据是onLoad()
2.发送网络请求
官网API->网络->发送请求->uni.request
请求成功渲染数据,失败给提示
3.提示怎么做
官网APi->界面->交互反馈
if(res.data.data!==0){
return uni.showToast({
title:"获取数据失败!"
})
}
4.对数据请求最好进行二次封装
在根目录下创建一个文件夹util下创建一个app.js,在这里面封装请求的方法:
const BASE_URL="http://localhost:8082"
export const myRequest=(option)=>{
return new Promise(()=>{
uni.request({
url:BASE_URL+option.url,
method:option.method || "GET",
success:(res)=>{
if(res.data.status!==0){
return uni.showToast({
title:"获取数据失败!"
})
}
resolve(res)
},
fail:((err)=>{
return uni.showToast({
title:"接口请求失败!"
})
reject(err)
})
})
})
}
然后在mian.js上挂载到全局:
import (myRequest) from “util/api.js”
Vue.prototype.$myRequest=myRequest
5.做轮播图
官网组件->视图容器->swiper
轮播图的宽度需要占据一整屏就是750rpx。
真正开发的时候建议设计人员的设计稿是以375的2倍图(也就是iphone6)进行设计。因为以375的2倍图,那么他的宽度就是750px,而占满屏也是750rpx。同理,如果是满屏的一般在设计上就是375rpx,用rpx表示就是375rpx.所以,如果设计人员是以375的2倍图做的设计稿,那么我们可以直接把px转换成rpx。
也就是说我们在375的屏幕上开发,但整屏是750rpx,那么后面的单位和字体为px的,我们都可以把他转换为2倍,如:12px的字体->24rpx,某view的宽是200px,就是400rpx。
轮播图的屏需要占满屏,高度呀自动适应,不变性就要这样写:
swiper{
width:750rpx;
height:750rpx*277/700;
img{
width:100%;
height:100%
}
}
6.发现黑马超市的背景色在项目中用到的次数比较多,所以可以在uni.scss里面定义一个变量
/* 颜色变量 */
$shop-color:#b50e03;
在页面可以直接使用
background:$shop-color;
7.上拉加载更多和下拉刷新
api->界面->下拉刷新 上拉加载更多事件
上拉加载更多:触发的是onReachBottom生命周期
下拉刷新:出发的是onPullDownRefresh生命周期
8.拨打电话
api->设备->拨打电话
9.左侧便可滚动
组件->视图容器->scroll-view
要想高度占整屏高度,需要先把page{height:100%}
10.图片预览
api->媒体->图片->uni.previewImage
11.年月日的转换
年/月/日的数值 toString().padStart(2,0)
第一个参数表示几位数值,没有这几位数值就在前面加第二个参数,这里是0
12.过滤
uni-app的过滤不是computed而是filter
13.新建页面
这样就把文件夹,文件都创建好了,package.json里面的偶引入好了
14.子级传值给父级,接收参数
父级直接在方法里面拿值,template里面不能写
15.跳转页面传值,在下一个页面可以在onLoad生命周期函数里面取到值
16.很多地方需要用到的js,在main,js里面全局过滤
Vue.filter("formatData",(data)=>{
const nData=new Date(data)
const year=new Date(data)
const month=new Date(data).toString().padStart(2,0)
const day=nData.getDay().toString().padStart(2,0)
return year+'-'+month+'-'+day
})
后面用的话就是
{{ day || formatData }}
17.小程序中解析html用ritch-text
18.黑马超市的商品列表和推荐商品的列表公共一个组件,点击他们的生活都要跳转到商品详情页。
商品详情页的组件触发方法,通过$emit把id分别传给商品列表的父组件,然后在父组件进行跳转页面的方法。
19.ritch-text里面的image图片大小设置不了的时候,可以试着在全局改一下看看
在App.vue里面修改图片类的样式
.goImageLoad{
width:750rpx;
height:auto
}
20.商品导航
组件->扩展组件->商品导航
21.微信小程序的打包
直接点击上传即可,但这个无法点击,是因为在manifest.json里面的小城配置里面没有AppID。
填这个需要注册一个小程序,如何注册呢?
①百度搜索“微信公众平台”,进入官网
②点击立即注册,注册微信小程序,然后完善信息,注册完就登录。
③登陆进来以后->开发->开发设置->找到“AppID”,把他赋值过来,粘贴到微信小程序的工具里面
22.微信小城上线的话,要把util下的api.js里的BASE_URL改为服务器的地址,并且把这个地址的域名配置到上面的官网的“服务器域名”里面
点击修改->修改之后再用微信扫一下,然后在这个里面配置上线的域名
23.点击上传->确定->输入版本号和项目备注->点击上传
提示:字体图标如果没有被打包上传,那我们就把这个字体文件上传到码云或者git上,变成线上字体文字
然后再重新起疑心小程序,再查看下有没有问题,再重新上传。上传成功以后回到“微信公众平台”的首页看看有没有,如果有就上传成功了。“管理”的“版本管理”里面应该就有之前上传的版本,但现在在个人的账号里面,还没有上线,如果想上线,需要点击“审核”->后面下一步下一步类似的就可以了。
24.H5打包
打包之前在manifest.json的H5配置进行配置(页面标题和路由模式hash要配置)
打包:发行->“网站-H5受经济版(仅适用于uni-app)”
点击发布以后,网站域名可以先不写,点击“发行”就打包了。
25.安卓打包
1)manifest.json的配置:
manifest.json的基础配置里面->获取应用标识,名称,版本
manifest.json的App图标配置:浏览选择图片->自动生成图表并替换
manifest.json的App启动图:浏览选择图片(就是进入App的时候的图片)
manifest.json的App SDK配置和App模块权限配置:用了什么就把勾上
2)配置好了就打包
发行->原生App云打包->打印->然后就在打包,打包完了就会返回一个下载地址
3)百度搜索“草料二维码生成器”,把下载地址粘贴进去,生成一个二维码。然后用手机扫这个二维码就可以下载这个App了。