vue学习笔记のtodolist的实现

借助微信群友及腾讯课堂的力量,对vue有了初步的了解,通过数据直接影响视图。通过vue实现todolist任务来巩固相关知识点。Todolist需要实现的主要功能有:任务的添加,回车添加(v-model、v-on)、删除(v-on)、选定重编辑(@dblclick)及取消重编辑(按esc)、对已完成任务、未完成任务及所有任务的列表切换显示(computed、v-show、v-if、v-bind、v-for、active)、存取数据(localStorage、watch)。

添加任务:

在<input>输入框中输入内容,按回车,则下面的任务列表中会出现刚刚添加的内容。该功能利用函数在methods中实现,调用push()方法(与数组中push()方法不太一样)。在methods中定义一个addTodo()方法实现,并在<input>标签中通过v-on指令绑定该函数。即当我们向<input>输入内容后按回车键触发该函数,前面的勾选框默认false不选中,此时会向列表项中插入一条任务,即一个对象,然后把输入框清空。title值通过v-model实现双向数据绑定。

删除任务:

直接点击任务列表后面的叉即可删除任务。根据任务内容找到list对象中的下标,然后通过splice()方法(与数组中对应方法不太一样)将其删除。

双击修改任务:

双击任务内容,可以改变任务内容,即title的值,将当前编辑的值赋值给title,然后在<label>标签中通过@dblclick绑定该修改函数edtorTodo(),同时在类名todo的<li>标签上,动态绑定一个class为editing,并为其指定修改之后的值edtorTodos,通过这个class来改变任务列表及相对应修改title的输入框的隐藏与显示,通过v-model检测title的改变并进行绑定。

输入框内取消修改:

在输入框内输入修改内容后,若不想修改了,则可按esc返回到之前的内容状态。这里在methods里定义了一个取消修改的函数cancelTodo(),定义一个beforeTitle保存之前的内容,然后将beforeTitle值赋给当前title。同时,通过@keyup.esc绑定cancelTodo()函数。

所有任务、未完成任务、完成任务的切换及计算:

通过计算属性computed根据isChecked值动态计算出对应list中任务个数。通过filter过滤、watch及hash值实现对应项的切换功能。

