微信小程序入门基础(3)缓存实践和Template模板

感觉上章没有讲完,这章继续讲,两章配合阅读。

1.Template模板

当一块区域需要在多个地方使用的时候,可以把这个区域做成一个模版,在使用的时候调用这个模版即可,这样即减少重复代码的编写,又易于维护,让代码整洁。

模板代码的编写

<template name='postItem'>
  <view class='box'>
    <view class='title-box'>
      <text class='title'>{{item.title}}</text>
      <text class='date'>{{item.date}}</text>
    </view>
    <image src='{{item.imgUrl}}' class='cont-image'></image>
    <text class='content'>{{item.content}}</text>
  </view>
</template>

为了方便管理我们的模版文件,可以在pages文件夹下面,新建一个模版文件,里面存放编写的模版;我们要使用标签template来包裹代码,并且要给其加一个name属性,当然也要编写对应的样式,和正常写样式的方法没有区别。

新建的模版文件里面只能存放模版的wxml和wxss文件,目前小程序的模版文件里面放入其他的文件类型不起作用,不能进行复用,虽然不报错,比如js文件。

template标签只是一种占位符,告诉编译器这个地方是加载模版代码的,当页面编译完成,这个标签就消失,所以要对与模版文件响应事件,我们就需要在加载模版文件的区域,使用一个可以添加事件的标签把其模版文件包裹起来,比如:view / block

<view bindtap=” ....”> template模版代码 </view>

使用模板代码

编写好了模版代码,怎么样在需要加载模版代码的地方使用呢?

首先,模版代码是在其他文件夹中,使用它,就必然要引入该模版文件,
一般在对应要引入模版文件的文件开头部分引入:

// 在对应的wxml文件中开头引入
<import  src = '模版wxml文件路径' />

// 在对应的wxss文件中开头引入,注意末尾的分号
@import '模版wxss文件路径' ;

然后在引入模版文件的wxml文件,适当位置使用

<template is = '模版的名字' data="{{要绑定到模版的数据}}"

到此,简单的模版引入和模版数据的绑定就完成,当我们要循环模版的时候,只需要如下,在外面加一层标签即可:

// bolck标签的作用是作用事件到template模版上面
<block wx:for=" 服务器获取的数据集"  wx:for-item='item' wx:for-index='index' >
    <template  is = '模版的名字'   data="{{要绑定到模版的数据,一般是服务器获取的一个数据对象item}}"
</block>

2.缓存实践:文章收藏和文章阅读数增加

收藏和Toast提示:

var postsData = require('../../../data/posts-data.js')
var app = getApp();
Page({
    data: {
        isPlayingMusic: false
    },
    onLoad: function (option) {
       //获取传递过来的id
        var postId = option.id;

        //下面读取缓存需要用postId,我们利用currentPostID存储到data里面,这样整个文件就可以都使用这个值了
        this.data.currentPostId = postId;

        //把根据id获取的数据放入到data中
        var postData = postsData.postList[postId];
        this.setData({
            postData: postData
        })

        /*
        posts_collected缓存数据可能类似如下形式(key-value形式,true代表收藏,false方便没收藏)
        posts_collected = {
          0:"true"
          1:"true",
          2:"false",
          3:"true",
          ...
        }
        */

        //读取所有的缓存,key为posts_collected,value是一个对象,为{0:'',1:",2:''};
        var postsCollected = wx.getStorageSync('posts_collected')
        if (postsCollected) {
            //根据点击的postId获取对应页面的缓存
            var postCollected = postsCollected[postId]
            if (postCollected){ //如果缓存存在,我们把collected缓存对应ID的值,即true/false
              this.setData({
                collected: postCollected
              })
            }
        }
        else {//如果不存在缓存
            var postsCollected = {};
            //postsCollected缓存中对应postID设置为false
            postsCollected[postId] = false;
            //如果不存在缓存,则进行设置
            wx.setStorageSync('posts_collected', postsCollected);
        }
        
    },


    //点击已收藏/未收藏图片时函数,主要是针对缓存的处理,根据缓存中collectd的值,以及设置collected的值
    onColletionTap: function (event) {
        this.getPostsCollectedSyc();
        
    },

    //同步
    getPostsCollectedSyc: function () {
        //postCollected是一个对象{0:'',1:'',2:'',...}
        var postsCollected = wx.getStorageSync('posts_collected');
        var postCollected = postsCollected[this.data.currentPostId];
        // 收藏变成未收藏,未收藏变成收藏,但是这只是改变值,没有赋值到data中(showToast赋值到data中)
        postCollected = !postCollected;
        //更新缓存对象中当前数据(currentPostId)的key/value值
        postsCollected[this.data.currentPostId] = postCollected;
        //postsCollected是一个缓存对象{0:'',1:'',2:'',...}
        //postCollected是代表收藏/没收藏的true/false
        this.showToast(postsCollected, postCollected);
    },


    // 更新缓存 收藏成功/取消成功的提示
    showToast: function (postsCollected, postCollected) {
        // 更新文章是否的缓存值,postCollected是一个对象{0:'',1:'',2:'',...}
        wx.setStorageSync('posts_collected', postsCollected);
        // 更新数据绑定变量collected为true/false,从而实现切换图片
        this.setData({
            collected: postCollected
        })
        wx.showToast({
            title: postCollected ? "收藏成功" : "取消成功",
            duration: 1000,
            icon: "success",
            success:function(){

            },
            fail:function(){

            },
            complete:function(){

            }

        })
    },

})

