这是vue官网的一个例子,挺适合作为vue应用的入门的。

通过这个应用,我们能学到vue的【双向绑定】,【v-for】【事件】,【计算】,【指令】等的应用。

应用预览

这个应用开头是这样的

初始状态.png

后来是这样的

增加一件事情以后

任务分析

作为一个to do 应用,最基本的任务有三个增加一个新的to do事项

标记完成to do的事项

显示to do的事项(未完成,完成,全部),能够在三者的状态下进行切换

删除to do的事项

针对任务,我们最基础的数据设计有几个,一个是最基础的to do事项存储,最直观的应该是一个数组,存储了所有的事项,但是每个事项应该有两种状态,一个状态是未完成,一个状态是完成,所以每个设计成var todos = [

{title:A,completed:true},

{title:B,completed:false},

...

]

这样的结构,title表示事项的内容,completed记录事项的状态。

所有的数据的改变都和前端交互有关。用户每次添加一个新的事项,就要往数组里面加元素,我们用变量newTodo来表示用户新增加的事项的内容,而状态为completed:false,而用户每次完成一个事项,就会改变事项的状态,从completed:false到completed:true,而用户删除一个事项,则要从数组中删除事件。同时我们要可以显示三种不同的事项状态(All,Active,Completed),所以我们要用一个visibility来表示用户选择的状态。

html结构

首先是结构,主题是一个section标签,它分成三个主要部分,一个是header.header,一个是section.main,最后一个是footer.footer。

下面给出基础结构的html代码,第一部分header.header里面主要是一个input来让用户添加待办事项(todo)。第二部分主要是已经列出事项列表,用ul和li来罗列事项,同时在每个li里面增加div,每个div由三个部分组成,input来让用户标注已经完成,label标注事项本身,button用来删除事项。footer第一个span用来计数,ul里面让用户切换三种状态,button用来清除已完成的事项。

autofocus autocomplete="off"

placeholder="What needs to be done?">

left

  • All
  • Active
  • Completed

remaining">

Clear completed

Vue的使用

首先,绑定vue,绑定整个最外围的的section。new Vue({  // the root element that will be compiled

el: '.todoapp',

})添加事项

首先,前面的html结构中,有一个Input结构,我们通过input来得到用户输入,然后用户在输入enter键的时候,触发事件,然后将用户输入的内容增加都数组里面。

这个时候,我们涉及到一个知识点,就是双向绑定,双向绑定的概念就是,将input里面的value(用户输入事项内容)和一个变量(这里的newTodo)绑定起来,input里面的事项内容改变,newTodo的内容也随之改变,反之也是一样。所以我们在input里面增加v-model属性

autofocus autocomplete="off"

placeholder="What needs to be done?"

v-model="newTodo">

然后再vue里面加入数据

