ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

案例:todo

2021-07-19 12:33:28  阅读:171  来源: 互联网

标签:vue list 案例 components 组件 import todo id


根据已有的文件让vue文件跑起来怎么做?
在这里插入图片描述
在这里插入图片描述

1.根据已有的 package.json 下依赖包 yarn install / yarn(可以省略 install)

完成
在这里插入图片描述

todo案例

完整效果演示

在这里插入图片描述

todo案例-创建工程和组件

目标: 新建工程, 准备好所需的一切

  • 需求1: 创建新工程
  • 需求2: 分组件创建 – 准备标签和样式

分析:

​ ①:初始化todo工程

​ ②:创建3个组件和里面代码

​ ③:把styles的样式文件准备好

​ ④: App.vue引入注册使用, 最外层容器类名todoapp

预先准备: 把styles的样式文件准备好(从预习资料复制), 在App.vue引入使用

// 1.0 样式引入
import "./styles/base.css"
import "./styles/index.css"

根据需求: 我们定义3个组件准备复用

在这里插入图片描述

components/TodoHeader.vue - 复制标签和类名


<template>
  <header class="header">
    <h1>todos</h1>
    <input id="toggle-all" class="toggle-all" type="checkbox" >
    <label for="toggle-all"></label>
    <input
      class="new-todo"
      placeholder="输入任务名称-回车确认"
      autofocus
    />
  </header>
</template>

<script>
export default {
 
}
</script>

components/TodoMain.vue - 复制标签和类名

<template>
  <ul class="todo-list">
    <!-- completed: 完成的类名 -->
    <li class="completed" >
      <div class="view">
        <input class="toggle" type="checkbox" />
        <label>任务名</label>
        <button class="destroy"></button>
      </div>
    </li>
  </ul>
  
</template>

<script>
export default {
}
</script>

components/TodoFooter.vue - 复制标签和类名

<template>
  <footer class="footer">
    <span class="todo-count">剩余<strong>数量值</strong></span>
    <ul class="filters">
      <li>
        <a class="selected" href="javascript:;" >全部</a>
      </li>
      <li>
        <a href="javascript:;">未完成</a>
      </li>
      <li>
        <a href="javascript:;" >已完成</a>
      </li>
    </ul>
    <button class="clear-completed" >清除已完成</button>
  </footer>
</template>

<script>
export default {

}
</script>

App.vue中引入和使用

<template>
  <section class="todoapp">
    <!-- 除了驼峰, 还可以使用-转换链接 -->
    <TodoHeader></TodoHeader>
    <TodoMain></TodoMain>
    <TodoFooter></TodoFooter>
  </section>
</template>

<script>
// 1.0 样式引入
import "./styles/base.css"
import "./styles/index.css"
    
import TodoHeader from "./components/TodoHeader";
import TodoMain from "./components/TodoMain";
import TodoFooter from "./components/TodoFooter";


export default {
  components: {
    TodoHeader,
    TodoMain,
    TodoFooter,
  },
};
</script>

todo案例-铺设待办任务

目的: 把待办任务, 展示到页面TodoMain.vue组件上

  • 需求1: 把待办任务, 展示到页面TodoMain.vue组件上
  • 需求2: 关联选中状态, 设置相关样式

分析:

​ ①: App.vue – 准备数组传入TodoMain.vue内

​ ②: v-for循环展示数据

​ ③: v-model绑定复选框选中状态

​ ④: 根据选中状态, 设置完成划线样式

App.vue

 <TodoMain :arr="showArr"></TodoMain>

export default {
  data() {
    return {
      list: [
        { id: 100, name: "吃饭", isDone: true },
        { id: 201, name: "睡觉", isDone: false },
        { id: 103, name: "打豆豆", isDone: true },
      ],
    };
  }
};

TodoMain.vue

<template>
  <ul class="todo-list">
    <!-- 2.2 循环任务-关联选中状态-铺设数据 -->
    <!-- completed: 完成的类名 -->
    <li :class="{completed: obj.isDone}" v-for="(obj, index) in arr" :key='obj.id'>
      <div class="view">
        <input class="toggle" type="checkbox" v-model="obj.isDone"/>
        <label>{{ obj.name }}</label>
        <!-- 4.0 注册点击事件 -->
        <button @click="delFn(index)" class="destroy"></button>
      </div>
    </li>
  </ul>