播放音乐:

var postsData = require('../../../data/posts-data.js')
var app = getApp();
Page({
    data: {
        isPlayingMusic: false
    },
    onLoad: function (option) {
       //获取传递过来的id
        var postId = option.id;

        //下面读取缓存需要用postId,我们利用currentPostID存储到data里面,这样整个文件就可以都使用这个值了
        this.data.currentPostId = postId;

        //把根据id获取的数据放入到data中
        var postData = postsData.postList[postId];
        this.setData({
            postData: postData
        })

        //数据的缓存和获取(例如收藏状态,已经收藏过要保持收藏状态)
        /*
        posts_collected缓存数据可能类似如下形式(key-value形式,true代表收藏,false方便没收藏)
        posts_collected = {
          0:"true"
          1:"true",
          2:"false",
          3:"true",
          ...
        }
        */

        //读取所有的缓存,key为posts_collected,value是一个对象,为{0:'',1:",2:''};
        var postsCollected = wx.getStorageSync('posts_collected')
        if (postsCollected) {
            //根据点击的postId获取对应页面的缓存
            var postCollected = postsCollected[postId]
            if (postCollected){ //如果缓存存在,我们把collected缓存对应ID的值,即true/false
              this.setData({
                collected: postCollected
              })
            }
        }
        else {//如果不存在缓存
            var postsCollected = {};
            //postsCollected缓存中对应postID设置为false
            postsCollected[postId] = false;
            //如果不存在缓存,则进行设置
            wx.setStorageSync('posts_collected', postsCollected);
        }

        //把全局的App变量打印出来(测试)
        console.log(app.globalData);

        //g_isPlayingMusic作用主要是新闻详情页的音乐播放和停止,要与播放器音乐播放与停止保持同步(更换图标等同步),
        //需要一个全局变量,因为一个页面返回,变量就会重新初始化。
        //页面返回时g_isPlayingMusic如果为true而且g_currentMusicPostId为当前postId,则此时isPlayingMusic为真
        //定义全局变量g_currentMusicPostID表示哪一个音乐正在被播放,因为A页面你把g_isPlayingMusic
        //设置为true,当你打开B页面此时还为true,这样isPlayingMusic也为true,所以我们要判断正在播放的是否和当前一直
        if (app.globalData.g_isPlayingMusic && app.globalData.g_currentMusicPostId
            === postId) {
            this.setData({
                isPlayingMusic: true
            })
        }
        this.setMusicMonitor();
    },

    //在这改变g_isPlayingMusic的值
    setMusicMonitor: function () {
        //点击播放图标和总控开关都会触发这个函数
        var that = this;
        //监听音乐播放
        wx.onBackgroundAudioPlay(function (event) {
            
            // 播放当前页面音乐才改变图标
            that.setData({
                isPlayingMusic: true
            })
               
            app.globalData.g_isPlayingMusic = true;
            app.globalData.g_currentMusicPostId = that.data.currentPostId;

        });
        //监听音乐暂停
        wx.onBackgroundAudioPause(function () {
            
            that.setData({
                isPlayingMusic: false
            })
            
            //g_isPlayingMusic设置为false
            app.globalData.g_isPlayingMusic = false;
            app.globalData.g_currentMusicPostId = null;
        });
        //监听音乐停止
        wx.onBackgroundAudioStop(function () {
            that.setData({
                isPlayingMusic: false
            })
            //g_isPlayingMusic设置为false
            app.globalData.g_isPlayingMusic = false;
            app.globalData.g_currentMusicPostId = null;
        });
    },

    //点击已收藏/未收藏图片时函数,主要是针对缓存的处理,根据缓存中collectd的值,以及设置collected的值
    onColletionTap: function (event) {
        this.getPostsCollectedSyc();
        
    },

    //同步
    getPostsCollectedSyc: function () {
        //postCollected是一个对象{0:'',1:'',2:'',...}
        var postsCollected = wx.getStorageSync('posts_collected');
        var postCollected = postsCollected[this.data.currentPostId];
        // 收藏变成未收藏,未收藏变成收藏,但是这只是改变值,没有赋值到data中(showToast赋值到data中)
        postCollected = !postCollected;
        //更新缓存对象中当前数据(currentPostId)的key/value值
        postsCollected[this.data.currentPostId] = postCollected;
        //postsCollected是一个缓存对象{0:'',1:'',2:'',...}
        //postCollected是代表收藏/没收藏的true/false
        this.showToast(postsCollected, postCollected);
    },

    // 更新缓存 收藏成功/取消成功的提示
    showToast: function (postsCollected, postCollected) {
        // 更新文章是否的缓存值,postCollected是一个对象{0:'',1:'',2:'',...}
        wx.setStorageSync('posts_collected', postsCollected);
        // 更新数据绑定变量collected为true/false,从而实现切换图片
        this.setData({
            collected: postCollected
        })
        wx.showToast({
            title: postCollected ? "收藏成功" : "取消成功",
            duration: 1000,
            icon: "success",
            success:function(){

            },
            fail:function(){

            },
            complete:function(){

            }

        })
    },

    onMusicTap: function (event) {
        //获取当前ID
        var currentPostId = this.data.currentPostId;
        //通过postData获取音乐url、title和coverImg
        var postData = postsData.postList[currentPostId];

        var isPlayingMusic = this.data.isPlayingMusic;
        if (isPlayingMusic) {
            wx.pauseBackgroundAudio();
            this.setData({
                isPlayingMusic: false
            })
            // app.globalData.g_currentMusicPostId = null;
            app.globalData.g_isPlayingMusic = false;
        }
        else {
            wx.playBackgroundAudio({
                dataUrl: postData.music.url,
                title: postData.music.title,
                coverImgUrl: postData.music.coverImg,
            })
            this.setData({
                isPlayingMusic: true
            })
            app.globalData.g_currentMusicPostId = this.data.currentPostId;
            app.globalData.g_isPlayingMusic = true;
        }
    },

    /*
    * 定义页面分享函数
    */
    onShareAppMessage: function (event) {
        return {
            title: '离思五首·其四',
            desc: '曾经沧海难为水,除却巫山不是云',
            path: '/pages/posts/post-detail/post-detail?id=0'
        }
    }

})

