0
点赞
收藏
分享

微信扫一扫

vue组件基础1:todoList之组件化编码

吃面多放酱 2022-03-14 阅读 70

todoList组件化编码流程

所需依赖项:nanoid 生成唯一id,使用npm下载

1.拆分页面结构

├─todoList --------------------------------- // 页面文件夹

│ ├─components ---------------------- // 组件文件夹

│ ├        ├─j-head --------------------- // 头部

│ ├        ├─j-list ----------------------- // 列表

│ ├        ├─j-item --------------------- // 子项

│ ├        ├─j-footer ------------------- // 底部

│ ├─index.vue ------------------------ // 父组件页面

2.页面代码

index.vue

<template>
  <div>
    <div class="todo-list-box">
      <j-head @addTodo="addTodo"></j-head>
      <j-list :todoList="todoList" @delTodo="delTodo" @selectTodo="selectTodo"></j-list>
      <j-footer :todoList="todoList" @delComplete="delComplete" @isAllCheck="isAllCheck"></j-footer>
    </div>
  </div>
</template>

<script>
import jHead from './j-head';
import jList from './j-list';
import jFooter from './j-footer';
import { nanoid } from 'nanoid';
export default {
  components: { jHead, jList, jFooter },
  data() {
    return {
      todoList: [
        {
          id: nanoid(),
          title: '睡觉',
          select: true
        },
        {
          id: nanoid(),
          title: '吃饭',
          select: false
        },
        {
          id: nanoid(),
          title: '学习',
          select: false
        }
      ]
    };
  },
  methods: {
    /** 添加事件 */
    addTodo(obj) {
      this.todoList.unshift(obj);
    },
    /** 删除事件 */
    delTodo(id) {
      if (!confirm('确定删除吗?')) return;
      this.todoList = this.todoList.filter((item) => item.id != id);
    },
    /** 勾选事件 */
    selectTodo(obj) {
      this.todoList.filter((item) => item.id === obj.id)[0].select = !obj.select;
    },
    /** 删除已完成事件 */
    delComplete() {
      this.todoList = this.todoList.filter((item) => !item.select);
    },
    /** 是否全选 */
    isAllCheck(is) {
      this.todoList.forEach((item) => (item.select = is));
    }
  }
};
</script>

<style lang="less" scoped>
.todo-list-box {
  width: 95vw;
  padding: 10px;
  margin: 15px auto;
  border: 1px solid #eee;
  border-radius: 5px;
}
</style>

j-head.vue

<template>
  <div class="j-head-box">
    <input type="text" @keyup.enter="add" />
  </div>
</template>

<script>
import { nanoid } from 'nanoid';
export default {
  methods: {
    /** 添加待办事项 */
    add(e) {
      if (!e.target.value.trim()) return alert('请输入事件名');
      const todoObj = { id: nanoid(), title: e.target.value, select: false };
      this.$emit('addTodo', todoObj);
      e.target.value = '';
    }
  }
};
</script>

<style lang="less" scoped>
.j-head-box {
  width: 100%;
  height: 30px;
  input {
    width: 100%;
    height: 100%;
    border-radius: 5px;
    border: 1px solid #eee;
  }
}
</style>

j-list.vue

<template>
  <div class="j-list-box">
    <template v-for="item in todoList">
      <j-item :key="item.id" :item="item" v-on="$listeners"></j-item>
    </template>
  </div>
</template>

<script>
import jItem from './j-item.vue';
export default {
  components: { jItem },
  props: {
    todoList: Array
  }
};
</script>

<style lnag="less" scoped>
.j-list-box {
  border: 1px solid #eee;
  margin: 10px 0;
  border-radius: 3px;
  border-top: none;
}
</style>

j-item.vue

<template>
  <div class="j-item-box">
    <label>
      <input type="checkbox" :checked="item.select" @change="selectTodo(item)" />
      <span>{{ item.title }}</span>
    </label>
    <button @click="delTodo(item.id)">删除</button>
  </div>
</template>

<script>
export default {
  props: {
    item: Object
  },
  methods: {
    /** 勾选事件 */
    selectTodo(item) {
      this.$emit('selectTodo', item);
    },
    /** 删除事件 */
    delTodo(id) {
      this.$emit('delTodo', id);
    }
  }
};
</script>

<style lang="less" scoped>
.j-item-box {
  display: flex;
  align-items: center;
  font-size: 14px;
  padding: 10px 5px;
  border-top: 1px solid #eee;
  label {
    flex: 1;
    display: flex;
    align-items: center;
  }
  span {
    flex: 1;
    margin-left: 5px;
  }
  button {
    color: white;
    font-size: 12px;
    margin-left: auto;
    background-color: red;
    border: none;
    border-radius: 3px;
    padding: 0 4px;
  }
}
</style>

j-footer.vue

<template>
  <div class="j-footer-box">
    <input type="checkbox" v-model="isAll" />
    <span>已完成{{ completeCount }}/全部{{ todoList.length }}</span>
    <button @click="delComplete">清除全部已完成任务</button>
  </div>
</template>

<script>
export default {
  props: {
    todoList: Array
  },
  computed: {
    /** 计算已完成事件个数 */
    completeCount() {
      return this.todoList.reduce((pre, item) => (item.select ? pre + 1 : pre), 0);
    },
    /** 是否全选 */
    isAll: {
      get() {
        return this.todoList.length === this.completeCount && this.todoList.length > 0;
      },
      set(value) {
        this.$emit('isAllCheck', value);
      }
    }
  },
  methods: {
    /** 清除已完成事项 */
    delComplete() {
      this.$emit('delComplete');
    }
  }
};
</script>

<style lang="less" scoped>
.j-footer-box {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0 5px;
  span {
    flex: 1;
    margin-left: 30px;
  }
  button {
    padding: 2px 5px;
    border: none;
    color: #fff;
    border-radius: 3px;
    background-color: red;
  }
}
</style>

3.涉及知识点

computed:vue中计算计算函数

var vm = new Vue({
        data: { a: 1, b: 1 },
        computed: {
           /** 
           * 仅读取 
           * 一般使用此方法
           * */
          sumB() {
            return this.b + 7;
          },
          /**
           * 读取和设置
           * 特殊情况使用例:v-model使用计算函数绑定时
           * */
          sumA: {
            /** 读取 */
            get() {
              return this.a + 1;
            },
            /** 设置 */
            set(v) {
              this.a = v - 1;
            },
          },
        },
      });

vm.sumB; // sumB = 8
vm.Suma; // 调用get方法结果为 Suma = 2
vm.sumA = 3; // 调用set方法 v = 3, a = 2, sumA = 3

this.$emit(@event,$event):绑定一个自定义事件,当这行代码执行时将参数传给父组件。

参数说明

参数名说明类型
@evnet父组件接收的方法名String
$event父组件接收的参数/

$listeners:是一个对象,内容为组件上的所有监听器

举报

相关推荐

0 条评论