</template>

<script>
export default {
  props: ["list"]
};
</script>

<style>
</style>

todo案例-添加任务

目标: 在顶部输入框输入要完成的任务名, 敲击回车, 完成新增功能

  • 需求: 输入任务敲击回车, 新增待办任务

分析:

​ ①: TodoHeader.vue – 输入框 – 键盘事件 – 回车按键

​ ②: 子传父, 把待办任务 – App.vue中 – 加入数组list里

​ ③: 原数组改变, 所有用到的地方都会更新

​ ④: 输入框为空, 提示用户必须输入内容

子组件:TodoHeader.vue

<template>
  <header class="header">
    <h1>todos</h1>
    <input id="toggle-all" class="toggle-all" type="checkbox" />
    <label for="toggle-all"></label>
    <!-- 3.0 v-model       双向绑定获取输入框的值  -->
    <!-- 3.1 @keyup.enter  监听用户按下回车  -->
    <input
      class="new-todo"
      placeholder="输入任务名称-回车确认"
      autofocus
      v-model.trim="task"
      @keyup.enter="downFn"
    />
  </header>
</template>

<script>
export default {
  data() {
    return {
      task: "",
    };
  },
  methods: {
    downFn() {
      if (this.task === "") {
        return alert("请输入用户名称");
      }
      // console.log("用户按下了回车键", this.task);
      // 3.2(重要) - 当前任务名字要加到list数组里
      this.$emit("create", this.task);
      // 为了更好地用户体验,清空输入框
      this.task = "";
    },
  },
};
</script>

父组件:综合案例_Todo.vue

<template>
  <!-- 1.3 在根标签添加 todoapp 类名 -->
  <div class="todoapp">
    <!-- 3.2 注册自定义事件 让子组件触发 -->
    <TodoHender @create="createFn"></TodoHender>
    <TodoMain :arr="list"></TodoMain>
    <TodoFooter></TodoFooter>
  </div>
</template>

<script>
// 1.1 使用组件的四个步骤:  新建组件( vue 文件)  2.引入组件 import  3.注册组件 components  4.使用组件
import TodoFooter from "./components/TodoFooter.vue";
import TodoMain from "./components/TodoMain.vue";
import TodoHender from "./components/TodoHender.vue";
// 1.2 样式引入
import "./styles/base.css";
import "./styles/index.css";
export default {
  // components:定义组件的结构
  components: {
    TodoFooter,
    TodoMain,
    TodoHender,
  },
  // data:定义数据的结构
  data() {
    return {
      list: [
        { id: 100, name: "吃饭", isDone: true },
        { id: 101, name: "睡觉", isDone: false },
        { id: 103, name: "打豆豆", isDone: true },
      ],
    };
  },
  //methods:定义函数/方法的结构
  methods: {
    createFn(theTesk) {
      // 3.3 push 到数组里
      this.list.push({
        // id 准备
        id: this.list.length ? this.list[this.list.length - 1].id + 1 : 10,
        // 任务是子组件触发自定义事件的时候传过来的
        name: theTesk,
        // 新建的任务默认都是未完成
        isDone: false,
      });
    },
  },
};
</script>

<style>
</style>

todo案例-删除任务

目标: 实现点x, 删除任务功能

  • 需求: 点击任务后的x, 删除当前这条任务

分析:

​ ①: x标签 – 点击事件 – 传入id区分

​ ②: 子传父, 把id传回– App.vue中 – 删除数组list里某个对应的对象

​ ③: 原数组改变, 所有用到的地方都会更新

App.vue - 传入自定义事件等待接收要被删除的序号

父组件:综合案例_Todo.vue

<template>
  <!-- 1.3 在根标签添加 todoapp 类名 -->
  <div class="todoapp">
    <!-- 3.2 注册自定义事件 让子组件触发 -->
    <TodoHender @create="createFn"></TodoHender>
    <TodoMain @del="deleteFn" :arr="list"></TodoMain>
    <TodoFooter></TodoFooter>
  </div>
</template>

