小程序生命周期函数到todos项目的实现

参考文档

页面生命周期
页面生命周期函数

生命周期函数的学习

生命周期函数

组件的创建,运行、销毁总是伴随着各种各样的事件;这些在组件特定时期,触发的事件,叫做组件的生命周期函数;也是生命周期钩子

onLoad()

页面加载时触发。一个页面只会调用一次,可以在 onLoad 的参数中获取打开当前页面路径中的参数。

我们在demo页面定义一个navigator路由导航

 <navigator url="/pages/demo1/demo1?title=demo">去到demo1页面</navigator>

最后接着我们在demo1的逻辑层使用onLoad

  onLoad: function (options) {
    console.log(options)
  },

当页面还没有显示完成,数据已经加载触发了打印了{title: "demo"};所以,比如我们需要对data数据初始化或则重新设置,都可以在onLoad里面设置.但是还不能操作视图层

onShow()和onHide()

监听页面的显示和隐藏

onShow页面显示/切入前台时触发。但不是代表页面已经渲染完成
onHide页面隐藏/切入后台时触发。 如 wx.navigateTo 或底部 tab 切换到其他页面,小程序切入后台等。

onReady()

页面初次渲染完成时触发。一个页面只会调用一次,代表页面已经准备妥当,可以和视图层进行交互。注意:对界面内容进行设置的 API 如wx.setNavigationBarTitle,请在onReady之后进行。

onUnload()

监听页面卸载。如wx.redirectTo或wx.navigateBack到其他页面时。

 <navigator
    url="/pages/demo1/demo1?title=demo"
  open-type='redirect'>去到demo1页面</navigator>

我们点击按钮时,跳转到其它界面;但是不会出现返回按钮了。证明当前页面已经被关闭了。所以当跳转到其它页面,历史记录不存在当前页面,就会触发该事件

onPullDownRefresh()和onReachBottom()

监听用户下拉刷新事件
当然需要在app.json进行启动下拉功能

  "window": {
    "enablePullDownRefresh": true
  },
  onPullDownRefresh: function () {
    console.log(' onPullDownRefresh')
  },

onReachBottom:页面上拉触底事件的处理函数

onPageScroll()

监听用户滑动页面事件。

onShareAppMessage(Object object)

监听用户点击页面内转发按钮( 组件 open-type=“share”)或右上角菜单“转发”按钮的行为,并自定义转发内容。

<button open-type='share'>share</button>

当点击button就会触发该事件

图解

图片

我们创建一个todos组件

page文件夹下一个todos组件,我们创建好后发现js文件已经把生命周期函数写进去了;美滋滋。其它组件删除不要了

{
  "pages": [
    "pages/todos/todos"
  ],
  "window": {
    "backgroundTextStyle": "dark",
    "navigationBarBackgroundColor": "#fff",
    "navigationBarTitleText": "TODOS",
    "navigationBarTextStyle": "black",
    "enablePullDownRefresh": true
  },
  "sitemapLocation": "sitemap.json"
}
我先把静态模板文件写了出来
  1. 其实就是使用小程序提供的组件:view、icon、text
  2. 样式的话使用伸缩布局和rpx单位,可以根据屏幕宽度进行自适应。
  3. rpx其实就是屏幕的物理像素
<view class="container">
  <view class='header'>
      <image src='../../assets/plus.png'></image>
      <input type="text" placeholder='Anything here'></input>
  </view>
  <view class='todo_list'>
      <view class='todo_item'>
          <view class='item_con'>
            <icon type="success" />
            <text class='completed'>vue study</text>
          </view>
          <icon type='clear' size="16"></icon>
      </view>
      <view class='todo_item'>
          <view class='item_con'>
            <icon type="circle" />
            <text>vue study</text>
          </view>
          <icon type='clear' size="16"></icon>
      </view>
  </view>
    <view class='footer'>
    <text>Toggle all</text>
    <text>items lift</text>
    <text>clear completed</text>
  </view>
</view>
.container {
  border-top: 1rpx solid #e0e0e0;
}

.header {
  display: flex;
  align-items: center;
  margin: 20rpx;
  padding: 20rpx;
  border: 1rpx solid #e0e0e0;
  border-radius: 5rpx;
  box-shadow: 0 0 5rpx #e0e0e0;
}

.header image {
  width: 40rpx;
  height: 40rpx;
  margin-right: 20rpx;
}

.todos {
  margin: 20rpx;
  border: 1rpx solid #e0e0e0;
  border-radius: 5rpx;
  box-shadow: 0 0 5rpx #e0e0e0;
}

.todos .item {
  display: flex;
  align-items: center;
  padding: 20rpx;
  border-bottom: 1rpx solid #e0e0e0;
}

.todos .item:last-child {
  border-bottom: 0;
}

.todos .item text {
  flex: 1;
  margin-left: 20rpx;
  font-size: 30rpx;
  color: #444;
}

.todo_list .todo_item .item_con text.completed{
  color: #888;
  text-decoration: line-through;
}

.footer {
  display: flex;
  justify-content: space-between;
  margin: 20rpx;
  font-size: 30rpx;
  color: #333;
}

列表渲染

列表渲染

模拟数据

  data: {
    inpMsg:'',
    lift:1,
    todos:[
      { id: 1, name: 'vue learning', completed: false },
      { id: 2, name: 'mini learning', completed: true },
      { id: 3, name: 'react learning', completed: false },
      { id: 4, name: 'angular learning', completed: false },
    ]
  },

