2021-11-05

一个ToolList案例上一个例子组件化

2021-11-05

抽取EditTodo

<template>
    <input
       type="text"
       :value="modelValue"
       @input="onInputChange"
       v-bind="$attrs"
    />
</template>

<script>
export default {
    // 属性声明
   props: {
       modelValue: {
           type: String,
           default: ''
       },
   },
  methods:{
      onInputChange(e){
        //  派发事件
        this.$emit('update:modelValue',e.target.value)
      }
  }
}
</script>

<style lang="scss" scoped>

</style>

抽取TodoItem

<template>
  <li :class="{ completed: todo.completed, editing: todo === editedTodo }">
    <div class="view">
      <input type="checkbox" v-model="todo.completed" />
      <label @dblclick="editTodo(todo)">{{ todo.title }}</label>
      <button @click="removeTodo(todo)">X</button>
    </div>
    <!-- 编辑代办 -->
    <input
      type="text"
      class="edit"
      v-model="todo.title"
      v-todo-foucs="todo === editedTodo"
      @blur="doneEdit(todo)"
      @keyup.enter="doneEdit(todo)"
      @keyup.escape="cancelTodo(todo)"
    />
  </li>
</template>

<script>
import {reactive,toRefs} from "vue"
export default {
  props: { //输入
      todo: {
          type: Object,
          required: true //必须为true
      },
      editTodo:Object
  },
// 输出
  emits:['remove-todo','update:edited-todo'],

  setup(props,{emit}) {
      const state=reactive({
        beforeEditCache: '', //缓存编辑前的title
      });

    function editTodo(todo) {
      state.beforeEditCache = todo.title;
    //   告诉父亲去做
      emit('update:edited-todo',todo)
    }
    function cancelTodo(todo) {
      todo.title = state.beforeEditCache;
       emit('update:edited-todo',null)
    }

    function doneEdit(todo) {
      emit('update:edited-todo',null)
    }
    //派发事件
    function removeTodo(todo) {
        //  emit事件
        emit('remove-todo',todo)
    }

    return {
        ...toRefs(state),
        removeTodo,
        editTodo,
        cancelTodo,
        doneEdit
    };
  },
    directives:{
      "todo-foucs":(el,{value},vnode)=>{
          if(value){
              el.focus();
          }
      }
  }
};
</script>

<style  scoped>
.completed label {
  text-decoration: line-through;
}
.edit,
.editing .view {
  display: none;
}
.view,
.editing .edit {
  display: block;
}
</style>

抽取Filter

<template>
    <!-- 过滤 -->
    <p class="filters">
        <span
        v-for="item in items"
        :key="item.value"
         @click="$emit('update:modelValue',item.value)" 
         :class="{selected:modelValue===item.value}">{{item.value}}</span>

    </p>
</template>

<script>
    export default {
        props:['items','modelValue'],
        emits:['update:modelValue']
    }
</script>

<style  scoped>
.filters >span{
  padding:2px 4px;
  margin-right: 4px;
  border: 1px solid transparent;
}
.filters >span.selected{
  border-color: rgba(173,47,47,0.2);
}
</style>

组件1逻辑提取 useFilter

import { reactive,computed } from "vue";
// 过滤器
const filters={
    all(todos){
      return todos
    },
    active(todos){
      return todos.filter(todo=>!todo.completed)
    },
    completed(todos){
        return todos.filter(todo=>todo.completed)
    },
  }
  export function useFilter(todos){
     const filterState=reactive({
        filterItems:[
       {label:'All',value:'all'},
       {label:'Active',value:'active'},
       {label:'Completed',value:'completed'},
     ],
     visibility:'all',
     filterdTodos:computed(()=>{
      return filters[filterState.visibility](todos.value)
     })
    });  
    
    return  filterState;
  }

组件2逻辑提取useTodos

// 逻辑控制
// 缓存操作
import {ref,watchEffect} from "vue"
const todoStorage={
    fetch(){
      let todos=JSON.parse(localStorage.getItem('vue3-todos')||'[]')
      todos.forEach((todo,index) =>{
        todo.id=index+1
      })
      return todos
    },
    save(todos){
       localStorage.setItem("vue3-todos",JSON.stringify(todos));
    }
  }

  export function useTodos(state){
     const todos= ref(todoStorage.fetch())//初始化

     function addTodo() {
        todos.value.push({
          id: todos.value.length + 1,
          title: state.newTodo,
          completed: false,
        });
        //   状态置空
        state.newTodo = "";
      }
  
      function removeTodo(todo) {
        todos.value.splice(todos.value.indexOf(todo), 1);
      }
  
  
      watchEffect(()=>{
        todoStorage.save(todos.value)
        
      })
      return{todos ,addTodo,removeTodo}
  }
上一篇:express中使用ejs注意点


下一篇:如何用express框架搭建node服务(路由、中间件、接口、日志、控制器)