<script>
// 1.1 使用组件的四个步骤:  新建组件( vue 文件)  2.引入组件 import  3.注册组件 components  4.使用组件
import TodoFooter from "./components/TodoFooter.vue";
import TodoMain from "./components/TodoMain.vue";
import TodoHender from "./components/TodoHender.vue";
// 1.2 样式引入
import "./styles/base.css";
import "./styles/index.css";
export default {
  // components:定义组件的结构
  components: {
    TodoFooter,
    TodoMain,
    TodoHender,
  },
  // data:定义数据的结构
  data() {
    return {
      list: [
        { id: 100, name: "吃饭", isDone: true },
        { id: 101, name: "睡觉", isDone: false },
        { id: 103, name: "打豆豆", isDone: true },
      ],
    };
  },
  //methods:定义函数/方法的结构
  methods: {
    //   创建任务
    createFn(theTesk) {
      // 3.3 push 到数组里
      this.list.push({
        // id 准备
        id: this.list.length ? this.list[this.list.length - 1].id + 1 : 10,
        // 任务是子组件触发自定义事件的时候传过来的
        name: theTesk,
        // 新建的任务默认都是未完成
        isDone: false,
      });
    },
    // 删除任务
    deleteFn(theId) {
      // 注意:filter 不改变原数组,需要重新赋值
      this.list = this.list.filter((item) => item.id !== theId);
    },
  },
};
</script>

<style>
</style>

子组件:TodoMain.vue

<template>
  <ul class="todo-list">
    <!-- completed: 完成的类名 -->
    <li v-for="item in arr" :key="item.id" :class="{ completed: item.isDone }">
      <div class="view">
        <input v-model="item.isDone" class="toggle" type="checkbox" />
        <label>{{ item.name }}</label>
        <button class="destroy" @click="destroyBtn(item.id)"></button>
      </div>
    </li>
  </ul>
</template>

<script>
export default {
  // 接收父组件的数据
  props: ["arr"],
  methods: {
    destroyBtn(id) {
      // console.log("点击了删除按钮", id);
      this.$emit("del", id);
    },
  },
};
</script>

todo案例-底部统计

目的: 显示现在任务的总数

  • 需求: 统计当前任务的条数

分析:

​ ①: App.vue中 – 数组list – 传给TodoFooter.vue

​ ②: 直接在标签上显示 / 定义计算属性用于显示都可以

​ ③: 原数组只要改变, 所有用到此数组的地方都会更新

TodoFooter.vue - 接收list统计直接显示
子组件:TodoFooter.vue

<template>
  <footer class="footer">
    <span class="todo-count"
      >剩余<strong>{{ count }}</strong></span
    >
    <ul class="filters">
      <li>
        <a class="selected" href="javascript:;">全部</a>
      </li>
      <li>
        <a href="javascript:;">未完成</a>
      </li>
      <li>
        <a href="javascript:;">已完成</a>
      </li>
    </ul>
    <button class="clear-completed">清除已完成</button>
  </footer>
</template>

<script>
export default {
  props: ["farr"],
  // 通过 computed 计算结构
  computed: {
    count() {
      return this.farr.length;
    },
  },
};
</script>

父组件:综合案例_Todo.vue

<template>
  <!-- 1.3 在根标签添加 todoapp 类名 -->
  <div class="todoapp">
    <!-- 3.2 注册自定义事件 让子组件触发 -->
    <TodoHender @create="createFn"></TodoHender>
    <TodoMain @del="deleteFn" :arr="list"></TodoMain>
    <TodoFooter :farr="list"></TodoFooter>
  </div>
</template>

<script>
// 1.1 使用组件的四个步骤:  新建组件( vue 文件)  2.引入组件 import  3.注册组件 components  4.使用组件
import TodoFooter from "./components/TodoFooter.vue";
import TodoMain from "./components/TodoMain.vue";
import TodoHender from "./components/TodoHender.vue";
// 1.2 样式引入
import "./styles/base.css";
import "./styles/index.css";
export default {
  // components:定义组件的结构
  components: {
    TodoFooter,
    TodoMain,
    TodoHender,
  },
  // data:定义数据的结构
  data() {
    return {
      list: [
        { id: 100, name: "吃饭", isDone: true },
        { id: 101, name: "睡觉", isDone: false },
        { id: 103, name: "打豆豆", isDone: true },
      ],
    };
  },
  //methods:定义函数/方法的结构
  methods: {
    //   创建任务
    createFn(theTesk) {
      // 3.3 push 到数组里
      this.list.push({
        // id 准备
        id: this.list.length ? this.list[this.list.length - 1].id + 1 : 10,
        // 任务是子组件触发自定义事件的时候传过来的
        name: theTesk,
        // 新建的任务默认都是未完成
        isDone: false,
      });
    },
    // 删除任务
    deleteFn(theId) {
      // 注意:filter 不改变原数组,需要重新赋值
      this.list = this.list.filter((item) => item.id !== theId);
    },
  },
};
</script>

