新版微信小程序开发实战

这篇博客深入探讨了微信小程序的各个方面,包括基础知识、Flex布局、Wx.request请求、生命周期、数据绑定、列表渲染等。还特别强调了JSON的使用和弹性布局(Flex)的应用,解释了如何通过justify-content和align-items实现水平垂直居中。此外,还介绍了组件开发、HTTP请求封装、Promise的运用以及导航、书籍、搜索历史和个人中心页面的实现。
摘要由CSDN通过智能技术生成

了解一个概念,微信公众号其实是一个大类,包含服务号、订阅号、小程序、企业微信 学习小程序的重点要放在微信开放能力的开发上

本篇博客围绕以下几点开讲

  1. 微信小程序的基础知识
  2. Flex 机制属性详解
  3. Wx.request 请求
  4. 生命周期
  5. 数据绑定
  6. 列表渲染、条件渲染、数据渲染、事件
  7. ES6语法应用
  8. 面向对象思维构建业务模型、箭头函数、Promise、Class
  9. Getter和setter

json

重点再说一下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常用的操作下面的链接讲解的很详细

https://blog.csdn.net/kingrome2017/article/details/82178661

重点说一下弹性布局flex

如何确定主轴和交叉轴,当flex-direction为row是水平方向就是主轴,垂直方向就是交叉轴,相反就不说了很好理解,一般配合使用justify-content和aligin-items实现水平垂直居中,下面的链接有详细的介绍

https://blog.csdn.net/kingrome2017/article/details/76528098

点赞组件开发

如何在页面中引用组件?通过在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里面做了闭空处理

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值