3.小程序中的block

block常用于列表循环(如下图所示)

在这里插入图片描述

<!--pages/posts/post.wxml-->
<import src="post-item/post-item-template.wxml" />

<block wx:for="{{posts_key}}" wx:for-item="item">
    <!--template和block都会在编译后,消失,也就是源代码中没有-->
    <view catchtap='onPostTap' data-postID='{{item.postId}}'> 
      <!--...相当于把之前一个item里面的数据进行展开和平铺了,所以模板里面不需要item了,因为是item里面的内容了-->
      <template is="postItem" data="{{...item}}"></template>
    </view>
</block>

//post-item-template.wxml
<template name="postItem">
    <view class="post-container">
       
       <view class="post-author-date">
           <image class="post-author" src="{{avatar}}"></image>
           <text class="post-date">{{date}}</text>
        </view>
           
        <text class="post-title">{{title}}</text>
        <image class="post-image" src="{{imgSrc}}"></image>
        <text class="post-content">{{content}}</text>
            
        <view class="post-like">
            <image class="post-like-image" src="/images/icon/chat.png"></image>
            <text class="post-like-font">{{collection}}</text>
            <image class="post-like-image" src="/images/icon/view.png"></image>
            <text class="post-like-font">{{reading}}</text>
        </view>

    </view>
