微信小程序快速入门个人学习心得(四)

微信小程序快速入门个人学习心得(三)

TODOS案例

这个案例是要做一个任务清单。

首先 思考一共分为几块内容:
1、输入框
2、任务列表
3、工具栏
因此一共三块,在对应wxml文件中,父容器中添加三个子容器。

<view class="container">
<view class="searchHandle"></view>
<view class="worksHandle"></view>
<view class="utilsHandle"></view>
</view>

对于输入框,又分为左边的添加和后面的输入。
对于任务列表,我们先固定写三个任务去调节样式。
对于工具栏则是三个文本。
在对应wxml中:

<!--index.wxml-->
<view class="container">
  <view class="searchHandle">
    <view class="addHandle">
      <image src="../../images/plus.png"></image>
    </view>
    <view class="inputHandle">
      <input type="text" placeholder="Anything here..."/>
    </view>
  </view>

  <view class="worksHandle">
    <view class="item">
      <icon type="success"></icon>
      <text>学习HTML</text>
      <icon type="clear" size="16"></icon>
    </view>
    <view class="item">
      <icon type="success"></icon>
      <text>学习CSS</text>
      <icon type="clear" size="16"></icon>
    </view>
    <view class="item">
      <icon type="success"></icon>
      <text>学习JS</text>
      <icon type="clear" size="16"></icon>
    </view>
  </view>
  <view class="utilsHandle">
    <text>全选</text>
    <text>还剩2个任务</text>
    <text>清除任务</text>
  </view>
</view>

与之对应的样式:

.container{
    
    
  border-top: 1rpx solid #e0e0e0;
}
.searchHandle{
    
    
  display: flex;
  align-items: center;
  border: 1rpx solid #e0e0e0;
  border-radius: 5rpx;
  box-shadow: 0 0 5rpx #e0e0e0;
  margin: 20rpx;
  padding: 20rpx;
}
.addHandle image{
    
    
  height: 40rpx;
  width: 40rpx;
  margin-right: 20rpx;
}
.worksHandle{
    
    
  border: 1rpx solid #e0e0e0;
  border-radius: 5rpx;
  box-shadow: 0 0 5rpx #e0e0e0;
  margin: 20rpx;
}
.worksHandle .item {
    
    
  display: flex;
  padding : 20rpx;
  border-bottom: 1rpx solid #e0e0e0;
  align-items: center;
}
.worksHandle .item:last-child{
    
    
  border-bottom: 0;
}
.worksHandle .item text {
    
    
  flex: 1;
  font-size: 30rpx;
  color: #444;
  margin: 20rpx;
}
.utilsHandle{
    
    
  margin: 20rpx;
  font-size: 30rpx;
  display: flex;
  justify-content: space-between;
  color: #333;
}

效果图:
在这里插入图片描述
然后 看看有哪些东西需要被抽象成一个数据成员。
一般来说,对于会变换的东西,一般需要把它抽象出来,写到data中。
对于任务清单,由于是一个列表,所以需要把它抽象成一个数组,根据其中元素个数去改变,数组中每个成员为一个对象。
界面上数据绑定的数据来自data中,data中有什么,这里才可以写什么。
对应js

Page({
    
    
  data: {
    
    
    //文本框数据模型
    search: '',
    //任务清单数据模型
    todos: [
      //任务名和完成状态
      {
    
    
        name: 'Learning WEAPP',
        completed: false
      },
      {
    
    
        name: 'Learning JS',
        completed: true
      },
      {
    
    
        name: 'Learning HTML',
        completed: false
      }
    ]
  }
})

修改wxml

<!--index.wxml-->
<view class="container">
  <view class="searchHandle">
    <view class="addHandle">
      <image src="../../images/plus.png"></image>
    </view>
    <view class="inputHandle">
      <input type="text" placeholder="Anything here..." value="{
     
     { search }}" />
    </view>
  </view>

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

  </view>
  <view class="utilsHandle">
    <text>全选</text>
    <text>还剩{
   
   {todos.length}}个任务</text>
    <text>清除任务</text>
  </view>
</view>

再然后: 界面交互。1、先让按钮点击时执行一段代码。2、拿到文本框里面的值。由于小程序的数据绑定是单向的,必须要给给文本注册改变事件,通过e.detail.value拿到当前的值。3、将这个值添加到列表中。
在这里插入图片描述

