项目的commit历史:
项目先手准备
WXML语法
<view> => div
<text> => span
<image> => img
<cover-view> 覆盖在原生组件之上的标签
-
项目结构
其他阅读:
强烈推介的几个微信小程序开发小技巧,简单又实用
约定:星星,旗子,水滴与赞
⭐标注为踩坑总结;
🚩标注为封装优化,完成一个大标题如pages/home之后再掉过头来实现。
💧标注为搁置,暂时不打算实现;
👍心得写在这里:
-做静态布局的o时候如有psd, 对图片大小,量到多少写多少rpx。
-先写静态布局,很多个block复制出来看看再结合js中的数组进行列表渲染
-知道想要更多个性化配置的时候要去找对应的api
全局配置
目标
- 修改
window
的底色 -
tabBar
运用iconfont-Symbol引入
参考:
⭐自定义tabBar
- 配置信息
app.json
:- 添加
custom: true
字段, - 所有 tab 页的 json 里需声明 usingComponents 项,也可以在 app.json 全局开启。
- PS:注意usingComponents的书写和全局开启的意思
- 添加
- 提供根目录入口,即严格书写结构目录
custom-tab-bar
custom-tab-bar/index.js
custom-tab-bar/index.json
custom-tab-bar/index.wxml
custom-tab-bar/index.wxss
- 编写自定义组件,该自定义组件完全接管tabBar的渲染
参考自定义tabBar代码段
思路为,自定义组件使用列表渲染,需要维护selected:index
,以及一个数组list
,数组元素为若干tabBar对象。
维护data嘛,WXML需要在列表循环item中自定义属性data-index,data-path,绑定bindtap事件
。
在bindtap绑定的方法上,1. 维护selected
2. 路由跳转,可以是wx.switchTab()
方法;
最后,为保证跳转后selected高亮,在跳转后的page或者components的onshow / show 方法中调用page实例的方法this.getTabBar()
,再维护一次selected状态。
【搁置💧】tabBar使用的图片。在小程序中使用iconfont:
mini-program-iconfont-cli
小程序使用svg
首页
目标
pages/home的目标有:轮播,列表, 轮播不跳转,每日不跳转,列表跳转详情
轮播swiper
- 调用接口:接口必须在开发白名单;
- 静态布局: 文字使用绝对定位,页数使用右浮;
- 列表渲染
前置:
- page的生命周期函数onload发起 wx.request()
-
接口约定
- 做静态布局的时候如有psd, 对图片大小,量到多少写多少rpx。
⭐开发:
- 本地开发跨域,需要勾选不校验合法域名。
- 维护banners数组需要调用Page实例的
this.setData()
方法,而不是直接对this.banners
变量操作(油门刹车和车速的例子) - 注意sucess属性如果不用箭头函数,此时this是undefined,需要_self拿到外层的this。
- 轮播默认swiper-item拥有样式,发现图片样式有问题,将item以及图片都添加样式
//page/home/home
//page实例的生命周期
onLoad: function (options) {
wx.request({
url: 'http://iwenwiki.com:3002/api/banner',
success: res => {
console.log(res)
// this.banners = res.data.data
this.setData({
banners: res.data.data
})
}
})
},
列表
- 我把图片的宽高直接告诉好了..
- 最粗浅的实现(⭐静态grid + ⭐单行省略; 接口数据||列表渲染 => or 动态获取)
- 对列表使用loading
- 🚩运用模板,在很多地方都需要list,抽象。
静态布局:
//1.
width: 210rpx;
height: 140rpx;
//2.1
<view class="list">
<view class="list-title">title</view>
<view class="list-image"><image src="/image/icon_API.png"></image></view>
<view class="list-description">description</view>
<view class="list-reading"><text>2233</text>阅读</view>
</view>
// ---------------------------------------
<view class="list">
<view class="list-title">title</view>
<view class="list-image"><image src="/image/icon_API.png"></image></view>
<view class="list-description">description</view>
<view class="list-reading"><text>2233</text>阅读</view>
</view>
// ---------------------------------------
<view class="list">
<view class="list-title">title</view>
<view class="list-image"><image src="/image/icon_API.png"></image></view>
<view class="list-description">description</view>
<view class="list-reading"><text>2233</text>阅读</view>
</view>
// ---------------------------------------
//2. 1
父 {
display: grid;
grid: 行 行 行 / 列 列
}
子 {
grid-area: 第几行 / 第几列 / 第几行 / 第几列
}
-------------------------------------
一行溢出省略,不许折行{
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
多行溢出省略,父高=行高*3倍 {
// grid-area: 2/2/3/3;
height: 120rpx;
line-height: 40rpx;
overflow: hidden;
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
}
.list {
display: grid;
grid: auto auto auto / 210rpx 1fr;
margin-top: 10px;
border-bottom: 1px solid rgba(0,0,0, .2);
}
.list .list-title {
grid-area: 1/1/2/3;
}
.list .list-image {
grid-area: 2/1/4/2;
}
.list image {
width:210rpx;
height: 140rpx;
}
.list .list-description {
grid-area: 2/2/3/3;
}
.list .list-reading {
grid-area: 3/2/4/3;
margin-left: auto;
}
.list text {
margin-right: 10rpx;
color: orangered;
}
动态获取:
//2.2
onLoad: function (options) {
wx.request({
url: 'http://iwenwiki.com:3002/api/banner',
// MORE CODE ..
}
})
wx.request({
url: 'http://iwenwiki.com:3002/api/indexlist',
success: res => {
console.log(res.data.data)
this.setData({
list: res.data.data
})
}
})
//2.3
<view class="list" wx:for="{{list}}" wx:key="index">
<view class="list-title">{{item.title}}</view>
<view class="list-image"><image src="/image/icon_API.png"></image></view>
<view class="list-description">{{item.desc}}</view>
<view class="list-reading"><text>{{item.readNum}}</text>阅读</view>
</view>
- 使用loading
- 分析:在微信开放文档中搜索Loading;
- 可以使用weui组件库;也可以调用原生的API,进去看看;
- 小程序的API有点东西。界面和路由,以及网络,广告,等等都有明确的文档。那就选用
wx.showloading()
看起来不错。
列表跳转详情:
- 路由:⭐页面跳转,传值的两种实现;
- 接口约定
- 新页面page/indexDetail
a. 在某些页面跳转中,url对应的params对象需要传值。⭐它有两种实现:
- 常用的是靠DOM上的事件,调用api,使用data-*自定义属性保存item上的数据。
- 第二种是靠路由相关的标签,调用<router-link>或者<navagator>它们的属性,在遍历中可以直接在item上拿到数据。
// home.js
/**
* 页面的原型方法
*/
taphref(e){
// console.log(e)
let data = e.currentTarget.dataset
wx.navigateTo({
// url: '/pages/about/about',
url: '/pages/indexDetail/indexDetail?itemId=' + data.id
})
},
js其中的
itemId
数据,就是打开页面的onload方法中能够轻易得到的options形参。
b. 💧官网中wx.navigateTo()
还有许多向打开页面传递数据的办法,一时不知怎么回事。
https://developers.weixin.qq.com/community/develop/article/doc/000664ed6d88b061d2daf19685b413
c. 在打开的页面中,书写页面实例的生命周期:onload方法对接口发起请求。
//pages/indexDetail/indexDetail.js
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
// console.log(options)
wx.request({
url: 'http://iwenwiki.com:3002/api/indexlist/detail?id=' + options.itemId,
success: res => {
console.log(res)
this.setData({
indexDetails: res.data[0]
})
}
})
},
静态布局
- page/indexDetail还要跳一跳才能进去改样式,太麻烦了,有什么解决办法吗?有的,新增编译模式即可。这个方法我是在一段视频课中找到的,试着google了很多,但始终无法精准描述我的问题。
-
文本样式:两边对齐,行首缩进
-
图片的样式:这是一篇文章的头部,我只是给它加个父容器,父容器限定高度并且设置溢出overflow:hidden。
🚩优化
目标
- 使用模板,独立列表部分的逻辑
- 💧原生api的
wx.request
进行封装
模板
为什么使用模板
当前代码段重复使用,哪里使用哪里调用
参考 框架-WXML语法-模板:微信开放文档
⭐什么是模板
- 定义模板,拥有name
<template name="odd">
<view> odd </view>
</template>
<template name="even">
<view> even </view>
</template>
- 使用模板,运用is属性
<block wx:for="{{[1, 2, 3, 4, 5]}}">
<template is="{{item % 2 == 0 ? 'even' : 'odd'}}"/>
</block>
//
<template is="odd"/>
<template is="even"/>
<template is="odd"/>
<template is="even"/>
- 使用模板,运用is属性和data属性
(模板的目的是公用HTML,然后在各自复用的实例中书写需要的data)
- 使用 is 属性,声明需要的使用的模板,然后将模板所需要的 data 传入
- 模板传递数据: <template is="模板名字" data="{{变量}}">
// 定义模板
<template name="msgItem">
<view>
<text> {{index}}: {{msg}} </text>
<text> Time: {{time}} </text>
</view>
</template>
//使用模板
<template is="msgItem" data="{{...item}}"/>
//为模板注入data
Page({
data: {
item: {
index: 0,
msg: 'this is a template',
time: '2016-09-15'
}
}
})
⭐开发: 列表模板
/templates
- 创建模板文件(templates/foodlist: 只有wxml,wxss)
- 定义模板
//微信开放文档
<!--
index: int
msg: string
time: string
-->
<template name="msgItem">
<view>
<text> {{index}}: {{msg}} </text>
<text> Time: {{time}} </text>
</view>
</template>
// /templates/foodlist/foodlist.wxml
<!--
foodlist: object
-->
<template name="foodlist"> 模板内容 {{foodlist.title}} </template>
/pages/food/food
- 引用模板,使用模板(attrs:
is, data
)
// /pages/food/food.wxml
<import src="模板的相对路径" />
<view id="food">
<template is="foodlist" data="{{...items}}"></template>
<template is="foodlist" data="{{...items}}"></template>
<template is="foodlist" data="{{...items}}"></template>
</view>
- 使用模板的样式
// pages/food/food.wxss
@import ('/templates/foodlist/foodlist.wxss')
- 给pages/food/food实例写数据
// /pages/food/food.js
Page({
data: {
//.... More Code To Come...
items: {
foodlist: {
title:'',
image:'',
desc:"",
readNum:2333
}
}
},
onload: function(options){
//wx.request({})
//.... More Code To Come...
}
//.... No Code To Come...
})
- 动态获取列表信息
- onload生命周期发起请求
- 将数据放在foodArray
- wxml循环渲染模板
- 修改一开始写好的模板。foodlist统一修改为item
// 请求省略
// foodArray存放省略
// /pages/food/food
<block wx:for="{{foodArray}}" wx:key="index">
<template is="foodlist" data="{{item}}"/>
</block>
// /templates/foodlist/foodlist.wxml
<template name="foodlist">
<view class="list">
<view class="list-title">{{item.name}}</view>
<view class="list-image"><image src="{{item.pic}}"></image></view>
<view class="list-description">{{item.description}}</view>
<view class="list-reading"><text>{{item.price}}</text>阅读</view>
</view>
</template>
在pages/food/food使用模板:
食疗坊
目标
pages/food的目标有:顶部搜索(定位城市),类项,列表, 搜索跳转,类项不跳转,列表跳转详情
静态布局
顶部搜索 + 类项 + 列表
使用WeUI组件库
A. 快速上手
- 引入组件(全局配置or
npm
构建) - 要在 app.wxss 里面引入 weui.wxss(useExtendedLib, 省略)
- 在页面中使用
dialog
组件:- 首先在页面的 json 文件加入 usingComponents 配置字段
- 然后可以在对应页面的 wxml 中直接使用该组件
//app.json 全局配置
{
"useExtendedLib": {
"kbone": true,
"weui": true
}
}
//page/index.json
{
"usingComponents": {
"mp-dialog": "/miniprogram_npm/weui-miniprogram/dialog/dialog"
}
}
//page/index.wxml
<mp-dialog title="test" show="{{true}}" bindbuttontap="tapDialogButton" buttons="{{[{text: '取消'}, {text: '确认'}]}}">
<view>test content</view>
</mp-dialog>
chapters类项静态布局
目的
开发
// 全局配置useExtendedLib
// page.json引入
// page/food/food.wxml
<view class="subjects">
<view class="item">
<mp-icon icon="music" color="#666" size="{{28}}"></mp-icon>
<text>美容养颜</text>
</view>
<view.item*7`tab`>
</view>
css核心内容:
-
.subject
使用flex布局,每个.item
设置宽度为25%; -
.item
使用flex布局,主轴朝下;
💧类项优化:
- 使用iconfont 考虑多种颜色的svg;
- 不使用iconfont:切图;
- 在wxml中一个个icon的写,太过繁琐;其解决方案:
1. 在/utils
文件夹中添加js文件,这个js文件导出的是含数据的对象,而非/utils
传统的功能;
2. 即:抽象(固定)的是数据而非功能。(把icon的值放入固定数据中)
3. 在页面实例的js中引入模块(import/require)
4. 在页面实例的wxml中使用列表渲染(循环)
🚩城市定位,跳转
- 找到定位提供经纬度的api
- 需要全局配置
scope.permission
- 利用后端接口返回城市
- 带参跳转page/food/food
https://developers.weixin.qq.com/miniprogram/dev/api/location/wx.getLocation.html
https://developers.weixin.qq.com/miniprogram/dev/reference/configuration/app.html#permission
开发:
- 在定位按钮绑定
bindtap事件
,使用wx.getLocation
这个API小程序,想要Log数据但:要求权限。于是全局配置scope.permission
,参考permissionObject示例配置。至此我们得到经纬度的数据。 -
通过以下接口获得城市;
3.考虑跳转page/food/food:
- wx.switchTab
不允许传参;
- wx.navigatBack
不允许传参;
- 全局变量getApp({globalData:xxx})
// pages/changeCity/changeCity.js
let app = getApp()
Page({
//More Code to Come..
})
5.已: 获得全局变量,城市; => 将要:跳转回tabBar,传入城市参数。
- 带参跳转page/food/food:
在这个page实例的onshow生命周期做文章:重新发起列表渲染的请求,以全局数据的this.getApp().city
作为请求的参数。