<style>
</style>

todo案例-数据切换

目的: 点击底部切换数据

  • 需求1: 点击底部切换 – 点谁谁有边框
  • 需求2: 对应切换不同数据显示

分析:

​ ①: TodoFooter.vue – 定义isSel – 值为all, yes, no其中一种

​ ②: 多个class分别判断谁应该有类名selected

​ ③: 点击修改isSel的值

​ ④: 子传父, 把类型isSel传到 综合案例_Todo.vue

​ ⑤: 定义计算属性showArr, 决定从list里显示哪些数据给TodoMain.vue和TodoFooter.vue

父组件:综合案例_Todo.vue

<template>
  <!-- 1.3 在根标签添加 todoapp 类名 -->
  <div class="todoapp">
    <!-- 3.2 注册自定义事件 让子组件触发 -->
    <TodoHender @create="createFn"></TodoHender>
    <TodoMain @del="deleteFn" :arr="showArr"></TodoMain>
    <TodoFooter @changeType="typeFn" :farr="showArr"></TodoFooter>
  </div>
</template>

<script>
// 1.1 使用组件的四个步骤:  新建组件( vue 文件)  2.引入组件 import  3.注册组件 components  4.使用组件
import TodoFooter from "./components/TodoFooter.vue";
import TodoMain from "./components/TodoMain.vue";
import TodoHender from "./components/TodoHender.vue";
// 1.2 样式引入
import "./styles/base.css";
import "./styles/index.css";
export default {
  // components:定义组件的结构
  components: {
    TodoFooter,
    TodoMain,
    TodoHender,
  },
  // data:定义数据的结构
  data() {
    return {
      list: [
        { id: 100, name: "吃饭", isDone: true },
        { id: 101, name: "睡觉", isDone: false },
        { id: 103, name: "打豆豆", isDone: true },
      ],
      getSel:'all',
    };
  },
  //methods:定义函数/方法的结构
  methods: {
    //   创建任务
    createFn(theTesk) {
      // 3.3 push 到数组里
      this.list.push({
        // id 准备
        id: this.list.length ? this.list[this.list.length - 1].id + 1 : 10,
        // 任务是子组件触发自定义事件的时候传过来的
        name: theTesk,
        // 新建的任务默认都是未完成
        isDone: false,
      });
    },
    // 删除任务
    deleteFn(theId) {
      // 注意:filter 不改变原数组,需要重新赋值
      this.list = this.list.filter((item) => item.id !== theId);
    },
    // 切换任务
    typeFn(theSel){
      this.getSel = theSel
    }
  },
  // computed 写计算属性的结构(算出来新的变量)
  computed: {
    showArr(){
      if( this.getSel === 'yes'){
        return this.list.filter(item => item.isDone === true)
      }else if(this.getSel === 'no'){
        return this.list.filter(item => item.isDone === false)
      }else{
        return this.list
      }
    }
  }
};
</script>

<style>
</style>

子组件:TodoFooter.vue

<template>
  <footer class="footer">
    <span class="todo-count"
      >剩余<strong>{{ count }}</strong></span
    >
    <ul class="filters">
      <li>
        <a :class="{selected :  isSel === 'all'}" href="javascript:;" @click="changeSel('all')" >全部</a>
        
      </li>
      <li>
        <a :class="{selected :  isSel === 'no'}" href="javascript:;" @click="changeSel('no')" >未完成</a>
      </li>
      <li>
        <a :class="{selected :  isSel === 'yes'}" href="javascript:;" @click="changeSel('yes')">已完成</a>
      </li>
    </ul>
    <button class="clear-completed">清除已完成</button>
  </footer>
</template>