(1-我们可以给window对象通过addEventListener绑定一个 hashchange事件,回调函数就是获得这个hash值,然后把这个hash值赋给Vue实例中的visibility属性,这个visibility默认是全部显示的。2-通过一个计算属性filteredList来根据visibility的值动态返回不同的状态的list,然后html中v-for指令就不是直接渲染list了,而是通过这个filteredList筛选出来的list,如果在输错hash值的情况下,我们可以判断hash不存在的情况下,全都返回hash值为all的结果,这样就达到了我们想要的效果了。

实现刷新页面时列表项内容依然存在,即列表项内容的存储:

这里用localStorage,利用其save()与fetch()实现数据的存取,即通过localStorage.setItem()实现存储,localStorage.getItem()实现读取。将获取的本粗存储的值赋给list,即可实现列表项内容不丢失。通过watch的深监控来监控list内数据的值并作出相应处理。

实现该任务用到的知识点有:

  • 将vue.js框架通过<script>标签引入
  • v-for指令:根据一组数组的选项列表进行渲染

语法:

value,key in items

value,key of items

  • 变异方法:

vue提供一组方法,对数组进行操作时候,会触发视图更新

push()   pop()    shift()   unshift()    splice()   sort()    reverse()

  • 事件处理器

v-on指令:用来监听dom事件触发代码

语法:v-on:eventName=”eventHandle”

指令简写: @

事件处理函数:写在methods中统一管理

事件对象:在事件处理函数中获取;内联事件处理函数执行,传入事件对象。$event

  • 事件修饰符:

事件处理函数只有纯粹的逻辑判断,不处理dom事件的细节,如阻止冒泡、取消默认行为、判断按键

修饰符的位置:v-on:eventName.修饰符

修饰符:.stop     .prevent   .capture    .self   .once

按键修饰符:

.enter   .tab   .delete  .esc   .space  .up   .down  .left   .right   .ctrl   .alt  .shift   .meta   .键值

执行事件处理函数时可以进行传参

 <input placeholder="勇敢自信youcan;   提示:+回车即可添加任务"
          class="task-input"
          type="text"
          v-model="todo"
          v-on:keyup.enter="addTodo(123,$event)"
  />
 new Vue({
    el:".main",
     data:{
         list:list,
         todo:""
     },
     methods:{ //统一管理事件处理函数
         addTodo:function(data,ev){    /*//添加任务//向list中添加一项任务//事件处理函数中的this指向的是当前这个根实例*/
                     this.list.push({
                    /*title:ev.target.value*/
                     title:this.todo     //替换上面的语句,减少dom操作
             });
           this.todo=" ";  //数据更新视图
         }

    }
 });
  • 条件渲染:

v-show指令:根据表达式的值,决定显示或隐藏元素。

语法:v-show=”表达式”

元素会被渲染在页面中只根据表达式的值进行css切换

  • 动态绑定class:

class也为元素的属性,可以使用v-bind:class

语法:

:class=”{className:表达式}”         // 表达式值为true,添加className,否则不添加

:class=”[className,className]”

v-bind指令:为元素动态绑定class,不同的条件下绑定不同的class,从而实现不同的样式显示。

  • 自定义指令:

除了vue内置的指令,可以自己设置指令

选项对象的directives属性{

directives:{}

}

钩子函数:

update被绑定元素所在的模板更新时调用

钩子函数中参数:

el:指令所绑定的元素,可以用来直接操作dom

binding:一个对象

value:指定的绑定值

  • 计算属性

模板是为了描述视图的结构,模板中放入太多逻辑,导致模板太重,难以维护。

在计算一个属性时,vue.js更新它的依赖列表并缓存结果,只有当其中一个依赖发生了变化,缓存的结果才有效。通过计算属性可以实现对数据的过滤筛选。

语法:

在选项对象中

{

computed:{}

}

  • v-model指令:实现对数据的双向绑定
  • 存取localStorage中的数据
  • 通过监控hash值变化来决定显示哪一部分
  • watch的深监控与浅监控


var list=[

    {

        title:"勇敢勇敢再勇敢",

        isChecked:false      //false表示未选中,任务未完成

    },

  {

      title:"坚强自信youcan",

      isChecked:true   //true,选中,任务完成

  }

]

watch:{           //监控功能

   /* list:function(){      //监控list这个属性,当值发生变化时就会执行后面的函数

        store.save("miaov-new-class",this.list);

    }//浅监控*/

      list:{

         handler:function(){

           store.save("miaov-new-class",this.list);

         },

         deep:true          //深监控

  }

}
html核心代码:
<body>

<div class="page-top">

    <div class="page-content">

        <h2>任务计划列表</h2>

    </div>

</div>

<div class="main">

    <h3 class="big-title">添加任务</h3>

    <input placeholder="勇敢自信youcan;   提示:+回车即可添加任务"

            class="task-input"

            type="text"

            v-model="todo"

            v-on:keyup.enter="addTodo"

     />

    <ul class="task-count"  v-show="list.length">

        <li>{{ noCheckeLength }}个任务未完成</li><!--渲染数据-->

        <li class="action">

            <a :class="{active:visibility===‘all‘}" href="#all">所有任务</a>

            <a href="#unfinished" :class="{active:visibility===‘unfinished‘}">未完成的任务</a>

            <a href="#finished" :class="{active:visibility===‘finished‘}">完成的任务</a>

        </li>

    </ul>

<h3 class="big-title">任务列表</h3>

<div class="tasks">

<span class="no-task-tip" v-show="!list.length">还没有添加任何任务</span>

<ul class="todo-list">

<li class="todo " :class="{completed:item.isChecked,editing:item===edtorTodos}" v-for="item in filteredList">

    <div class="view">

        <input  class="toggle" type="checkbox" v-model="item.isChecked" />

        <label @dblclick="edtorTodo(item)">{{item.title}}</label>

        <button class="destroy" @click="deleteTodo(item)"></button>

    </div>

    <input

            v-focus="edtorTodos===item"

            class="edit"

            type="text"

            v-model="item.title"

            @blur="edtorTodoed(item)"

            @keyup.enter="edtorTodoed(item)"

            @keyup.esc="cancelTodo(item)"

    />

</li>

</ul>

</div>

</div>

  

js核心代码:

var store={    //封装一个对象//存取localStorage中的数据

    save(key,value){  //es6函数写法

        localStorage.setItem(key,JSON.stringify(value));  //将数据转换为json形式的字符串

    },

    fetch(key){

        return JSON.parse(localStorage.getItem(key))||[];

        //获得的数据是json字符串,需要用json.parse解析一下,若没取到就返回空

    }

}

//取出所有的值

//到localStorage中取数据

var list=store.fetch("miaov-new-class");

//过滤的时候分三种情况:all、finished、unfinished

var filter={

    all:function(list){

        return list;

    },

    finished:function(list){

        return list.filter(function(item){

            return item.isChecked;

        })

    },

    unfinished:function(){

        return list.filter(function(item){

            return !item.isChecked;

        })

    }

}

 var vm=new Vue({

    el:".main",

    data:{

        list:list,

        todo:"",

        edtorTodos:‘‘ ,//记录正在编辑的数据

        beforeTitle:‘‘  ,//记录一下正在编辑的数据的title

        visibility:"all"   //通过这个属性值的变化对数据进行筛选

    },

     watch:{           //监控功能

       list:{

           handler:function(){

               store.save("miaov-new-class",this.list);

           },

           deep:true          //深监控

       }

     },

     computed:{

       noCheckeLength:function(){

          return  this.list.filter(function(item){

               return !item.isChecked

           }).length

       },

         filteredList:function(){

             //找到了过滤函数就返回过滤后的数据,如果没有则返回所有数据

             return filter[this.visibility] ? filter[this.visibility](list) : list;

         }

     },

    methods:{ //统一管理事件处理函数

        addTodo:function(){   /*//添加任务

            //向list中添加一项任务

            //事件处理函数中的this指向的是当前这个根实例*/

            this.list.push({

                /*title:ev.target.value*/

                title:this.todo  ,   //替换上面的语句,减少dom操作

                isChecked:false

            });

            this.todo=‘‘;  //数据更新视图

        },

        deleteTodo:function(todo){  //删除任务

            var index=this.list.indexOf(todo);

            this.list.splice(index,1);

        },

        edtorTodo:function(todo){  //编辑任务

            console.log(todo);

            this.edtorTodos=todo;//用数据记录一下现在正在编辑的信息,

            // 编辑任务的时候,记录一项编辑这条任务的title,方便取消编辑的是好重新给之前的title

            this.beforeTitle=todo.title;

        },

        edtorTodoed:function(todo){  //编辑任务成功

            this.edtorTodos="";

        },

        cancelTodo:function(todo){ //取消编辑任务

            /*console.log(123);*/

            todo.title=this.beforeTitle;

            this.beforeTitle=‘‘;

            //让div显示出来,input框隐藏,可以选择将正在编辑的信息置为空

            this.edtorTodos=‘‘;

        }

    },

    directives:{

        "focus":{

            update(el,binding){

               /* console.log(el);

                console.log(binding);*/

                if(binding.value){

                    el.focus();//当选中某个input时自动获得焦点

                }

            }

        }

    }

});

function watchHashChange(){

    var hash=window.location.hash.slice(1);

    /*console.log(hash);*/

    vm.visibility=hash;

}

watchHashChange();

window.addEventListener("hashchange",watchHashChange);

遇到的问题:

1-网页开始定义的文字及列表后面的叉删除符显示异常

解决方法:

html的head中定义:

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

同时在css开头定义:@charset "utf-8";

2- {{message}}直接显示,而没有渲染成绑定的数据

数据没有传进去,初步判断为es6与es5模式的混用,如let声明、var声明及函数的简写

3-在所有任务、未完成任务、完成任务三个显示框上,点击哪个下面对应的列表项就显示哪个,但红色的框框始终显示在所有任务上

原来问题出在css :active选择器上啊。:active选择器用于选择活动链接,当在一个链接上点击时,其将成为活动链接即被激活的。此外,:link选择器用于设置对未被访问页面的链接的样式;:visited选择器用于设置指向已访问页面的链接的样式;:hover选择器用于设置鼠标指针浮动在链接上时的样式。

<li class="action">
    <a :class="{active:visibility===‘all‘}" href="#all">所有任务</a>
    <a href="#unfinished" :class="{active:visibility===‘unfinished‘}">未完成的任务</a>
    <a href="#finished" :class="{active:visibility===‘finished‘}">完成的任务</a>
</li>
 
.active {
    border: 1px solid rgba(175, 47, 47, 0.2);
}

4-在所有任务页面,当删除列表项内容时,下面的列表项内容会立即消失,但是在未完成任务与已完成任务页面,当点击删除列表项内容时,列表项内容不会立即消失,当刷新页面或点击别处再点回来时其下被删除的列表项内容才会被删除,这里的问题出现在哪里呢?

有待解决。。。。。。

时间: 2025-01-20 02:49:24

vue学习笔记のtodolist的实现的相关文章

Vue学习笔记入门篇——组件的使用

本文为转载,原文:Vue学习笔记入门篇--组件的使用 组件定义 组件 (Component) 是 Vue.js 最强大的功能之一.组件可以扩展 HTML 元素,封装可重用的代码.在较高层面上,组件是自定义元素,Vue.js 的编译器为它添加特殊功能.在有些情况下,组件也可以是原生 HTML 元素的形式,以 is 特性扩展. 组件使用 注册 注册一个全局组件,你可以使用 Vue.component(tagName, options).组件在注册之后,便可以在父实例的模块中以自定义元素 的形式使用.

Vue学习笔记入门篇——组件的内容分发(slot)

本文为转载,原文:Vue学习笔记入门篇--组件的内容分发(slot) 介绍 为了让组件可以组合,我们需要一种方式来混合父组件的内容与子组件自己的模板.这个过程被称为 内容分发 (或 "transclusion" 如果你熟悉 Angular).Vue.js 实现了一个内容分发 API,使用特殊的 'slot' 元素作为原始内容的插槽. 编译作用域 在深入内容分发 API 之前,我们先明确内容在哪个作用域里编译.假定模板为: <child-component> {{ messa

Vue学习笔记入门篇——组件的通讯

本文为转载,原文:Vue学习笔记入门篇--组件的通讯 组件意味着协同工作,通常父子组件会是这样的关系:组件 A 在它的模版中使用了组件 B.它们之间必然需要相互通信:父组件要给子组件传递数据,子组件需要将它内部发生的事情告知给父组件.然而,在一个良好定义的接口中尽可能将父子组件解耦是很重要的.这保证了每个组件可以在相对隔离的环境中书写和理解,也大幅提高了组件的可维护性和可重用性.在 Vue 中,父子组件的关系可以总结为 props down, events up.父组件通过 props 向下传递

Vue学习笔记目录

本文为转载,原文:Vue学习笔记目录 Vue介绍 Vue.js是当下很火的一个JavaScript MVVM库,它是以数据驱动和组件化的思想构建的.相比于Angular.js,Vue.js提供了更加简洁.更易于理解的API,使得我们能够快速地上手并使用Vue.js. 如果你之前已经习惯了用jQuery操作DOM,学习Vue.js时请先抛开手动操作DOM的思维,因为Vue.js是数据驱动的,你无需手动操作DOM.它通过一些特殊的HTML语法,将DOM和数据绑定起来.一旦你创建了绑定,DOM将和数据

Vue学习笔记进阶篇——Render函数

本文为转载,原文:Vue学习笔记进阶篇--Render函数 基础 Vue 推荐在绝大多数情况下使用 template 来创建你的 HTML.然而在一些场景中,你真的需要 JavaScript 的完全编程的能力,这就是 render 函数,它比 template 更接近编译器. <h1> <a name="hello-world" href="#hello-world"> Hello world! </a> </h1>

Vue学习笔记进阶篇——过渡状态

本文为转载,原文:Vue学习笔记进阶篇--过渡状态Vue 的过渡系统提供了非常多简单的方法设置进入.离开和列表的动效.那么对于数据元素本身的动效呢,比如: 数字和运算 颜色的显示 SVG 节点的位置 元素的大小和其他的属性 所有的原始数字都被事先存储起来,可以直接转换到数字.做到这一步,我们就可以结合 Vue 的响应式和组件系统,使用第三方库来实现切换元素的过渡状态. 状态动画和watcher 通过 watcher 我们能监听到任何数值属性的数值更新.可能听起来很抽象,所以让我们先来看看使用 T

Vue学习笔记进阶篇——列表过渡及其他

本文为转载,原文:Vue学习笔记进阶篇--列表过渡及其他本文将介绍Vue中的列表过渡,动态过渡, 以及可复用过渡是实现. 列表过渡 目前为止,关于过渡我们已经讲到: 单个节点 同一时间渲染多个节点中的一个 那么怎么同时渲染整个列表,比如使用 v-for ?在这种场景中,使用 <transition-group>组件.在我们深入例子之前,先了解关于这个组件的几个特点: 不同于 <transition>, 它会以一个真实元素呈现:默认为一个<span>.你也可以通过 tag

Vue学习笔记进阶篇——多元素及多组件过渡

本文为转载,原文:Vue学习笔记进阶篇--多元素及多组件过渡 多元素的过渡 对于原生标签可以使用 v-if/v-else.但是有一点需要注意: 当有相同标签名的元素切换时,需要通过 key 特性设置唯一的值来标记以让 Vue 区分它们,否则 Vue 为了效率只会替换相同标签内部的内容.即使在技术上没有必要,给在 <transition> 组件中的多个元素设置 key 是一个更好的实践. 示例: <transition> <button v-if="isEditing

## vue学习笔记--简单父子组件--

## vue学习笔记 ### 组件之间的通讯1. 父组件到子组件```js //father <div> <son msg="父组件的信息写在这"></son> <son title="title"></son> <!--:title--> </div> <script> export default { data(){ return { title: '当传递一个变量过