本文状态:未完成

一、产品原型

todo

参考 Windows todo设计一个简单的移动端todo页面原型

二、开发教程

1、新建Todolist.vue

先通过脚手架配置好vue项目:@vue/cli

在项目src\views下面新建Todo.vue

<template>
  <div class="todo">
    <h1>Todolist</h1>
    <input type="text" v-model="content" @keypress="add"><button @click="add">Add</button>
    <p>{{content}}</p>
    <div class="section-title">待办</div>
    <ul class="todolist underway">
      <TodoItem :="todo" v-for="todo in underway" :key="todo.id" :class="{done:todo.status}" v-model="todo.status" />
    </ul>
    <div class="section-title">已完成</div>
    <ul class="todolist completed">
      <TodoItem :="todo" v-for="todo in completed" :key="todo.id" :class="{done:todo.status}" v-model="todo.status" />
    </ul>
  </div>
</template>

<script>
import TodoItem from '../components/TodoItem';
export default {
  name: "Todo",
  components:{
    TodoItem
  },
  data(){
    return{
      content:'hello world!',
      checked:'',
      todos:[
        {
          id:1,
          content:'这是内容1',
          status:false
        },
        {
          id:2,
          content:'这是内容2',
          status:true
        },
        {
          id:3,
          content:'这是内容3',
          status:true
        },
        {
          id:4,
          content:'这是内容4',
          status:false
        },
        {
          id:5,
          content:'这是内容5',
          status:true
        }
      ],
    }
  },
  methods:{
    add(){
      this.todos.push({
        id:this.todos.length+1,
        content:this.content,
        status:false
      })
    }
  },
  computed:{
    underway(){
      return this.todos.filter(todos=>!todos.status);
    },
    completed(){
      return this.todos.filter(todos=>todos.status);
    }
  }
}
</script>

<style scoped>
.section-title{font-weight: bold;font-size: 18px;}
.todolist li{list-style: none;}
.todolist li.done{text-decoration:line-through; }
</style>

2、添加组件

<template>
  <li>
    <input type="checkbox" :name="id" :id="id" :value="content" :checked="modelValue" @input="onInput"/>
    <label :for="id">{{content}}</label>
  </li>
</template>

<script>
export default {
  name: "TodoItem",
  data(){
    return{

    }
  },
  props:{
    id:Number,
    content:String,
    modelValue:Boolean
  },
  methods:{
    onInput(e){
      this.$emit('update:modelValue',e.target.checked);
    }
  }
}
</script>

<style scoped>

</style>

2、添加路由

router\index.js中添加

const routes = [
    //...
    {
        path: '/todo',
        name: 'Todo',
        component: ()=> import('../views/Todo')
    }

3、入口文件增加Todo页面入口(可以不要这一步)

App.vue 文件

<router-link to="/todo">Todo</router-link>

// router-view 公用的不用多次添加
<router-view/>

4、预览页面

现在就可以npm run serve运行查看,

打开首页后,点击Todo就可以打开todo页面,也可以直接在浏览器输入下面地址查看

http://localhost:8080/todo

四、备注

父子组件相互传递数据

==单条参数==

<!-- 父组件 -->
<template>
<p>{{ name }}</p>
  <TodoItem v-model="name" />
</template>

<script>
import Son from '../components/Son';
export default {
  name: "Father",
  components:{
    Son
  },
  data(){
    return{
      name:'Ketty'
    }
  }
}
</script>

<!-- 子组件 -->
<template>
  <input type="text" :value="modelValue" @input="onInput"/>
</template>

<script>
export default {
  name: "Son",
  props:{
    modelValue:String
  },
  methods:{
    onInput(e){
      this.$emit('update:modelValue',e.target.value);
    }
  }
}
</script>

<style scoped>

</style>

==多条参数==

<!-- 父组件 -->
<template>
<p>{{ name }}</p>
<p>{{ addr }}</p>
  <TodoItem v-model:name="name" v-model:addr="addr"/>
</template>

<script>
import Son from '../components/Son';
export default {
  name: "Father",
  components:{
    Son
  },
  data(){
    return{
      name:'Ketty',
      addr:""
    }
  }
}
</script>

<!-- 子组件 -->
<template>
  <input type="text" :value="name" @input="onNameInput"/>
  <input type="text" :value="addr" @input="onAddrInput"/>
</template>

<script>
export default {
  name: "Son",
  props:{
    name:String,
    addr:String
  },
  methods:{
    onNameInput(e){
      this.$emit('update:name',e.target.value);
    },
    onAddrInput(e){
      this.$emit('update:addr',e.target.value);
    }
  }
}
</script>