</template>

view和block两者的区别是,<view>是一个组件,会在页面上做渲染;<block>不是一个组件,它仅仅是一个包装元素,只接受控制属性,不会在页面中做任何渲染。

参考文章:
https://blog.csdn.net/henryhu712/article/details/80464723
https://www.jianshu.com/p/1ca1787990a9

4.事件驱动和数据优先/数据绑定

事件驱动思想, 使用事件驱动来实现模块之间传递参数与解耦.比如在A模块发射一个事件,在B模块监听这个事件,中间使用数据来进行传递即可,像这里就是在总模块里面监听子模块里面的音乐播放状态。

数据优先思想,改变UI,只需要改变数据绑定的对应的数据就可以,这点和angular,IOS中的RAC,响应式编程思想类似,数据绑定优势还有,一个数据可以绑定多个事件,这样只需要在JS文件里面写上对应的多个事件即可,不像jQuery一样要获取多个dom元素才能进行多个事件描述,可能利于做单元测试。w

5.页面关闭状态丢失和全局变量设置g_isPlayingMusic

var postsData = require('../../../data/posts-data.js')
var app = getApp();
Page({
    data: {
        //音乐的暂停/启动状态
        isPlayingMusic: false
    },
    onLoad: function (option) {
       //获取传递过来的id
        var postId = option.id;

        //下面读取缓存需要用postId,我们利用currentPostID存储到data里面,这样整个文件就可以都使用这个值了
        this.data.currentPostId = postId;

        //把根据id获取的数据放入到data中
        var postData = postsData.postList[postId];
        this.setData({
            postData: postData
        })

        //isPlayingMusic是记录播放状态,collected是缓存里面true/false
        //数据的缓存和获取(例如收藏状态,已经收藏过要保持收藏状态)
        /*
        posts_collected缓存数据可能类似如下形式(key-value形式,true代表收藏,false方便没收藏)
        posts_collected = {
          0:"true"
          1:"true",
          2:"false",
          3:"true",
          ...
        }
        */

        //读取所有的缓存,key为posts_collected,value是一个对象,为{0:'',1:",2:''};
        var postsCollected = wx.getStorageSync('posts_collected')
        if (postsCollected) {
            //根据点击的postId获取对应页面的缓存
            var postCollected = postsCollected[postId]
            if (postCollected){ //如果缓存存在,我们把collected缓存对应ID的值,即true/false
              this.setData({
                collected: postCollected
              })
            }
        }
        else {//如果不存在缓存
            var postsCollected = {};
            //postsCollected缓存中对应postID设置为false
            postsCollected[postId] = false;
            //如果不存在缓存,则进行设置
            wx.setStorageSync('posts_collected', postsCollected);
        }

        //把全局的App变量打印出来(测试)
        console.log(app.globalData);

        //作用主要是新闻详情页的音乐播放和停止,要与播放器音乐播放与停止保持同步(更换图标等同步),
        //需要一个全局变量,因为一个页面返回,变量就会重新初始化。
        //
        if (app.globalData.g_isPlayingMusic && app.globalData.g_currentMusicPostId
            === postId) {
            this.setData({
                isPlayingMusic: true
            })
        }
        this.setMusicMonitor();
    },

    //在这改变g_isPlayingMusic的值
    setMusicMonitor: function () {
        //点击播放图标和总控开关都会触发这个函数
        var that = this;
        //监听音乐播放
        wx.onBackgroundAudioPlay(function (event) {
            var pages = getCurrentPages();
            var currentPage = pages[pages.length - 1];
            if (currentPage.data.currentPostId === that.data.currentPostId) {
                // 打开多个post-detail页面后,每个页面不会关闭,只会隐藏。通过页面栈拿到到
                // 当前页面的postid,只处理当前页面的音乐播放。
                if (app.globalData.g_currentMusicPostId == that.data.currentPostId) {
                    // 播放当前页面音乐才改变图标
                    that.setData({
                        isPlayingMusic: true
                    })
                }
                // if(app.globalData.g_currentMusicPostId == that.data.currentPostId )
                // app.globalData.g_currentMusicPostId = that.data.currentPostId;
            }
            // 音乐播放了,就把g_isPlayingMusic设置为true
            app.globalData.g_isPlayingMusic = true;

        });
        //监听音乐暂停
        wx.onBackgroundAudioPause(function () {
            var pages = getCurrentPages();
            var currentPage = pages[pages.length - 1];
            if (currentPage.data.currentPostId === that.data.currentPostId) {
                if (app.globalData.g_currentMusicPostId == that.data.currentPostId) {
                    that.setData({
                        isPlayingMusic: false
                    })
                }
            }
            //g_isPlayingMusic设置为false
            app.globalData.g_isPlayingMusic = false;
            // app.globalData.g_currentMusicPostId = null;
        });
        //监听音乐停止
        wx.onBackgroundAudioStop(function () {
            that.setData({
                isPlayingMusic: false
            })
            //g_isPlayingMusic设置为false
            app.globalData.g_isPlayingMusic = false;
            // app.globalData.g_currentMusicPostId = null;
        });
    },

    //点击已收藏/未收藏图片时函数,主要是针对缓存的处理,根据缓存中collectd的值,以及设置collected的值
    onColletionTap: function (event) {
        // this.getPostsCollectedSyc();
        this.getPostsCollectedAsy();
    },

    //异步
    getPostsCollectedAsy: function () {
        var that = this;
        wx.getStorage({
            key: "posts_collected",
            success: function (res) {
                //getStorage成功回调success,res.data就是返回数据,就是缓存
                var postsCollected = res.data;
                //this.data.currentPostID是对应数据的ID,然后根据ID从缓存数据postCollected中取对应缓存。
                //为什么是currentPostId,因为涉及到postId传递的问题,上面我们把currentPostId传递到data中了
                var postCollected = postsCollected[that.data.currentPostId];
               
                // 收藏变成未收藏,未收藏变成收藏(postCollected取反)
                postCollected = !postCollected;
                //取反之后,更新缓存,这个只是更新缓存中value的值,我们还要进行setStorageSync和把data中的collected进行设置
                postsCollected[that.data.currentPostId] = postCollected;

                //更新文章是否的缓存值,wx.setStorageSync('posts_collected', postsCollected);,这是把key和更新后的value对应起来
                //更新数据绑定变量,从而实现切换图片
                /*
                this.setData({
                    collected: postCollected
                })
                */

                //收藏成功/取消成功的提示
                that.showToast(postsCollected, postCollected);
            }
        })
    },

    //同步
    getPostsCollectedSyc: function () {
        //postCollected是一个对象{0:'',1:'',2:'',...}
        var postsCollected = wx.getStorageSync('posts_collected');
        var postCollected = postsCollected[this.data.currentPostId];
        // 收藏变成未收藏,未收藏变成收藏,但是这只是改变值,没有赋值到data中(showToast赋值到data中)
        postCollected = !postCollected;
        //更新缓存对象中当前数据(currentPostId)的key/value值
        postsCollected[this.data.currentPostId] = postCollected;
        //postsCollected是一个缓存对象{0:'',1:'',2:'',...}
        //postCollected是代表收藏/没收藏的true/false
        this.showToast(postsCollected, postCollected);
    },

    showModal: function (postsCollected, postCollected) {
        var that = this;
        wx.showModal({
            title: "收藏",
            content: postCollected ? "收藏该文章?" : "取消收藏该文章?",
            showCancel: "true",
            cancelText: "取消",
            cancelColor: "#333",
            confirmText: "确认",
            confirmColor: "#405f80",
            success: function (res) {
                if (res.confirm) {
                    wx.setStorageSync('posts_collected', postsCollected);
                    // 更新数据绑定变量,从而实现切换图片,根据collected为true/false更新数据
                    that.setData({
                        collected: postCollected
                    })
                }
            }
        })
    },

    // 更新缓存 收藏成功/取消成功的提示
    showToast: function (postsCollected, postCollected) {
        // 更新文章是否的缓存值,postCollected是一个对象{0:'',1:'',2:'',...}
        wx.setStorageSync('posts_collected', postsCollected);
        // 更新数据绑定变量collected为true/false,从而实现切换图片
        this.setData({
            collected: postCollected
        })
        wx.showToast({
            title: postCollected ? "收藏成功" : "取消成功",
            duration: 1000,
            icon: "success",
            success:function(){

            },
            fail:function(){

            },
            complete:function(){

            }

        })
    },

    //用户分享触发的函数
    onShareTap: function (event) {
        var itemList = [
            "分享给微信好友",
            "分享到朋友圈",
            "分享到QQ",
            "分享到微博"
        ];
        //showActionSheet是显示操作菜单
        wx.showActionSheet({
            itemList: itemList,
            itemColor: "#405f80",
            success: function (res) {   //如果成功,则弹出模拟框
                // res.cancel 用户是不是点击了取消按钮
                // res.tapIndex 数组元素的序号,从0开始
                wx.showModal({
                    title: "用户 " + itemList[res.tapIndex],
                    content: "用户是否取消?" + res.cancel + "现在无法实现分享功能,什么时候能支持呢"
                })
            }
        })
    },

    onMusicTap: function (event) {
        //获取当前ID
        var currentPostId = this.data.currentPostId;
        //通过postData获取音乐url、title和coverImg
        var postData = postsData.postList[currentPostId];

        //获取音乐是启动/暂停状态
        var isPlayingMusic = this.data.isPlayingMusic;

        if (isPlayingMusic) {//如果是true说明正在播放,我们点击就会暂停,同时还要设置isPlayingMusic记录此时音乐播放状态,方便下次判断
            wx.pauseBackgroundAudio();
            this.setData({
                isPlayingMusic: false
            })
            // app.globalData.g_currentMusicPostId = null;
            //需要一个全局变量,这样不同页面才能共享音乐播放状态
            app.globalData.g_isPlayingMusic = false;
        }
        else {//如果是false,说明停止播放了,我们点击就会播放,同时也要记录此时的音乐播放状态,方便下次进行判断
            wx.playBackgroundAudio({
                dataUrl: postData.music.url,
                title: postData.music.title,
                coverImgUrl: postData.music.coverImg,
            })
            this.setData({
                isPlayingMusic: true
            })
            //播放时候,我们要用全局变量记录哪一首被播放
            app.globalData.g_currentMusicPostId = this.data.currentPostId;

            app.globalData.g_isPlayingMusic = true;
        }
    },

    /*
    * 定义页面分享函数
    */
    onShareAppMessage: function (event) {
        return {
            title: '离思五首·其四',
            desc: '曾经沧海难为水,除却巫山不是云',
            path: '/pages/posts/post-detail/post-detail?id=0'
        }
    }

})

本来以为data里面有isPlayingMusic记录播放状态,页面关闭之后应该有状态啊,后来想了想页面进入时候data中isPlayingMusic是false,没有改变,因为我们在页面改变是通过点击事件改变isPlayingMusic状态,当我们重新进入页面时候只会执行onLoad函数,此时isPlayingMusic状态只能是data中设定的。

所以,当我们页面关闭之后,所有的状态都会恢复到初始状态,不符合音乐播放状态的要求,所以,要一个与页面无关的状态保持,当我页面关闭的时候,这个状态依然保持着变量,而当我的应用程序全部关闭之后,这些所有的状态变量会恢复到默认值,全局变量合适App({})。

参考文章:
https://segmentfault.com/a/1190000013298922#articleHeader2
https://segmentfault.com/a/1190000013513917

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值