<script>
export default {
  props: ["farr"],
  data () {
          return {
            // all 全部, no  未完成, yes  已完成
          isSel:"all"  
    }
  },
  methods: {
    changeSel(sel){
      // 点击时按钮添加边框
      this.isSel = sel
      // 触发父子间上的自定义事件,把 选中的类型 传到父组件中
      this.$emit('changeType', sel)
      
    }
  },
  // 通过 computed 计算结构
  computed: {
    count() {
      return this.farr.length;
    },
  },
};
</script>

todo案例-清空已完成

目的: 点击右下角按钮- 把已经完成的任务清空了

  • 需求: 点击右下角链接标签, 清除已完成任务

分析:

​ ①: 清空标签 – 点击事件

​ ②: 子传父 – App.vue – 一个清空方法

​ ③: 过滤未完成的覆盖list数组 (不考虑恢复)

综合案例_Todo.vue - 先传入一个自定义事件-因为得接收TodoFooter.vue里的点击事件

父组件:综合案例_Todo.vue

<template>
  <!-- 1.3 在根标签添加 todoapp 类名 -->
  <div class="todoapp">
    <!-- 3.2 注册自定义事件 让子组件触发 -->
    <TodoHender @create="createFn"></TodoHender>
                            <!--  换成计算出来的 showArr 数组  -->
    <TodoMain @del="deleteFn" :arr="showArr"></TodoMain>
    <TodoFooter @changeType="typeFn" @clear="clearFn" :farr="showArr"></TodoFooter>
  </div>
</template>

<script>
// 1.1 使用组件的四个步骤:  新建组件( vue 文件)  2.引入组件 import  3.注册组件 components  4.使用组件
import TodoFooter from "./components/TodoFooter.vue";
import TodoMain from "./components/TodoMain.vue";
import TodoHender from "./components/TodoHender.vue";
// 1.2 样式引入
import "./styles/base.css";
import "./styles/index.css";
export default {
  // components:定义组件的结构
  components: {
    TodoFooter,
    TodoMain,
    TodoHender,
  },
  // data:定义数据的结构
  data() {
    return {
      list: [
        { id: 100, name: "吃饭", isDone: true },
        { id: 101, name: "睡觉", isDone: false },
        { id: 103, name: "打豆豆", isDone: true },
      ],
      getSel:'all',
    };
  },
  //methods:定义函数/方法的结构
  methods: {
    //   创建任务
    createFn(theTesk) {
      // 3.3 push 到数组里
      this.list.push({
        // id 准备
        id: this.list.length ? this.list[this.list.length - 1].id + 1 : 10,
        // 任务是子组件触发自定义事件的时候传过来的
        name: theTesk,
        // 新建的任务默认都是未完成
        isDone: false,
      });
    },
    // 删除任务
    deleteFn(theId) {
      // 注意:filter 不改变原数组,需要重新赋值
      this.list = this.list.filter((item) => item.id !== theId);
    },
    // 切换任务
    typeFn(theSel){
      this.getSel = theSel
    },
    // 清除已完成
    clearFn(){
      // 真是修改了 list
      this.list = this.list.filter(item => item.isDone !== true)
    }
  },
  // computed 写计算属性的结构(算出来新的变量)
  computed: {
    showArr(){
      if( this.getSel === 'yes'){
        return this.list.filter(item => item.isDone === true)
      }else if(this.getSel === 'no'){
        return this.list.filter(item => item.isDone === false)
      }else{
        return this.list
      }
    }
  }
};
</script>

<style>
</style>

子组件:TodoFooter.vue

<template>
  <footer class="footer">
    <span class="todo-count"
      >剩余<strong>{{ count }}</strong></span
    >
    <ul class="filters">
      <li>
        <a :class="{selected :  isSel === 'all'}" href="javascript:;" @click="changeSel('all')" >全部</a>
        
      </li>
      <li>
        <a :class="{selected :  isSel === 'no'}" href="javascript:;" @click="changeSel('no')" >未完成</a>
      </li>
      <li>
        <a :class="{selected :  isSel === 'yes'}" href="javascript:;" @click="changeSel('yes')">已完成</a>
      </li>
    </ul>
    <button class="clear-completed" @click="clearBtn">清除已完成</button>
  </footer>