new Vue({

data: {

newTodo: ''

})但是我们同时还要将用户输入的事项增加到todos数组中,需要在用户按下enter键的时候,触发事件。这里涉及到了[vue事件](http://cn.vuejs.org/guide/events.html),vue事件是绑定到元素上面的,

autofocus autocomplete="off"

placeholder="What needs to be done?"

v-model="newTodo"

@keyup.enter="addTodo">同时我们也要增加事件触发以后的处理函数,vue模块的结果如下。

new Vue({

data: {

todos: [],

newTodo: ''

},

methods: {

addTodo: function () {

var value = this.newTodo && this.newTodo.trim();

if (!value) {

return;

}

this.todos.push({ title: value, completed: false });

this.newTodo = '';

}

})至此,我们已经能够愉快地添加事件了。

2. 显示事项

显示事项其实要区分事项的状态,从概览里面我们已经看到,总共分成三类事项,一类是全部,一类是未完成,还有一类是已经完成。所以我们要对事项有一个分类的提取,作者写了一个filters来获取不同状态的事项列表。

var filters = {

all: function (todos) {

return todos;

},

active: function (todos) {

return todos.filter(function (todo) {

return !todo.completed;

});

},

completed: function (todos) {

return todos.filter(function (todo) {

return todo.completed;

});

}

};注意到,我们只是将todos绑定在vue的data范围里面,而且三种状态的数据是根据data的数据来的,所以我们用到了computer[计算属性](http://cn.vuejs.org/guide/computed.html)。计算属性用来解决依赖关系,比如用户事项的三种状态,都依赖于todos数组生成,所以我们需要用到计算属性来让todos变化的时候,三种状态的事项列表也能动态变化。然后我们用filterdTodos来表示最终要显示的某种状态的变量。

new Vue({

data:{

...

visibility: 'all'

},

...

computed: {

filteredTodos: function () {

return filtersthis.visibility;

}

})section.main应该在todo的数据有元素的时候显示, 显然,我们应该在todos数组不为空的时候,显示,所以涉及到了[v-show](http://vuejs.org.cn/guide/conditional.html#v-show)

用来控制dom节点的display,当todos里面的元素大于0的时候,节点就显示,不然就隐藏。

另外还有一个v-cloak,可以配合`[v-cloak]{display:none}`来隐藏没有渲染的节点,不然你会看到很多的{{}}之类的文字。

当用户填写了事项的时候,也就是todos里面有内容了之后,下一步是显示事项,我们知道当前的状态,要显示的数据都在filteredTodos里面,所以利用[v-for](http://vuejs.org.cn/guide/list.html#值域-v-for)来循环生成列表.

这样我们就能生成不同的li了。

针对每个事项,我们知道有两种状态,而我们想给已经完成的事项显示的时候,有删除线的样式,所以我们要根据事项的状态来绑定[css](http://vuejs.org.cn/guide/class-and-style.html),根据todo的状态来增加css。

v-for="todo in filteredTodos"

:class="{completed: todo.completed, editing: todo == editedTodo}">>对于每个具体的事项,我们有三个操作,一个是转化状态,也就是利用左边的input来切换,另外一个是编辑事项,利用双击文本来实现,另外一个功能是删除事项,利用右边的X的button来完成。1. 事项的状态转化

![具体事项](http://upload-images.jianshu.io/upload_images/2099962-4e1ace6fb72ee9ad.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)li里面的结构如下所示。

{{todo.title}}

切换状态用todo.completed来表示,然后再分别绑定事件。

new Vue({

data:{

editedTodo: null

}

...

methods: {

removeTodo: function (todo) {

this.todos.$remove(todo);

},editTodo: function (todo) {        this.beforeEditCache = todo.title;        this.editedTodo = todo;

},     cancelEdit: function (todo) {    this.editedTodo = null;

todo.title = this.beforeEditCache;

}

}

})1. 事项的编辑

针对Input的可编辑状态,这里设置了一个能编辑的Input,也就是设置成text.绑定了 todo.title的数据。

v-model="todo.title"

v-todo-focus="todo == editedTodo"

@blur="doneEdit(todo)"

@keyup.enter="doneEdit(todo)"

@keyup.esc="cancelEdit(todo)">其他容易理解,我们在键盘输入enter的时候和焦点转移的时候,将todo的内容保存下来。

new Vue({

...

methods: {

doneEdit: function (todo) {

if (!this.editedTodo) {

return;

}

this.editedTodo = null;

todo.title = todo.title.trim();

if (!todo.title) {

this.removeTodo(todo);

}

}

})这里编辑了一个[指令](http://vuejs.org/guide/custom-directive.html)。指令是数据变化自动转化为dom行为。如果editedTodo为todo,那么会触发这个Input的指令。

directives: {

'todo-focus': function (value) {

if (!value) {

return;

}

var el = this.el;

Vue.nextTick(function () {

el.focus();

});

}

}指令现在的函数是update函数,也就是说在数据更新的时候调用,如果刚开始进入编辑状态,那么这时候value的值改成true,如果结束编辑,那么value的值为false,也就是只在进入编辑状态的时候指令出发,然后把焦点转移到当前的input上面。这里有一个[nextTick](http://vuejs.org.cn/guide/reactivity.html#异步更新队列),也就是在对dom直接进行改动的时候,因为异步更新队列的关系,所以我们要用nextTick不然可能会无效。最后加一个取消编辑的命令,是用键盘的Esc来实现。1. 显示状态切换

最后还有footer这部分,可以看到有三个部分,其他的不难,我们来想一下All,Active,Completed这三种状态切换的问题吧。最简单的,就是保存一个变量,这个变量可以决定要显示的状态,然后通过点击三个选项来切换状态。然而作者选用了链接路由的方式。

![](http://upload-images.jianshu.io/upload_images/2099962-c208dc6c5cb1feb3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)html的结构

{{remaining | pluralize 'item'}} left

  • All
  • Active
  • Completed

Clear completed

我们可以看到ul.filters的下面有三个li代表三种状态,每个都是一个链接,链接是 `#/url`这样的格式。首先要了解routes.js

var router = new Router();

['all', 'active', 'completed'].forEach(function (visibility) {

router.on(visibility, function () {

app.visibility = visibility;

});

});

router.configure({

notfound: function () {

window.location.hash = '';

app.visibility = 'all';

}

});

router.init();代码可以看到,每次点击超链接,都会切换visibility的状态。而vue的compute的属性可以为每次的visiblity状态切换改变前端的样式。1. 数据存储

还记得我们刚开始的时候todos设置为空么,我们可以将数据存在localStorage来让用户下次访问的时候,也能访问到相应的数据,所以设置了一个`store.js`

/*jshint unused:false */

(function (exports) {

'use strict';

var STORAGE_KEY = 'todos-vuejs';

exports.todoStorage = {

fetch: function () {

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

},

save: function (todos) {

localStorage.setItem(STORAGE_KEY, JSON.stringify(todos));

}

};

})(window);然后我们在初始化todos的时候,调用fetch函数,而每次检测到todos变化的时候,调用watch函数。new Vue({    data: {

todos:todoStorage.fetch(),

...

}

...  watch: {            todos: {

handler: function (todos) {

todoStorage.save(todos);

},                deep: true

}

}

})

关键代码

1.html结构

todos

autofocus autocomplete="off"

placeholder="What needs to be done?"

v-model="newTodo"

@keyup.enter="addTodo">

  • v-for="todo in filteredTodos"

    :class="{completed: todo.completed, editing: todo == editedTodo}">

    {{todo.title}}

    v-model="todo.title"

    v-todo-focus="todo == editedTodo"

    @blur="doneEdit(todo)"

    @keyup.enter="doneEdit(todo)"

    @keyup.esc="cancelEdit(todo)">

{{remaining | pluralize 'item'}} left

  • All
  • Active
  • Completed

remaining">

Clear completed

2.app.js/*global Vue, todoStorage */(function (exports) {    'use strict';    var filters = {        all: function (todos) {            return todos;

},        active: function (todos) {            return todos.filter(function (todo) {                return !todo.completed;

});

},        completed: function (todos) {            return todos.filter(function (todo) {                return todo.completed;

});

}

};

exports.app = new Vue({        // the root element that will be compiled

el: '.todoapp',        // app initial state

data: {            todos: todoStorage.fetch(),            newTodo: '',            editedTodo: null,            visibility: 'all'

},        // watch todos change for localStorage persistence

watch: {            todos: {                handler: function (todos) {

todoStorage.save(todos);

},                deep: true

}

},        // computed properties

// http://vuejs.org/guide/computed.html

computed: {            filteredTodos: function () {                return filters[this.visibility](this.todos);

},            remaining: function () {                return filters.active(this.todos).length;

},            allDone: {                get: function () {                    return this.remaining === 0;

},                set: function (value) {                    this.todos.forEach(function (todo) {

todo.completed = value;

});

}

}

},        // methods that implement data logic.

// note there's no DOM manipulation here at all.

methods: {            addTodo: function () {                var value = this.newTodo && this.newTodo.trim();                if (!value) {                    return;

}                this.todos.push({ title: value, completed: false });                this.newTodo = '';

},            removeTodo: function (todo) {                this.todos.$remove(todo);

},            editTodo: function (todo) {                this.beforeEditCache = todo.title;                this.editedTodo = todo;

},            doneEdit: function (todo) {                if (!this.editedTodo) {                    return;

}                this.editedTodo = null;

todo.title = todo.title.trim();                if (!todo.title) {                    this.removeTodo(todo);

}

},            cancelEdit: function (todo) {                this.editedTodo = null;

todo.title = this.beforeEditCache;

},            removeCompleted: function () {                this.todos = filters.active(this.todos);

}

},        // a custom directive to wait for the DOM to be updated

// before focusing on the input field.

// http://vuejs.org/guide/custom-directive.html

directives: {            'todo-focus': function (value) {                if (!value) {                    return;

}                var el = this.el;

Vue.nextTick(function () {

el.focus();

});

}

}

});

})(window);

3.数据的存储(function (exports) {    'use strict';    var STORAGE_KEY = 'todos-vuejs';

exports.todoStorage = {        fetch: function () {            return JSON.parse(localStorage.getItem(STORAGE_KEY) || '[]');

},        save: function (todos) {

localStorage.setItem(STORAGE_KEY, JSON.stringify(todos));

}

};

})(window);

作者:进击的前端

链接:https://www.jianshu.com/p/82778a67ea57

todomvc html css模板,通过todoMVC来学vue.js的使用相关推荐

  1. 为什么 那么多 前端开发者都想学 Vue.js

    根据JavaScript 2017 前端库状况调查 Vue.js是开发者最想学的前端库.我在这里说明一下我为什么认为这也是和你一起通过使用 Vue 构建一个简单的 App 应用程序的原因. 我最近曾与 ...

  2. 为什么43%前端开发者想学Vue.js

    根据JavaScript 2017前端库状况调查 Vue.js是开发者最想学的前端库.我在这里说明一下我为什么认为这也是和你一起通过使用Vue构建一个简单的App应用程序的原因. 我最近曾与Evan ...

  3. todomvc html css模板,[超详细] vue入门项目 TodoMVC 实现和思考

    如果对你有帮助希望可以点个 star 哦 ~ 一.项目初始化 1.下载模板 在存放该项目的目录下执行: git clone https://github.com/tastejs/todomvc-app ...

  4. vusjs 配合php_对照着jquery来学vue.js系列之配合thinkphp下拉获取分页数据

    上篇文章介绍了vue.js如何ajax获取数据: 接着不可避免就遇到的是: 如何进行数据分页呢? 这里以thinkphp为示例讲解:其他场景性质一样: 示例项目:https://github.com/ ...

  5. 小陈学vue.js 过滤器

    过滤器可以用在两个地方:双花括号插值和 v-bind 表达式 (后者从 2.1.0+ 开始支持).过滤器应该被添加在 JavaScript 表达式的尾部,由"管道"符号指示: &l ...

  6. Vue.js 使用script或template标签创建组件模板内容

    为了使HTML代码和JavaScript代码是分离的,便于以后的阅读和维护,我们可以并建议使用<script>或<template>标签创建组件模板内容. <!DOCTY ...

  7. Vue.js:todomvc经典案例详解

    1.应用模板下载: TodoMVC 案例官网:http://todomvc.com 如图下载模板: 2. npm安装依赖 通过 nmp 安装相关依赖,进入vs code ,找到文件,右键点击在集成终端 ...

  8. Vue.js框架入门经典项目TodoMVC

    1. 介绍 项目地址:http://todomvc.com/ github模板下载地址:https://github.com/tastejs/todomvc-app-template 可通过git和n ...

  9. (22)Vue.js 综合案例:TodoMVC

    一.TodoMVC介绍 TodoMVC 是一个经典项目,让开发者快速实践到框架开发方式. 官网地址:http://todomvc.com/ TodoMVC一句话评价:功能完备不冗余,多样实现引深思. ...

最新文章

  1. AI = “Automated Inspiration(灵感自动化)”
  2. Git学习笔记;Git bash 库同步问题
  3. 关于CAN总线的位时间/同步段/传播时间段/相位缓冲段/采样点
  4. java basic data type,java基本数据类型--Basic Datatypes
  5. 在codeigniter中使用Cache_Lite来缓存
  6. 关于 m_pszAppName
  7. sqlserver 没有维护计划_制定数据库备份计划,不再为数据丢失闹心!
  8. 关于POSTSQL 的语言编码问题!
  9. RestTemplate 下载文件
  10. 组装三代番木瓜基因组——by Serenity Fang
  11. 如何用计算机名添加的打印机,如何添加打印机(如何在电脑上安装打印机)
  12. 介入切除心脏肿瘤:ONOCOR血管可回收技术历史性应用
  13. 21世纪 直销势不可挡
  14. 土气和洋气的方法不用π求圆的面积
  15. Unity 数据存储与读取_JSON
  16. java判断字符串以数字开头_java-如何检查以数字开头的字符串?
  17. 任天堂 Wii 模拟器 Dolphin 已原生支持苹果 M1 Mac 电脑
  18. oracle OCP指南
  19. 笔记本电脑如何玩游戏不卡顿,提升自己的笔记本性能!开启高性能模式的方法
  20. 我决定辞掉工作,全职开发我的操作系统!(续)

热门文章

  1. 大家记忆中的Q版泡泡堂是不是这个样子的呀!Python实现简易Q版泡泡堂小游戏!!!
  2. PHP5 GD,验证码笔记 COOKIE,SESSION
  3. 男人不成熟的35个标志
  4. druid连接池例子
  5. 2005年感悟做男人100条
  6. 从零实现RPC框架之:4协议设计
  7. win10打开lol后所有声音消失
  8. 夜店App怎么做?来听90后MM聊夜店生态圈
  9. 【C++】auto关键字
  10. Servlet生命周期、工作步骤