了解一个概念,微信公众号其实是一个大类,包含服务号、订阅号、小程序、企业微信 学习小程序的重点要放在微信开放能力的开发上
本篇博客围绕以下几点开讲
- 微信小程序的基础知识
- Flex 机制属性详解
- Wx.request 请求
- 生命周期
- 数据绑定
- 列表渲染、条件渲染、数据渲染、事件
- ES6语法应用
- 面向对象思维构建业务模型、箭头函数、Promise、Class
- Getter和setter
重点再说一下json
json对象的属性必须加双引号,这是严格要求的一项使用json.stringifiy实现过滤修改 但是这个方法在火狐浏览器3.5、3.6有一个bug,4.0修复了这个bug
<script>
var book = {
"title": "pop",
"authors": [
"ls",
"zrar",
"bzrar"
],
"edition": 3,
"year": 2011
}
var jsonText = JSON.stringify(book, function(key, value){
switch(key){
case "authors":
return value.join('/');
case "year":
return 2018;
default:
return value;
}
})
console.log(jsonText,'json')
//{"title":"pop","authors":"ls/zrar/bzrar","edition":3,"year":2018} json
</script>
还有就是 json字符串和数组互转 json格式化html常用的操作下面的链接讲解的很详细
重点说一下弹性布局flex
如何确定主轴和交叉轴,当flex-direction为row是水平方向就是主轴,垂直方向就是交叉轴,相反就不说了很好理解,一般配合使用justify-content和aligin-items实现水平垂直居中,下面的链接有详细的介绍
点赞组件开发
如何在页面中引用组件?通过在json中定义key/value的形式引入组件 ,如何在css中定义全局样式?使用page对象去定义,因为页面渲染后会自动生成一个page标签。只有font、color可以在组件外继承使用,可以通过line-height方法消除文字空白间距,关于let的使用她是定义块级变量的
<!--components/like/like-cmp.wxml-->
<view class="container" bind:tap="onLike">
<image src="{
{like?yes_url:no_url}}" />
<text>{
{
count}}</text>
</view>
// components/like/like-cmp.js
Component({
/**
* 组件的属性列表
*/
properties: {
like: Boolean,
count: Number,
readOnly:Boolean
},
data: {
yes_url: 'images/like.png',
no_url: 'images/like@dis.png'
},
methods: {
onLike: function (event) {
if(this.properties.readOnly){
return
}
let count = this.properties.count
count = this.properties.like ? count - 1 : count + 1
this.setData({
count: count,
like: !this.properties.like
})
let behavior = this.properties.like ? 'like' : 'cancel'
this.triggerEvent('like', {
behavior: behavior
}, {
})
}
}
})
/* components/like/like-cmp.wxss */
.container{
display: flex;
flex-direction: row;
/* 必须指定宽度,否则会出现移动 */
/* width:120rpx; */
padding:10rpx;
}
.container text{
font-size:24rpx;
color: #bbbbbb;
line-height:24rpx;
position:relative;
bottom:10rpx;
left:6rpx;
}
.container image{
width:32rpx;
height:28rpx;
}
下面是引入组件的方法,采用的绝对路径而不是相对与当前文件的相对路径。
{
"usingComponents": {
"navi-cmp": "/components/navi/navi",
"epsoide-cmp": "/components/epsoide/epsoide",
"like-cmp": "/components/like/index",
"movie-cmp":"/components/classic/movie/movie",
"music-cmp": "/components/classic/music/music",
"essay-cmp": "/components/classic/essay/essay",
"img-btn-cmp": "/components/image-button/index"
}
}
封装HTTP请求
在onload阶段调用数据是因为它早于onready,promise主要是解决异步且套问题所谓的回调地狱通过return的方式实现,尽量不要乱用promise,复杂页面拆分成低耦合的模块有助于维护开发
// config文件
const config = {
api_blink_url: 'http://pro/v1/',
appkey: '获取appkey'
}
export {
config }
import {
config } from '../config.js'
//import { config as loop } from '../config.js' 可以使用as指代别名一但修改用的地方都要使用别名要统一
class HTTP {
constructor() {
this.baseRestUrl = config.api_blink_url
}
//http 请求类, 当noRefech为true时,不做未授权重试机制
request(params) {
var that = this
var url = this.baseRestUrl + params.url;
if (!params.method) {
params.method = 'GET';
}
wx.request({
url: url,
data: params.data,
method: params.method,
header: {
'content-type': 'application/json',
'appkey':config.appkey
},
success: function (res) {
// 判断以2(2xx)开头的状态码为正确
// 异常不要返回到回调中,就在request中处理,记录日志并showToast一个统一的错误即可
var code = res.statusCode.toString();
var startChar = code.charAt(0);
if (startChar == '2') {
params.success && params.success(res.data);
} else {
params.error && params.error(res);
}
},
fail: function (err) {
params.fail && params.fail(err)
}
});
}
};
export {
HTTP };
从这里开始不在页面中写HTTP请求而是引入model再对HTTP做一次封装,通过image-btn自定义组件实现分享功能
<view class='container'>
<view class='header'>
<epsoide-cmp class="epsoide" index="{
{classic.index}}" />
<view class="like-container">
<like-cmp bind:like="onLike" class="like" like="{
{like}}" count="{
{count}}" />
<img-btn-cmp class="share-btn" open-type="share">
<image class="share" slot="img" src="/images/icon/share.png" />
</img-btn-cmp>
</view>
</view>
<movie-cmp wx:if="{
{classic.type==100}}" img="{
{classic.image}}" content="{
{classic.content}}" />
<music-cmp wx:if="{
{classic.type==200}}" img="{
{classic.image}}" content="{
{classic.content}}" src="{
{classic.url}}" title="{
{classic.title}}" />
<essay-cmp wx:if="{
{classic.type==300}}" img="{
{classic.image}}" content="{
{classic.content}}" />
<navi-cmp class="navi" latest="{
{latest}}" first="{
{first}}" catch:left="onNext" catch:right="onPrevious" title="{
{classic.title}}" />
</view>
<!-- <navigator target="miniProgram" app-id="wx8ffc97ad5bcccc89" open-type="navigate">sdasd</navigator> -->
<!-- <button bind:tap="onIP">IP</button> -->
model的实现
import {
HTTP } from '../utils/http.js'
import {
ClassicStorage} from '../models/classic-storage.js'
class ClassicModel extends HTTP{
prefix = 'classic'
constructor() {
super()
}
getLatest(sCallback){
this.request({
url:'classic/latest',
success:(data)=>{
// 如果不用箭头函数,this将指代不正确
let key = this._fullKey(data.index)
wx.setStorageSync(key, data)
this._setLatestIndex(data.index)
sCallback(data)
}
})
}
getPrevious(index, sCallback){
this._getClassic(index,'previous',sCallback)
}
getNext(index, sCallback) {
this._getClassic(index, 'next', sCallback)
}
getById(cid, type, success){
let params = {
url:'classic/'+type+'/' + cid,
success:success
}
this.request(params)
}
isLatest(index){
let key = this._fullKey('latest-' + index)
let latestEpsoide = wx.getStorageSync(key)
if(latestEpsoide){
if (index == latestEpsoide){
return true
}
}
else return false
}
isFirst(index){
if (index==1){
return true
}
else return false
}
getMyFavor(success){
let params={
url:'classic/favor',
success:success
}
this.request(params)
}
_getClassic(index, next_or_previous, sCallback){
let key = next_or_previous == 'next' ? this._fullKey(index + 1):
this._fullKey(index-1)
let classic = wx.getStorageSync(key)
if (!classic) {
let params = {
url: 'classic/' + index + '/' + next_or_previous,
success:(data)=>{
let key = this._fullKey(data.index)
wx.setStorageSync(key, data)
sCallback(data)
}
}
this.request(params)
}
else{
sCallback(classic)
}
}
/**
* 在缓存中存放最新一期的期数
*/
_setLatestIndex(index){
let key = this._fullKey('latest-' + index)
wx.setStorageSync(key, index)
}
_getLatestEpsoide(index){
let key = this._fullKey(index)
return wx.getStorageSync(key)
}
_fullKey(partKey){
let key = this.prefix + '-' + partKey
return key
}
}
export {
ClassicModel}
// pages/classic/classic.js
import {
ClassicModel} from '../../models/classic.js'
import {
LikeModel } from '../../models/like.js'
let classicModel = new ClassicModel()
let likeModel = new LikeModel()
Page({
/**
* 页面的初始数据
*/
data: {
classic:null,
latest:true,
first:false,
like:false,
count:0
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
classicModel.getLatest((data)=>{
this._getLikeStatus(data.id, data.type)
this.setData({
classic:data
})
})
},
onPrevious:function(event){
let index = this.data.classic.index
classicModel.getPrevious(index, (data)=>{
if(data){
this._getLikeStatus(data.id, data.type)
this.setData({
classic:data,
latest: classicModel.isLatest(data.index),
first: classicModel.isFirst(data.index)
})
}
else{
console.log('not more classic')
}
})
},
onNext:function(event){
let index = this.data.classic.index
classicModel.getNext(index, (data)=>{
if (data) {
this._getLikeStatus(data.id, data.type)
this.setData({
classic: data,
latest: classicModel.isLatest(data.index),
first: classicModel.isFirst(data.index)
})
}
else {
console.log('not more classic')
}
})
},
onLike:function(event){
let like_or_cancel = event.detail.behavior
likeModel.like(like_or_cancel, this.data.classic.id, this.data.classic.type)
},
_getLikeStatus:function(cid, type){
likeModel.getClassicLikeStatus(cid, type, (data)=>{
this.setData({
like:data.like_status,
count:data.fav_nums
})
})
},
onShareAppMessage(){
}
})
由于异步调用无法使用return,通过回调函数把数据传出去,以及自定义事件triggerEvent,因为点赞的功能不需要传递success函数从而报错,在HTTP.js里面做了闭空处理