</template>

<script>
export default {
  props: ["farr"],
  data () {
          return {
            // all 全部, no  未完成, yes  已完成
          isSel:"all"  
    }
  },
  methods: {
    changeSel(sel){
      // 点击时按钮添加边框
      this.isSel = sel
      // 触发父子间上的自定义事件,把 选中的类型 传到父组件中
      this.$emit('changeType', sel)
    },
    clearBtn(){
      this.$emit('clear')
    }
  },
  // 通过 computed 计算结构
  computed: {
    count() {
      return this.farr.length;
    },
  },
};
</script>

todo案例-数据缓存

目的: 新增/修改状态/删除 后, 马上把数据同步到浏览器本地存储

  • 需求: 无论如何变化 – 都保证刷新后数据还在

分析:

​ ①:~Todo.vue – 侦听list数组改变 – 深度

​ ②: 覆盖式存入到本地 – 注意本地只能存入JSON字符串

​ ③: 刷新页面 – list应该默认从本地取值 – 要考虑

父组件:Todo.vue

<template>
  <!-- 1.3 在根标签添加 todoapp 类名 -->
  <div class="todoapp">
    <!-- 3.2 注册自定义事件 让子组件触发 -->
    <TodoHender @create="createFn"></TodoHender>
                            <!--  换成计算出来的 showArr 数组  -->
    <TodoMain @del="deleteFn" :arr="showArr"></TodoMain>
    <TodoFooter @changeType="typeFn" @clear="clearFn" :farr="showArr"></TodoFooter>
  </div>
</template>

<script>
// 1.1 使用组件的四个步骤:  新建组件( vue 文件)  2.引入组件 import  3.注册组件 components  4.使用组件
import TodoFooter from "./components/TodoFooter.vue";
import TodoMain from "./components/TodoMain.vue";
import TodoHender from "./components/TodoHender.vue";
// 1.2 样式引入
import "./styles/base.css";
import "./styles/index.css";
export default {
  // components:定义组件的结构
  components: {
    TodoFooter,
    TodoMain,
    TodoHender,
  },
  // data:定义数据的结构
  data() {
    return {
      list:JSON.parse(localStorage.getItem('todoList')) || [
        { id: 100, name: "吃饭", isDone: true },
        { id: 101, name: "睡觉", isDone: false },
        { id: 103, name: "打豆豆", isDone: true },
      ],
      getSel:'all',
    };
  },
  //methods:定义函数/方法的结构
  methods: {
    //   创建任务
    createFn(theTesk) {
      // 3.3 push 到数组里
      this.list.push({
        // id 准备
        id: this.list.length ? this.list[this.list.length - 1].id + 1 : 10,
        // 任务是子组件触发自定义事件的时候传过来的
        name: theTesk,
        // 新建的任务默认都是未完成
        isDone: false,
      });
    },
    // 删除任务
    deleteFn(theId) {
      // 注意:filter 不改变原数组,需要重新赋值
      this.list = this.list.filter((item) => item.id !== theId);
    },
    // 切换任务
    typeFn(theSel){
      this.getSel = theSel
    },
    // 清除已完成
    clearFn(){
      // 真是修改了 list
      this.list = this.list.filter(item => item.isDone !== true)
    }
  },
  // computed 写计算属性的结构(算出来新的变量)
  computed: {
    showArr(){
      if( this.getSel === 'yes'){
        return this.list.filter(item => item.isDone === true)
      }else if(this.getSel === 'no'){
        return this.list.filter(item => item.isDone === false)
      }else{
        return this.list
      }
    }
  },
  watch: {
    list:{
      deep:true,
      handler(){
        localStorage.setItem('todoList',JSON.stringify(this.list))
      }
      
    }
  }
};
</script>

<style>
</style>

todo案例-全选功能

目标: 点击左上角v号, 可以设置一键完成, 再点一次取消全选

  • 需求1: 点击全选 – 小选框受到影响
  • 需求2: 小选框都选中(手选) – 全选自动选中状态

分析:

​ ①: TodoHeader.vue – 计算属性 - isAll

​ ②: App.vue – 传入数组list – 在isAll的set里影响小选框

​ ③: isAll的get里统计小选框最后状态, 影响isAll – 影响全选状态

