微信小程序> 企业级微信小程序实战详解

企业级微信小程序实战详解

浏览量:588 时间: 来源:weixin_34150830

项目地址:github.com/wudiufo/WeC…

完成效果展示:www.bilibili.com/video/av488…


小爱心是否点赞组件 components/like

思路:

like 默认为 false,显示空心小爱心

触摸执行tap:onLike 方法,因为 this.setData({count:count,like:!like})是异步的,先执行count = like ? count - 1 : count + 1,这时like还是false,执行count+1。然后在执行this.setData()方法,将like变为true,显示实心小爱心。

let behavior = like ? 'like' : 'cancel'        //自定义事件      this.triggerEvent('like', {        behavior: behavior      }, {})复制代码

自定义事件like,当like为真时,behavior为like,在models/like.js中,let url = behavior === 'like' ? 'like/cancel' : 'like',因为behavior === 'like'为真,就调用服务器接口'like/cancel',相反就调用like接口。

刚开始实心就调用'like/cancel'接口,空心就调用'like'接口


底部左右切换组件 components/navi

思路:

navi/index.js中:
先定义哪些数据是外部传来的数据,哪些数据是私有数据properties: {//外部传来的数据    title: String,    first: Boolean, //如果是第一期向右的箭头就禁用,默认是false    latest: Boolean //如果是最新的一期向左的箭头就禁用,默认是false  }, data: {//私有数据    disLeftSrc: './images/triangle.dis@left.png',    leftSrc: './images/triangle@left.png',    disRightSrc: './images/triangle.dis@right.png',    rightSrc: './images/triangle@right.png'  },复制代码

左箭头:

在navi/index.wxml中image bind:tap="onLeft" class="icon" src="{{latest?disLeftSrc:leftSrc}}"/

src显示图片规则:如果是最新的期刊,就显示向左禁用状态disLeftSrc箭头;如果不是最新一期的期刊,就显示向左可用状态leftSrc箭头

为图片绑定触摸事件onLeft,在navi/index.js中:

在 methods 中:如果不是最新的期刊,就继续绑定自定义事件leftonLeft: function(event) { //不是最新一期     if (!this.properties.latest) {       this.triggerEvent('left', {}, {})     }   },复制代码

右箭头:

在navi/index.wxml中image bind:tap="onRight" class="icon" src="{{first?disRightSrc:rightSrc}}"/

src显示图片规则:如果是第一期的期刊,就显示向右禁用状态disRightSrc箭头;如果不是第一期的期刊,就显示向右可用状态rightSrc箭头

为图片绑定触摸事件onRight,在navi/index.js中:

在 methods 中:如果不是第一期的期刊,就继续绑定自定义事件rightonRight: function(event) { //不是第一期     if (!this.properties.first) {       this.triggerEvent('right', {}, {})     }   }复制代码
pages/classic中:
1:在 classic.json 中,注册使用navi自定义组件{ "usingComponents": {   "v-like": "/components/like/index",   "v-movie": "/components/classic/movie/index",   "v-episode": "/components/episode/index",   "v-navi": "/components/navi/index" }}2:在 classic.wxml 中:绑定自定义事件left, 获取当前一期的下一期;绑定自定义事件right,获取当前一期的上一期v-navi bind:left="onNext" bind:right="onPrevious" class="nav" title="{{classic.title}}" first="{{first}}" latest="{{latest}}"/   3:在 classic.js 中:// 获取当前一期的下一期,左箭头onNext: function(evevt) {this._updateClassic('next') },// 获取当前一期的上一期,右箭头onPrevious: function(evevt) { this._updateClassic('previous') },// 重复代码过多,利用函数封装的思想,新建一个函数抽取公共代码// 发送请求,获取当前页的索引,更新数据 _updateClassic: function(nextOrPrevious) {   let index = this.data.classic.index   classicModel.getClassic(index, nextOrPrevious, (res) = {     // console.log(res)     this.setData({       classic: res,       latest: classicModel.isLatest(res.index),       first: classicModel.isFirst(res.index)     })   }) },     4:在 models/classic.js 中:// 当前的期刊是否为第一期,first就变为true,右箭头就显示禁用 isFirst(index) {   return index === 1 ? true : false }// 当前的期刊是否为最新的一期,latest就变为TRUE,左箭头就显示禁用// 由于服务器数据还会更新,确定不了最新期刊的索引,所以就要利用缓存机制,将最新期刊的索引存入到缓存中,如果外界传进来的索引和缓存的最新期刊的索一样,latest就变为TRUE,左箭头就显示禁用 isLatest(index) {   let latestIndex = this._getLatestIndex()   return latestIndex === index ? true : false }// 将最新的期刊index存入缓存 _setLatestIndex(index) {   wx.setStorageSync('latest', index) } // 在缓存中获取最新期刊的index _getLatestIndex() {   let index = wx.getStorageSync('latest')   return index }复制代码

优化缓存。解决每次触摸左右箭头都会频繁向服务器发送请求,这样非常耗性能,用户体验极差。解决方法,就是把第一次发送请求的数据都缓存到本地,再次触摸箭头时,会先查找本地缓存是否有数据,有就直接从缓存中读取数据,没有就在向服务器发送请求,这样利用缓存机制大大的提高了用户的体验。(但也有一部分是需要实时更新的,比如是否点赞的小爱心组件,需要每次都向服务器发送请求获取最新数据)

在 models/classic.js 中:
1:// 设置缓存中的key 的样式,classic-1这种样式  _getKey(index) {    let key = `classic-${index}`    return key  }2:  // 因为getPrevious,getNext实现代码相似,所以为了简化代码可以合并为一个函数  // 缓存思路:在缓存中寻找key,找不到就发送请求 API,将key写入到缓存中。解决每次都调用Api向服务器发请求,耗费性能  // 在缓存中,确定key  getClassic(index, nextOrPrevious, sCallback) {    //0: 是next,触摸向左箭头获取下一期,触摸向右箭头否则获取上一期    let key = nextOrPrevious === 'next' ? this._getKey(index + 1) : this._getKey(index - 1)    //1:在缓存中寻找key    let classic = wx.getStorageSync(key)    //2:如果缓存中找不到key,就调用服务器API发送请求获取数据    if (!classic) {      this.request({        url: `classic/${index}/${nextOrPrevious}`,        success: (res) = {            //将获取到的数据设置到缓存中          wx.setStorageSync(this._getKey(res.index), res)            //再把获取到的数据返回,供用户调取使用          sCallback(res)        }      })    } else { //3:如果在缓存中有找到key,将缓存中key对应的value值,返回给用户,供用户调取使用      sCallback(classic)    }  }--------------------------------------------------------------------------------// 获取最新的期刊利用缓存机制进一步优化 //获取最新的期刊  getLatest(cb) {    this.request({      url: 'classic/latest',      success: (res) = {//将最新的期刊index存入缓存,防止触摸向左箭头时,没有设置latest的值,左箭头会一直触发发送请求找不到最新的期刊报错        this._setLatestIndex(res.index)          //再把获取到的数据返回,供用户调取使用        cb(res)        // 将最新的期刊设置到缓存中,先调取 this._getKey() 方法,为最新获取的期刊设置key值,调用微信设置缓存方法将key,和对应的value值res存进去        let key = this._getKey(res.index)        wx.setStorageSync(key, res)      }    })  }复制代码

处理是否点赞小爱心组件的缓存问题:他不需要缓存,需要实时获取最新数据

在 models/like.js 中:
//编写一个获取点赞信息的方法,从服务器获取最新点赞信息的数据  // 获取点赞信息  getClassicLikeStatus(artID, category, cb) {    this.request({      url: `classic/${category}/${artID}/favor`,      success: cb    })  }复制代码
在 pages/classic/classic.js 中:
//设置私有数据初始值data: {    classic: null,    latest: true,    first: false,    likeCount: 0,//点赞的数量    likeStatus: false //点赞的状态  },       // 在classic.wxml中: v-like class="like" bind:like="onLike" like="{{likeStatus}}" count="{{likeCount}}"/       // 编写一个私有方法获取点赞信息  // 获取点赞信息  _getLikeStatus: function(artID, category) {    likeModel.getClassicLikeStatus(artID, category, (res) = {      this.setData({        likeCount: res.fav_nums,        likeStatus: res.like_status      })    })  },        //生命周期函数--监听页面加载  onLoad: function(options) {    classicModel.getLatest((res) = {      console.log(res)        // this._getLikeStatus(res.id, res.type) //不能这样写,会多发一次favor请求,消耗性能      this.setData({        classic: res,        likeCount: res.fav_nums,        likeStatus: res.like_status      })    })复制代码

在 classic/music/index.js 中:

解决切换期刊时,其他期刊也都是播放状态的问题。应该是,切换期刊时音乐就停止播放,回到默认不播放状态

利用组件事件的通信机制,小程序中只有父子组件

在 components/classic/music/inddex.js 中:

方案一:
//利用组件生命周期,只有 wx:if 才可以从头掉起组件生命周期// 组件卸载的生命周期函数  // 组件卸载音乐停止播放,但这时不生效是因为,在classic.wxml中用的是hidden,应改为if  detached: function(event) {    mMgr.stop()  }, // 在 pages/classic/classic.wxml 中 //     v-music wx:if="{{classic.type===200}}" img="{{classic.image}}" content="{{classic.content}}" src="{{classic.url}}" title="{{classic.title}}"/      复制代码

知识点补充:

wx:if vs hidden,和Vue框架的v-if和v-show 指令一样:wx:if 》他是惰性的,如果初始值为false框架什么也不做,如果初始值为true框架才会局部渲染。true或false的切换就是从页面中局部加入或移除的过程。wx:if 有更高的切换消耗,如果在运行时条件不大可能改变则 wx:if 较好。生命周期会重新执行。hidden 》组件始终会被渲染,只是简单的控制显示与隐藏。hidden 有更高的初始渲染消耗。如果需要频繁切换的情景下,用 hidden 更好。生命周期不会重新执行。

方案二:(推荐使用)

解决切换期刊时音乐可以当做背景音乐一直播放,而其他的期刊是默认是不播放状态

在 components/classic/music/inddex.js 中:
//为了保证期刊在切换时,背景音乐可以一直播放,就要去除掉 mMgr.stop() 事件方法detached: function(event) {    // mMgr.stop() //为了保证背景音乐的持续播放就不能加stop  },      // 监听音乐的播放状态,如果当前页面没有播放的音乐,就设置playing为false。如果当前页面的音乐地址classic.url和当前正在播放的音乐的地址一样,就让播放状态为true_recoverStatus: function() {      if (mMgr.paused) {        this.setData({          playing: false        })        return      }      if (mMgr.src === this.properties.src) {                  this.setData({            playing: true          })                      }    },                // 监听播放状态,总控开关就可以控制播放状态,结局总控开关和页面不同步问题    _monitorSwitch: function() {      console.log('monitorSwitch背景音频', '触发3')        // 监听背景音频播放事件      mMgr.onPlay(() = {          this._recoverStatus()          console.log('onPlay ' + this.data.playing)        })        // 监听背景音频暂停事件      mMgr.onPause(() = {          this._recoverStatus()          console.log('onPause ' + this.data.playing)        })        // 关闭音乐控制台,监听背景音频停止事件      mMgr.onStop(() = {          this._recoverStatus()          console.log('onStop ' + this.data.playing)        })        // 监听背景音频自然播放结束事件      mMgr.onEnded(() = {        this._recoverStatus()        console.log('onEnded ' + this.data.playing)      })    },          //调用生命周期函数,每次切换都会触发attached生命周期        // 在组件实例进入页面节点树时执行  // hidden,ready,created都触发不了生命周期函数  attached: function(event) {    console.log('attach实例进入页面', '触发1')    this._monitorSwitch()    this._recoverStatus()  },复制代码

播放动画旋转效果制作:

在 components/classic/music/index.wxss 中:
//定义帧动画用CSS3.rotation {  -webkit-transform: rotate(360deg);  animation: rotation 12s linear infinite;  -moz-animation: rotation 12s linear infinite;  -webkit-animation: rotation 12s linear infinite;  -o-animation: rotation 12s linear infinite;}@-webkit-keyframes rotation {  from {    -webkit-transform: rotate(0deg);  }  to {    -webkit-transform: rotate(360deg);  }}复制代码

补充css3知识点:

》使用CSS3开启GPU硬件加速提升网站动画渲染性能:为动画DOM元素添加CSS3样式-webkit-transform:transition3d(0,0,0)或-webkit-transform:translateZ(0);,这两个属性都会开启GPU硬件加速模式,从而让浏览器在渲染动画时从CPU转向GPU,其实说白了这是一个小伎俩,也可以算是一个Hack,-webkit-transform:transition3d和-webkit-transform:translateZ其实是为了渲染3D样式,但我们设置值为0后,并没有真正使用3D效果,但浏览器却因此开启了GPU硬件加速模式。》这种GPU硬件加速在当今PC机及移动设备上都已普及,在移动端的性能提升是相当显著地,所以建议大家在做动画时可以尝试一下开启GPU硬件加速。

》适用情况通过-webkit-transform:transition3d/translateZ开启GPU硬件加速的适用范围:

使用很多大尺寸图片(尤其是PNG24图)进行动画的页面。页面有很多大尺寸图片并且进行了css缩放处理,页面可以滚动时。使用background-size:cover设置大尺寸背景图,并且页面可以滚动时。(详见:coderwall.com/p/j5udlw)编写大量DOM元素进行CSS3动画时(transition/transform/keyframes/absTop&Left)使用很多PNG图片拼接成CSS Sprite时》总结  通过开启GPU硬件加速虽然可以提升动画渲染性能或解决一些棘手问题,但使用仍需谨慎,使用前一定要进行严谨的测试,否则它反而会大量占用浏览网页用户的系统资源,尤其是在移动端,肆无忌惮的开启GPU硬件加速会导致大量消耗设备电量,降低电池寿命等问题。

在 components/classic/music/index.wxml 中:
//为图片加上播放就旋转的类,不播放 就就为空字符串image class="classic-img {{playing?'rotation':''}}"  src="{{img}}"/image复制代码

用 slot 插槽,解决在公用组件中可以加入其他修饰内容问题。其实就是,在定义公用组件时,用 slot 命名插槽占位,在父组件调用时可以传递需要的内容补位。和Vue的指令 v-slot 相似。

在 components/tag/index.js 中:
//在 Component 中加入// 启用slot  options: {    multipleSlots: true  },复制代码
在定义的公共组件 components/tag/index.wxml 中:
//定义几个命名插槽,供父元素占位使用view class="container tag-class"  slot name="before"/slot  text{{text}}/text  slot name="after"/slot/view复制代码
在 pages/detail/detail.json 中:
//注册并使用组件{  "usingComponents": {    "v-tag": "/components/tag/index"  }}复制代码
在 pages/detail/detail.wxml 中:
//使用组件v-tag,补位命名插槽v-tag tag-class="{{index===0?'ex-tag1':''||index===1?'ex-tag2':''}}" text="{{item.content}}"     text class="num" slot="after"{{'+'+item.nums}}/text/v-tag复制代码

pages/detail/detail 中,解决评论内容自定义组件 v-tag 评论前两条显示两种颜色的做法:
第一种方法:(推荐使用)
在  pages/detail/detail.wxss  中:
/* v-tag是自定义组件,不能使用css3,在微信小程序中,只有内置组件才可以用css3 *//*用CSS hack方式给自定义组件加样式*/.comment-containerv-tag:nth-child(1)view {  background-color: #fffbdd;}.comment-containerv-tag:nth-child(2)view {  background-color: #eefbff;}复制代码
第二种方法:

定义外部样式方法,像父子组件传递属性一样,传递样式类

在 detail.wxss 中:
/* 定义外部样式 */.ex-tag1 {  background-color: #fffbdd !important;}.ex-tag2 {  background-color: #eefbff !important;}复制代码
在 detail.wxml 中:
/*将自定义的样式类通过属性传值的方式传递给自定义子组件v-tag */v-tag tag-class="{{index===0?'ex-tag1':''||index===1?'ex-tag2':''}}" text="{{item.content}}"        text class="num" slot="after"{{'+'+item.nums}}/text/v-tag复制代码
在 components/tag/index.js 中:
//将外部传进来的样式写在Component中,声明一下// 外部传进来的css,样式  externalClasses: ['tag-class'],复制代码
在 components/tag/index.wxml 中:
// 把父组件传递过来的类 tag-calss 写在 class 类上view class="container tag-class"  slot name="before"/slot  text{{text}}/text  slot name="after"/slot/view复制代码

解决服务器返回的内容简介有 换行符的问题:

原因:

是因为服务器返回的原始数据 是    ,经过转义就变成  

在text文本标签中默认转义为换行

解决方法:

WXS:WXS(WeiXin Script)是小程序的一套脚本语言,结合 WXML,可以构建出页面的结构。和Vue 中的 Vue.filter(过滤器名,过滤器方法) 很相似。WXS 与 JavaScript 是不同的语言,有自己的语法,并不和 JavaScript 一致。由于运行环境的差异,在 iOS 设备上小程序内的 WXS 会比 JavaScript 代码快 2 ~ 20 倍。在 android 设备上二者运行效率无差异。

在 utils/filter.wxs 中:
// 定义过滤器函数,处理服务器返回的数据,将  变成 // 会打印两次,undefined和请求得到的数据,因为第一次初始时text为null,发送请求得到数据后调用setData更新数据一次var format = function(text) {  console.log(text)      if (!text) {    return  }  var reg = getRegExp('\', 'g')  return text.replace(reg, '')}module.exports.format = format复制代码
在  pages/detail/detail.wxml 中:
//引入wxs src="../../utils/filter.wxs" module="util"///在需要过滤的数据中使用text class="content"{{util.format(book.summary)}}/text复制代码

解决解决服务器返回的内容简介首行缩进的问题:

在  pages/detail/detail.wxss 中:
//对需要缩进的段落前加以下的类,但这时只有第一段缩进.content {  text-indent: 58rpx;  font-weight: 500;}复制代码
在 utils/filter.wxs 中:
//用转义字符   作为空格,但这时小程序会以 样式输出,不是我们想要的效果var format = function(text) {   if (!text) {    return  }  var reg = getRegExp('\', 'g')  return text.replace(reg, '    ')}module.exports.format = format复制代码
在  pages/detail/detail.wxml 中:
//加入属性  decode="{{true}}",首行缩进问题解决text class="content" decode="{{true}}"{{util.format(book.summary)}}/text复制代码

解决短评过多让其只显示一部分的问题:

在 utils/filter.wxs 中:
//添加一个限制短评长度的过滤器,并导出// 限制短评的长度的过滤器var limit = function(array, length) {  return array.slice(0, length)}module.exports = {  format: format,  limit: limit};复制代码
在  pages/detail/detail.wxml 中:
wxs src="../../utils/filter.wxs" module="util"/view
            
            

版权声明

即速应用倡导尊重与保护知识产权。如发现本站文章存在版权问题,烦请提供版权疑问、身份证明、版权证明、联系方式等发邮件至197452366@qq.com ,我们将及时处理。本站文章仅作分享交流用途,作者观点不等同于即速应用观点。用户与作者的任何交易与本站无关,请知悉。

产品经理

手机 : 13312967497

擅长 : 小程序流量变现

扫码领取礼包

最新资讯

热门模板

  • 头条
  • 搜狐
  • 微博
  • 百家
  • 一点资讯
  • 知乎