Page({
    
    
  data: {
    
    
    //文本框数据模型
    search: '',
    //任务清单数据模型
    todos: [
      //任务名和完成状态
      {
    
    
        name: 'Learning HTML',
        completed: false
      },
      {
    
    
        name: 'Learning JS',
        completed: true
      },
      {
    
    
        name: 'Learning Css',
        completed: false
      }
    ],
    leftCount: 2,
    allCompleted: false
  },
  addToDoHandle: function () {
    
    
    //当点击按钮执行的函数,将这个值添加到列表中必须现实的通过setData去改变数据,这样界面上才会得到变化
    if (!this.data.search) return
    var todos = this.data.todos
    todos.push({
    
    
      name: this.data.search,
      completed: false
    })
    this.setData({
    
    
      todos: todos,
      search: '',
      leftCount: this.data.leftCount + 1
    })
  },
  changeHandle: function (e) {
    
    
    this.setData({
    
    
      search: e.detail.value
    })
  },
  toggleTodoHandle: function (e) {
    
    
    //切换当前点中的item的完成状态
    var item = this.data.todos[e.currentTarget.dataset.index]
    item.completed = !item.completed
    //根据当前任务状态决定添加还是减少任务数量
    var leftCount = this.data.leftCount //+ (item.completed ? -1 : 1)
    if (item.completed) {
    
    
      leftCount = leftCount - 1;
    } else {
    
    
      leftCount = leftCount + 1;
    }
    this.setData({
    
    
      todos: this.data.todos,
      leftCount: leftCount
    })
  },
  //需要注意冒泡问题
  clearHandle: function (e) {
    
    
    if (!this.data.todos[e.currentTarget.dataset.index].completed) {
    
    
      this.data.leftCount = this.data.leftCount - 1;
    }
    var todos = this.data.todos
    todos.splice(e.currentTarget.dataset.index, 1)
    //todos中会移除index所指向的元素
    this.setData({
    
    
      todos: todos,
      leftCount: this.data.leftCount
    })
  },
  // this在小程序里永远指向的是当前页面对象而不是事件源对象
  toggleAllHanale: function () {
    
    
    var todos = this.data.todos
    if (this.data.allCompleted == false) {
    
    
      for (let index = 0; index < todos.length; index++) {
    
    
        todos[index].completed = true
      }
      this.data.allCompleted = true
      this.data.leftCount = 0
    } else {
    
    
      for (let index = 0; index < todos.length; index++) {
    
    
        todos[index].completed = false
      }
      this.data.allCompleted = false
      this.data.leftCount = this.data.todos.length
    }

    this.setData({
    
    
      todos: todos,
      leftCount: this.data.leftCount
    })
  },
  removeAllCompletedHandle: function () {
    
    
    //遍历方法:
    // var todos = []
    // this.data.todos.forEach(function (item) {
    
    
    //   if (!item.completed) {
    
    
    //       todos.push(item)
    //   }
    // })

    //filter是过滤,返回值为真添加进新数组,为假不添加
    var todos = this.data.todos.filter(function (item){
    
    
     return !item.completed
    })

    this.setData({
    
    
      todos: todos,
    })
  }
})

对应wxml
其中,value="{ { search }}"是当前文本框的值,bindconfirm="addToDoHandle"是点击完成添加事件。

<!--index.wxml-->
<view class="container">
  <view class="searchHandle">
    <view class="addHandle">
      <image src="../../images/plus.png" bindtap="addToDoHandle"></image>
    </view>
    <view class="inputHandle">
      <input type="text" placeholder="input ..." value="{
     
     { search }}" bindinput="changeHandle" bindconfirm="addToDoHandle"/>
    </view>
  </view>
  <!--如果数组长度不为0则显示,否则显示else-->
<block wx:if="{
     
     {todos.length}}">
    <view class="worksHandle">
    <!--通过三元表达式去控制样式,根据item.completed的取值决定是否添加completed样式。注意:item与花括号之间有个空格-->
    <view class="item {
     
     { item.completed ? 'completed' : ''}}" wx:for="{
     
     { todos }}" bindtap="toggleTodoHandle" data-index="{
     
     {index}}">
      <icon type="{
     
     { item.completed ? 'success' : 'circle'}}"/>
      <text>{
   
   { item.name }}</text>
      <icon type="clear" size="16" catchtap="clearHandle" data-index="{
     
     {index}}"/>
    </view>

  </view>
  <view class="utilsHandle">
    <text bindtap="toggleAllHanale">全选</text>
    <!-- 非0就显示 -->
    <text wx:if="{
     
     {leftCount}}">还剩{
   
   {leftCount}}个任务</text>
    <text bindtap="removeAllCompletedHandle">清除已完成任务</text>
  </view>
</block>
<view wx:else class="final">
  <text>恭喜你完成所有任务</text>
</view>
</view>

对应wxss

.container {
    
    
  border-top: 1rpx solid #e0e0e0;
 
}

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

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

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

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

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

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

.worksHandle .item.completed text {
    
    
  color: #888;
  text-decoration: line-through;
}

.utilsHandle {
    
    
  margin: 20rpx;
  font-size: 30rpx;
  display: flex;
  justify-content: space-between;
  color: #333;
}
.final{
    
    
  height: 800rpx;
  display: flex;
  justify-content: center;
  align-items: center;
}
.final text{
    
    
  font-size: 50rpx;
  color: #888;
}

效果如下:在这里插入图片描述
本次需要提醒注意的事情:
1、block 标签只是为了把两个标签包裹在一起,方便对他们整体进行操作,不会形成任何标签结构。
2、jsforeach用法:

   数组名.forEach(function(value,index,array) {
    
     //code something  });

其中value是必须的,他代表当前数组的每个元素的值。
array[index] == value; //结果为true

java
for(元素类型 元素名称 : 遍历数组(集合)(或者能进行迭代的)){ 语句 }

 for(String str : arr){
    
                          //这里的str就是为了获取每次循环的arr中的值
            System.out.println(str);          //就相当于 String str=arr[i]
 }

3、data-index="{ {index}}"这里的data-index也可以写成其他的,比如data-aaa,但是后面的{ {index}}这个index是系统自己定义的,在这个花括号里只能写系统或者我们自己定义在data中的数据,获取方法就是e.currentTarget.dataset.aaa

结束~

猜你喜欢

转载自blog.csdn.net/zcylxzyh/article/details/112858652
今日推荐