小程序
wx:for
- 在小程序中遍历时用 wx:for ;
- 可遍历数组,也可遍历对象,一下实例中遍历对象
<view>
<view wx:for="{{person}}" wx:key="{{index}}" wx:for-index="key">
{{key}}:{{item}}
// name:"Array",
// height:180cm
</view>
</view>
// js文件
page({
data:{
person:{
name:"Array",
height:180cm
}
}
})
WXSS
- WXSS是一套样式语言,用于描述 WXML 的组件样式
尺寸单位
- rpx :可以根据屏幕宽度进行自适应。规定屏幕宽为 750px
- 1 rpx = 0.5px = 1 物理像素
内联样式
style
<view style="color:{{color}}"></view>
class
<view class="normal_class"></view>
组件(navigator)
<!-- 保留当前也页面,跳转到应用内的某个页面,但是不能跳到 tabBar 页面 -->
<navigator url="../index/index" open-type="navigate">跳转</navigator>
uni-App
全局配置和页面配置
脚手架
-
全局安装
npm install -g @vue/cli
-
创建项目
vue create -p dcloudio/uni-preset-vue my-project
-
安装依赖 sass 依赖
npm install sass-loader node-sass
-
启动项目(微信小程序)
npm run dev:mp-weixin
-
微信小程序开发者工具导入项目
-
版本不一致问题
- 解决:重新安装对应的 vue 版本即可:
npm install vue@2.6.10
项目结构介绍
通过globalStyle进行全局配置
用于设置应用的状态栏、导航条、标题、窗口背景色
属性 | 类型 | 默认值 | 描述 |
---|---|---|---|
navigationBarBackgroundColor | HexColor | #F7F7F7 | 导航栏背景颜色(同状态栏背景色) |
navigationBarTextStyle | String | white | 导航栏标题颜色及状态栏前景颜色,仅支持black / white |
navigationBarTitleText | String | 导航栏标题文字内容 | |
backgroundColor | HexColor | #ffffff | 窗口的背景色 |
backgroundTextStyle | String | dark | 下拉loading的样式,仅支持dark / light |
enablePullDownRefresh | Boolean | false | 是否开启下拉刷新 |
onReachBottomDistance | Number | 50 | 页面上拉触底事件触发时距页面底部距离,单位仅支持px |
样式和sass
- 支持小程序的rpx 和 h5 vw\vh(750rpx为小程序全屏宽度,100vw为小程序全屏宽度)
- 内置有sass的配置了,只需要安装对应的依赖 “npm install sass-loader node-sass”
- vue组件中,再style 标签上加入属性 “
rpx
为小程序中的单位, 750 rpx = 屏幕的宽度vm
为h5 的单位, 100 vm = 屏幕的高度
数据展示
- 在js中的 data 中定义数据
- 在 template 中通过 {{ 数据 }}
- 在标签的属性上通过 :data-index= ‘数据’ 来使用
1. 使用数据{{ title }}
<template>
<view class="content">
<view>{{ title }}</view>
</view>
</template>
<style></style>
<script>
export default{
data(){
return{
title:"数据展示"
}
}
}
</script>
2. 在标签上通过属性的方式来使用数据
<template>
<view class="content">
<view :data-title="title">{{ title }}</view>
</view>
</template>
数据循环(v-for)
- item 和 index 分别为 循环项和循环索引
- :key 指定唯一的属性,用来提高循环效率
<view v-for="(item,index) in list" :key='item.id'>
{{ item.id }} -- {{ item.text }} -- {{ index }}
</view>
<script>
export default{
data(){
return{
list:[
{
id:1,
text:'数据循环1'
},{
id:2,
text:'数据循环2'
}
]
}
}
}
</script>
条件编译
-
通过 v-if 来决定显示和隐藏,不适合做频繁的切换显示(当 v-if 的值为 false 时,删除对应的标签)
-
通过 v-show 来决定显示和隐藏,适合做频繁的切换显示(当 v-show 的值为 false 时,改变的只是 display:none 这个值)
<view v-if="true">显示</view> <view v-if="isShow">显示或隐藏</view> <view v-show>显示或隐藏</view>
@ 计算属性
- 可以理解为是对 data 中的数据提供了一种加工或者过滤的能力
- 通过 computed 来定义计算属性
<template>
<view>{{ coMoney }}</view>
<view>
<view v-for="item in filterList" :key="item.id"></view>
</view>
</template>
<script>
data(){
return{
list:[
{
id:0,
name:"Zip"
},
{
id:1,
name:"Jarry"
},
{
id:2,
name:"Zoom"
}
]
}
},
computed:{
cnMoney(){
return "Y"+this.money
},
// 过滤数组
filterList(){
return this.list.filter(v => v.id < 0);
},
// 加工
processList(){
return this.list.map(v => {
v.color= "red";
return v;
})
}
}
</script>
@组件传参
父组件向子组件
- 父组件向子组件传值通过 属性 的方法
- 通过 props 进行接收数据
// 父组件
<template>
<view>
<img-border :src="src1"></img-border>
<img-border :src="src2"></img-border>
</view>
</template>
<script>
import imgBorder form "@/components/img-border";
export default{
componets:{
imgBorder
}
data(){
return{
src1:"http://img.img.png",
src2:"http://img.img2.png"
}
}
}
</script>
// 子组件
<template>
<img class="img-border" :src="src"></img>
</template>
<script>
export default{
props:{
src:String
}
}
</script>
子组件向父组件传递数据
- 子组件通过触发事件 的方式向父组件传递数据
- 父组件通过 监听事件 的方式来接受数据
- 练习:将两张图片的 src 路径打印在 src 这个文本标签内
// 父组件
<template>
<view>
<view><text>{{ src }}</text></view>
<img-border @srcChange="handleSrcChange" :src="src1"></img-border>
<img-border @srcChange="handleSrcChange" :src="src2"></img-border>
</view>
</template>
<script>
import imgBorder form "@/components/img-border";
export default{
componets:{
imgBorder
},
data(){
return{
src:'',
src1:"http://img.img.png",
src2:"http://img.img2.png"
}
},
menthods:{
handleSrcChnage(e){
this.src = e;
}
}
}
</script>
// 子组件
<template>
<img @click="handleClick" class="img-border" :src="src"></img>
</template>
<script>
export default{
props:{
src:String
},
methods:{
handleClick(){
// this.$emit("自定义的事件名称","要传递的参数")
this $emit("srcChange",this.src)
}
}
}
</script>
@全局定义数据两种方式
通过 Vue 的原型共享数据
-
Vue.prototype.baseURL="http://www.baidu.com"
// main.js 文件 Vue.prototype.baseURL = "http://www.baidu.com" // index.vue 文件 <script> // 生命周期函数 // onLoad 页面加载完毕就会触发 onLoad(){ console.log(this.baseURL) // www.baidu.com } </script>
通过 globalData 共享数据
-
getApp().globalData.text="test"
App.vue 文件 <script> export default{ globalData:{ base:"www.360.com" } } </script> // index.vue 文件 <script> // 生命周期函数 // onLoad 页面加载完毕就会触发 onLoad(){ console.log(getApp().globalData .base) // www.360.com } </script>
插槽
生命周期
- uni-app https://uniapp.dcloud.io/frame?id=生命周期
- vue http://cn.vuejs.org/v2/guide/instance.html?#生命周期图示
- 微信小程序 https://developers.weixin.qq.com/miniprogram/dev/framework/app-service/page-life-cycle.html
@uni-ui 组件库
- 网址:npmjs.com/package/@dcloudio/uni-ui
-
安装 uni-ui
npm install @dcloudio/uni-ui
-
使用 uni-ui
import {uniBadge} from "@dcloudio/uni-ui" export default{ components:{uniBadge} }
-
在 template 中使用组件
<uni-badge text="1"></uni-badge> <uni-badge text="2" type="success" @click="bindClick"></uni-badge><uni-badge text="3" type="success" :inverted="true"></uni-badge>
@封装异步请求
- 基于原生的 promise 来封装
- 挂载到 Vue 的原型上
- 通过 this. request 的方式来使用
1. 在 src 文件夹中新建一个 utils 文件夹,并新建一个 request.js 文件
// request.js 文件
export default(params)=>{
// 加载中的效果
uni.showLoading({
title:"加载中"
})
// resolve:成功的时候被执行;reject:失败的时候执行
return new Promise((resolve,reject) => {
wx.request({
...params,
success(res){
resolve(res.data);
},
fail(err){
reject(err);
},
// 无论失败或成功都会触发此函数
complete(){
// 停止加载中的效果
uni.hideLoading();
}
})
})
}
2. 挂载到 Vue的原型上
// main.js 文件
import { request } from "./utils/request";
Vue.prototype.request=request;
3. 在页面中使用
// index.vue 文件
mounted(){
this.request({
url:"http://127.0.0.1:3000/img/img.png"
})
.then(res => {
console.log(res)
})
}
将时间戳改为 日/月 格式(moment.js)
- 网址:momentjs.cn
-
安装依赖
npm install moment --save
-
在页面中引入
import moment form "moment"
<script>
// 例如时间戳为:stime:1579276982000
result.MM = moment(this.stime).format("MM")
result.DD = moment(this.stime).format("DD")
</script>
分页功能
- 使用
scroll-view
标签充当分页的容器 - 绑定滚动条触底事件 scrolltolower
- 实现分页逻辑
<template>
<scroll-view class="recommend_view" @scrolltolower="handleTolower" scroll-y ></scroll-view>
</template>
<script>
data(){
return{
// 请求的参数
params:{
// 要获取几条
limit:30,
// 关键字
order:"hot",
// 要跳过几条
skip;0
},
// 是否还有下一页
hasMore:true
}
},
mounted(){},
methods:{
// 获取接口的数据
getList(){
this.request({
url:"http://img/img",
data:this.params,
}).then(res => {
// 判断还有没有下一页数据
if(result.res.vertical.length === 0){
this.hasMore = false;
return;
}s
// 判断是否第一次发送请求(优化性能更)
if(this.recommends.length === 0){
// 将事件戳改为 日/月 格式
this.monthes.MM = moment(this.monthes.stime).format("MM")
this.monthes.DD = moment(this.monthes.stime).format("DD")
}
// 获取热门数据的列表
// 数组拼接 es6
this.hots = [...this.hots, ...result.res.vertical];
})
},
// 滚动条触底事件
handleTolower(){
//console.log("狗丢了怎么办呢? 搜狗搜索!")
/*
1. 修改参数 skip += limit
2. 重新发送请求 getList()
3. 请求回来成功 hots 数据的叠加
*/
if(this.hasMore){
this. params.skip += this.params.limit;
this.getList();
}else{
// 弹窗提示用户
uni.showToast({
title:"没有数据了",
icon:"none"
})
}
}
}
</script>
<style>
.recommend_view{
// height:屏幕的高度 - 头部标题的高度
height: calc( 100vh - 36px );
}
</style>
功能
使用 setNavigationBarTitle
修改 页面标题
<script>
export default{
mounted(){
// 修改页面的标题
uni.setNaviagtionBarTitle({title:"标题"})
}
}
</script>
自动轮播图
- 使用 swiper 标签
- 属性:写在 swiper 标签中
- 自动轮播: autoplay
- 指示器: indicator-dots
- 指示点颜色:indicator-color
- 当前选中的指示点颜色:indicator-active-color
- 自动切换时间间隔:interval
- 衔接轮播: circular
- 图片标签与 swiper 标签的宽度、高度问题
- swiper 默认的高度室 150px
- swiper-item 默认高度为 100%
- 解决:
- 计算图片的宽度和高度的比例 (宽度 / 高度)
- 将图片的比例写到 swiper 标签的样式中
<template>
<view>
<!-- 轮播图开始 -->
<view class="album_swiper">
<swiper autoplay indicator-dots circular>
<swiper-item v-for="item in banner" :key="item.id">
<image :src="item.thumb"></image>
</swiper-item>
</swiper>
</view>
<!-- 轮播图结束 -->
</view>
</template>
<script>
data(){
return{
params:{},
// 轮播图数字
banner:[],
// 列表数组
album:[]
}
}
// 页面组件加载完毕后执行
mounted(){
this.getList();
},
methods:{
getList(){
this.request({
url:"",
data:this.params
}).then(res => {
this.banner = res.banner;
this.album = res.album;
})
}
}
</script>
<style lang="scss" scoped>
.album_swiper{
/* swiper 高 = 小程序的宽度 750rpx 除以 图片的宽高比例 */
swiper{
height: calc(750rpx / 2.3);
image{
height:100%;
}
}
}
</style>