​ ④: 考虑无数据情况空数组 – 全选不应该勾选

提示: 就是遍历所有的对象, 修改他们的完成状态属性的值

子组件:TodoHender.vue

<template>
  <header class="header">
    <h1>todos</h1>
    <input id="toggle-all" class="toggle-all" type="checkbox" v-model="isAll" />
    <label for="toggle-all"></label>
    <!-- 3.0 v-model       双向绑定获取输入框的值  -->
    <!-- 3.1 @keyup.enter  监听用户按下回车  -->
    <input
      class="new-todo"
      placeholder="输入任务名称-回车确认"
      autofocus
      v-model.trim="task"
      @keyup.enter="downFn"
    />
  </header>
</template>

<script>
export default {
  props:['arr'],
  data() {
    return {
      task: "",
    };
  },
  methods: {
    downFn() {
      if (this.task === "") {
        return alert("请输入用户名称");
      }
      // console.log("用户按下了回车键", this.task);
      // 3.2(重要) - 当前任务名字要加到list数组里
      this.$emit("create", this.task);
      // 为了更好地用户体验,清空输入框
      this.task = "";
    },
  },
  computed: {
    isAll:{
      get(){
        return this.arr.every(item => item.isDone === true)
      },
      set(val){
        this.arr.forEach(item => item.isDone = val)
      }
    }
  }
};
</script>

父组件:综合案例_Todo.vue

<template>
  <!-- 1.3 在根标签添加 todoapp 类名 -->
  <div class="todoapp">
    <!-- 3.2 注册自定义事件 让子组件触发 -->
    <TodoHender :arr="list" @create="createFn"></TodoHender>
                            <!--  换成计算出来的 showArr 数组  -->
    <TodoMain @del="deleteFn" :arr="showArr"></TodoMain>
    <TodoFooter @changeType="typeFn" @clear="clearFn" :farr="showArr"></TodoFooter>
  </div>
</template>

<script>
// 1.1 使用组件的四个步骤:  新建组件( vue 文件)  2.引入组件 import  3.注册组件 components  4.使用组件
import TodoFooter from "./components/TodoFooter.vue";
import TodoMain from "./components/TodoMain.vue";
import TodoHender from "./components/TodoHender.vue";
// 1.2 样式引入
import "./styles/base.css";
import "./styles/index.css";
export default {
  // components:定义组件的结构
  components: {
    TodoFooter,
    TodoMain,
    TodoHender,
  },
  // data:定义数据的结构
  data() {
    return {
      list:JSON.parse(localStorage.getItem('todoList')) || [
        { id: 100, name: "吃饭", isDone: true },
        { id: 101, name: "睡觉", isDone: false },
        { id: 103, name: "打豆豆", isDone: true },
      ],
      getSel:'all',
    };
  },
  //methods:定义函数/方法的结构
  methods: {
    //   创建任务
    createFn(theTesk) {
      // 3.3 push 到数组里
      this.list.push({
        // id 准备
        id: this.list.length ? this.list[this.list.length - 1].id + 1 : 10,
        // 任务是子组件触发自定义事件的时候传过来的
        name: theTesk,
        // 新建的任务默认都是未完成
        isDone: false,
      });
    },
    // 删除任务
    deleteFn(theId) {
      // 注意:filter 不改变原数组,需要重新赋值
      this.list = this.list.filter((item) => item.id !== theId);
    },
    // 切换任务
    typeFn(theSel){
      this.getSel = theSel
    },
    // 清除已完成
    clearFn(){
      // 真是修改了 list
      this.list = this.list.filter(item => item.isDone !== true)
    }
  },
  // computed 写计算属性的结构(算出来新的变量)
  computed: {
    showArr(){
      if( this.getSel === 'yes'){
        return this.list.filter(item => item.isDone === true)
      }else if(this.getSel === 'no'){
        return this.list.filter(item => item.isDone === false)
      }else{
        return this.list
      }
    }
  },
  watch: {
    list:{
      deep:true,
      handler(){
        localStorage.setItem('todoList',JSON.stringify(this.list))
      }
      
    }
  }
};
</script>

<style>
</style>

标签:vue,list,案例,components,组件,import,todo,id
来源: https://blog.csdn.net/Henry_ID/article/details/118754902

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有