将列表渲染到界面上,这里展示部分代码,其它是使用mustache语法进行绑定,补充完整即可

  <view class='todo_list'>
      <view class='todo_item' wx:for="{{todos}}" wx:key="{{index}}">
          <view class='item_con'>
            <icon type='{{item.completed?"success":"circle"}}' />
            <text class='{{item.completed?"completed":""}}'>{{item.name}}</text>
          </view>
          <icon type='clear' size="16"></icon>
      </view>
  </view>

显示结果如图

添加一条数据

点击添加按钮(图片功能),向界面添加一条数据

  1. 首先判断文本框是否有内容this.data.inpMsg,当文本框为空时,禁止添加;
  2. 当文本框有内容时,监听文本框的变化bindinput,通过event事件对象e.detail,value获取文本框的内容;点击添加按钮,向todos添加一条数据(当然可以用dataset来获取)
  3. 数据格式和todos保持一致,初始化completed是未完成,id为递增,name为文本框内容
  <view class='header'>
      <image src='../../assets/plus.png' bindtap='addTodoHandle'></image>
      <input 
      type="text" 
      placeholder='Anything here'
      value='{{inpMsg}}'
      bindinput='getTodoHandle'
      ></input>
  </view>
  getTodoHandle(e){
    this.setData({
      inpMsg:e.detail.value
    })
  },
  addTodoHandle(){
    // 判断文本框
    let msg = this.data.inpMsg
    if (!msg.length){
      return;
    }
    let todos = this.data.todos
    let id = todos.length?todos[todos.length-1].id+1:1
    todos.push({name:msg,id,completed:false})
    this.setData({
      todos,
      inpMsg:''
    })
  },
点击切换completed完成或未完成状态
  1. 给icon绑定一个点击事件bindtap
  2. 给icon添加一个属性,并绑定当前的索引值
  3. 点击根据索引值,切换completed的布尔值
  4. this.setData({})设置数据
            <icon 
            type='{{item.completed?"success":"circle"}}' 
            bindtap='changeCompleted'
            data-index='{{index}}'
            />
  changeCompleted(e){
    // 获取点击时当前的索引值(该索引值也是data数据的索引值)
    let index = e.currentTarget.dataset.index
    let todos = this.data.todos
    todos[index].completed = !todos[index].completed
    this.setData({
      todos
    })
  },
点击clear按钮删除该条数据
  1. 给清除按钮添加一个点击事件,绑定index索引值
  2. 处理函数:根据index进行删除该条数据,可以使用splice,也可以使用filter
  3. 记得需要使用this.setData({})设置数据
          <icon 
          type='clear' 
          size="16" 
          bindtap='clearHandle'
          data-index='{{index}}'
          ></icon>
  clearHandle(e){
    let index = e.currentTarget.dataset.index
    let todos = this.data.todos
    todos = todos.filter((item, i)=>index !== i)
    this.setData({
      todos
    })
  },
Toggle all 切换所有完成状态
  1. 绑定点击事件
  2. 只要有一个是未完成状态completed:false,全部切换为已完成。如果全部是已完成,则切换为全部未完成
<text bindtap='toggleAllHandle'>Toggle all</text>
  toggleAllHandle(){
    let todos = this.data.todos
    let togBool = todos.some(item => !item.completed)//只要有一个未完成,它都返回true,togBool=true;否则返回false
    todos = todos.map(item=>{
      item.completed = togBool
      return item
    })
    this.setData({
      todos
    })
  },
渲染未完成的数量
  1. 当页面加载时,渲染lift,即未完成的todos;也就是completed:false
  onLoad: function (options) {
    this.setData({
      lift: this.data.todos.filter(item => !item.completed).length
    })
  },
  1. 根据页面变化重新渲染数据,之前有setData都加上该条数据,例如删除一条数据的函数,其它自行加上
  clearHandle(e){
    let index = e.currentTarget.dataset.index
    let todos = this.data.todos
    todos = todos.filter((item, i)=>index !== i)
    let lift = todos.filter(item => !item.completed).length
    this.setData({
      todos,
      lift
    })
  },
  1. 因为我们小程序没有像react那样有生命周期函数shouldComponentUpdate(nextProps, nextState)可以监听数据变化,直接一次性加。所以只能一步步加lift
<text>{{lift}} items left</text>
清除已经完成的数据
  1. 绑定点击事件
<text bindtap='clearCompletedHandle'>clear completed</text>
  1. 根据completed删除数据
  clearCompletedHandle(){
    let todos = this.data.todos
    todos = todos.filter(item=>!item.completed)
    this.setData({
      todos
    })
  },

数据持久化

  1. 上面关于todos的业务逻辑已经处理完成,接下来我们要本地存储数据
  2. 当页面进入时,获取本地储存的,初始化todos
  onLoad: function (options) {
    let todos = []
    wx.getStorage({
      key: 'todos',
      success:res=>{
        todos = res.data
        this.setData({
          lift: todos.filter(item => !item.completed).length,
          todos
        })
      }
    })
  },
  1. 在每一步改变数据的操作后存储本地数据
    wx.setStorage({
      key: 'todos',
      data: todos,
    })

改进和建议

  1. 使用less相比于css会更加提高我们的开发效率;我们可以使用koala来编译我们的less文件
  2. 因为生命周期函数和我们绑定的函数都是一起的,不像vue是写在methods里外的;所以我们可以在命名的时加个handle,区分开来。
  3. 最好加个双击编辑功能,可以直接改数据
  4. 当然我们每个函数都要定义todos,可以全局设置定义一个app.globalData

其它参考文档

小程序开发·指南·框架·API等
小程序介绍·开发·注册·主体信息·支付
小程序·开发支持
开发者社区
小程序·云开发

猜你喜欢

转载自blog.csdn.net/weixin_41105030/article/details/90143339
今日推荐