Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get the shit done! #3

Open
FrankFang opened this issue Jan 16, 2017 · 82 comments
Open

Get the shit done! #3

FrankFang opened this issue Jan 16, 2017 · 82 comments
Labels

Comments

@FrankFang
Copy link
Contributor

FrankFang commented Jan 16, 2017

首先新建项目目录

cp -r step-2 step-3

这样我们就可以基于之前的代码做新任务,同时不改动之前的代码。

学会一个框架的最好办法

学会一个框架的最好办法那就是——做毁一个项目。

接下来我们就要用 Vue.js 做一个待办事项小应用。简单起见,我们就不写 CSS 了,只用 HTML 和 JS 搞定。

我们的目标只有一个,就是搞清楚怎样用 Vue.js 进行开发。

需求

这个项目的英文名就暂定为 Todo,它有以下功能:

  1. 用户可以新建一个待办事项
  2. 用户可以删除一个待办事项
  3. 用户可以将一个待办事项标记为已完成
  4. 用户刷新页面之后,待办事项还在

Getting Started

由于我们现在对 Vue.js 还一无所知,所以就走一步算一步先。

首先我们用 HTML 描绘一下我们的界面

page.html

<html>
  <head>
    <meta charset=utf-8>
  </head>
  <body>
    <div id="app">
      <div class="newTask">
        <input type="text">
      </div>
      <ol class="todos">
      </ol>
    </div>
    <script src="bundle.js"></script>
  </body>
</html>
  1. charset 要加上,不然出现中文就乱码了
  2. 加一个 div#app,用于给 Vue 初始化
  3. div.newTask > input 用于让用户输入待办的内容
  4. ol.todos 用于容纳所有待办,每个待办就是一个 <li>

添加待办

接下来我们做第一个需求,添加待办。

做之前你要想好流程:

  1. 用户输入待办内容
  2. 用户按下回车
  3. 新的待办出现在 ol.todos

好的,开始做了。

import Vue from 'vue'

var app = new Vue({
  el: '#app',
  data: {
    newTodo: '',
    todoList: []
  }
})                                                               

我们用 todoList 数组作为所有待办事项的容器,newTask 作为 input 的值。

为什么要有 data?

这里出现了第一个令我们费解的地方——「为什么我们需要将 DOM 与 JS 变量(data)对应起来」。

如果我们用 jQuery 来写,直接在 input 的键盘事件中取出 input.value,构造一个 <li>,插入到 ol.todos 就完了嘛。对不对?

这就是框架和库的区别了。jQuery 作为一个库,你想怎么用就怎么用,但是你在使用一个框架的时候,有很多「指导思想」是你要遵循的。Vue 的指导思想之一就是「尽量不要操作 DOM」,因为这个框架会帮你操作 DOM。

绑定数据

      <div class="newTask">
        <input type="text" v-model="newTodo">
      </div>

这一句将 input.value 与 data.newTodo 绑定起来了,而且是双向的:

  1. 只要 input.value 被用户改了,data.newTodo 就会变成一样的值;
  2. 只要 data.newTodo 被 JS 改了,input.value 就会变成一样的值。

怎么验证呢?

首先我们来验证在 JS 里改变 newTodo,input.value 就会变:

import Vue from 'vue'

var app = new Vue({
  el: '#app',
  data: {
    newTodo: '',
    todoList: []
  },
  created: function(){
    let i = 0
    setInterval(()=>{
      this.newTodo = i // this.newTodo 就是 data.newTodo,实际上 this.newTodo 是 data.newTodo 的代理
      i+= 1
    },1000)
  }
})                                                               

运行 webpack,打开 page.html,可以看到 input 的值自己变化着。

Tips:如果你不想每次都运行 webpack,那么你可以新开一个命令行窗口,运行 webpack --watch,那么 webpack 就会在每次 JS 文件变化时自动重新运行。

接下来验证 input.value 改变会导致 data.newTodo 变化:

import Vue from 'vue'

var app = new Vue({
  el: '#app',
  data: {
    newTodo: '',
    todoList: []
  },
  created: function(){
    setInterval(()=>{
      console.log(this.newTodo)
    },1000)
  }
})

F12 打开 console,然后在 input 里输入一些字符试试。

以上,就是双向绑定。

细节请自行查看 https://cn.vuejs.org/v2/guide/forms.html

绑定事件

我们需要在用户敲击 回车 的时候,在 data.todoList 里新建一个对象。

如何监听用户的键盘事件呢?请查看 https://cn.vuejs.org/v2/guide/events.html

看完这一节,你就能写出以下代码了:

app.js

import Vue from 'vue'

var app = new Vue({
  el: '#app',
  data: {
    newTodo: '',
    todoList: []
  },
  methods: {
    addTodo: function(){
      this.todoList.push({
        title: this.newTodo,
        createdAt: new Date()
      })
      console.log(this.todoList)
    }
  }
})   

page.html

      <div class="newTask">
        <input type="text" v-model="newTodo" @keypress.enter="addTodo">
      </div>

这时你刷新 page.html,在 input 里面输入 回车,就会在控制台看到 todoList 不是空字符串了:

展示新待办

虽然 data.todoList 已经含有一个新的项目了,但是页面里却没有展示。

根据 https://cn.vuejs.org/v2/guide/list.html 写出下面代码:

page.html

      <ol class="todos">
        <li v-for="todo in todoList">
          {{ todo.title }}
        </li>
      </ol>

然后重新刷新页面,在 input 输入一些字符,回车。你就会看到新增成功了:

优化

按照正常人的逻辑,添加成功后,input 的值应该清空,于是我们改写 app.js:

app.js

  methods: {
    addTodo: function(){
      this.todoList.push({
        title: this.newTodo,
        createdAt: new Date()
      })
      this.newTodo = ''  // 变成空
    }
  }

刷新试试效果如何吧。

标记为完成

思路:

  1. 给每一个 todo 添加一个 done 属性
  2. 给每一个 <li> 里面添加一个 checkbox
  3. 参考 https://cn.vuejs.org/v2/guide/forms.html#复选框 ,将 done 和 checkbox 双向绑定。

代码如下:

app.js

  methods: {
    addTodo: function(){
      this.todoList.push({
        title: this.newTodo,
        createdAt: new Date(),
        done: false // 添加一个 done 属性
      })
      this.newTodo = ''
    }
  }

page.html

      <ol class="todos">
        <li v-for="todo in todoList">
          <input type="checkbox" v-model="todo.done"> {{ todo.title }}

          <span v-if="todo.done">已完成</span>
          <span v-else>未完成</span>
        </li>
      </ol>

效果如下:

删除待办

思路:

  1. 在每一项后面添加一个删除按钮
  2. 点击按钮则从 data.todoList 中删除该项

代码如下:

app.js

  methods: {
    addTodo: function(){
      this.todoList.push({
        title: this.newTodo,
        createdAt: new Date(),
        done: false // 添加一个 done 属性
      })
      this.newTodo = ''
    },
    // 加了👇这个函数
    removeTodo: function(todo){
      let index = this.todoList.indexOf(todo) // Array.prototype.indexOf 是 ES 5 新加的 API
      this.todoList.splice(index,1) // 不懂 splice?赶紧看 MDN 文档!
    }
  }

page.html

      <ol class="todos">
        <li v-for="todo in todoList">
          <input type="checkbox" v-model="todo.done"> {{ todo.title }}

          <span v-if="todo.done">已完成</span>
          <span v-else>未完成</span>

          <button @click="removeTodo(todo)">X</button>  <!-- 👈 加了一个按钮 -->
        </li>
      </ol>

效果如下(GIF有点大,请稍等或开代理)

保存待办事项

我们发现每次刷新页面,待办就没了。

这是因为这些代码都保存在内存里,而内存是无法持久的。所以我们选择保存在 localStorage 中。

思路:

  1. 在用户关闭页面前,将数据保存在 localStorage 里
  2. 在用户进入页面后,立刻读取 localStorage

代码如下:

app.js

var app = new Vue({
  el: '#app',
  data: {
    newTodo: '',
    todoList: []
  },
  created: function(){
    // onbeforeunload文档:https://developer.mozilla.org/zh-CN/docs/Web/API/Window/onbeforeunload
    window.onbeforeunload = ()=>{
      let dataString = JSON.stringify(this.todoList) // JSON 文档: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/JSON
      window.localStorage.setItem('myTodos', dataString) // 看文档https://developer.mozilla.org/zh-CN/docs/Web/API/Window/localStorage
    }

    let oldDataString = window.localStorage.getItem('myTodos')
    let oldData = JSON.parse(oldDataString)
    this.todoList = oldData || []

  },
  methods: { ...

由于我们只涉及数据的变化,所以 page.html 不变。

让我看到你的应用

你可以将这个应用部署到 GitHub Pages 上。

  1. 新建一个 GitHub repo,或者使用你现有的 GitHub repo。
  2. 在 repo 的 Settings 页面里将 GitHub Pages 功能打开,并选中 master 分支,点 Save,你就会得到一个「部署地址」,比如我的地址是 https://jirengu-inc.github.io/jrg-project-5/:
  3. 在这个部署地址后面接上你 repo 里的文件路径,也可以预览 HTML 了。比如我的预览页面是:https://jirengu-inc.github.io/jrg-project-5/step-3/page.html
  4. 由于国内访问 GitHub 较慢,所以你预览的时候可能看到 {{ }} 标记,不要紧,等一会就好。如果你不想让用户看见这些,可以看 https://cn.vuejs.org/v2/api/#v-cloak

致饥人谷学员

Just get this shit done.

把你的预览页面发到下面,你就成功了。

如果还有时间,建议看看 TodoMVC 项目。比我们这个应用复杂一丢丢,你已经可以独自完成 TodoMVC 了,如果你完成了,把你的链接放在下面单独 at 我。

挑战

  1. 你能否把 newTodo 的内容也保存下来,下次用户进入页面时,会显示之前输入但是还未提交的 newTodo 内容?
  2. 你能否把这个页面美化一下?
  3. 你能否添加「友好的」时间展示,让用户知道这个 todo 是什么时候创建的。
@FrankFang
Copy link
Contributor Author

@Zegendary
Copy link

Zegendary commented Jan 16, 2017

page
code
@FrankFang

@wlf1112
Copy link

wlf1112 commented Jan 17, 2017

代码
展示
WLF

@FrankFang
Copy link
Contributor Author

@wlf1112 bug 1: 刷新页面后待办就木有了~

@wlf1112
Copy link

wlf1112 commented Jan 17, 2017

老师,改完了@FrankFang

@TerenYeung
Copy link

yjl for v-o-r task-03
source
demo

@lzm320856
Copy link

lzm320856 commented Jan 17, 2017

代码
展示
LZM

@hungryYang
Copy link

hungryYang commented Jan 17, 2017

page
code
YCR

@starlikerain
Copy link

starlikerain commented Jan 17, 2017

dogeeeeeeeee


样式加好了
demo
Source Code

@FrankFang
Copy link
Contributor Author

@lzm320856 无法将多个标记为已完成,报错:

Uncaught SyntaxError: Identifier 'CANDIDATE_MIME_TYPES' has already been declared
    at (index):1

@ReedSun
Copy link

ReedSun commented Jan 17, 2017

这里是效果
这里是代码

@whiteblank
Copy link

代码
预览
GJC

@whiteblank
Copy link

@FrankFang 已修改

@zhangjiuyi
Copy link

效果
代码 ZJY

@FrankFang
Copy link
Contributor Author

@zhangjiuyi 界面很小清新哦

@candy252324
Copy link

效果
代码地址CJH

@WangXiaoyugg
Copy link

效果
代码地址 WXY

@FrankFang
Copy link
Contributor Author

@WangXiaoyugg 永远不要给中文字加斜体样式

@LisaLi85
Copy link

预览
代码 LLL

@lightbuild
Copy link

预览
代码
任磊6-任磊

@FrankFang
Copy link
Contributor Author

@lightbuild 使用 Date.prototype.Format 改写 Date 不太好,你可以用一个 formatDate 函数来做

function formatDate(date, format){...}

@0xjeso
Copy link

0xjeso commented Jan 17, 2017

预览
代码
SJ

@chaocool
Copy link

chaocool commented Jan 17, 2017

预览
代码 CJC

年底挤奶时间哇

@ab690257072
Copy link

预览
源码
ZLQ

@FrankFang
Copy link
Contributor Author

@ab690257072 BUG 1:你在页面上操作一段时间之后,就会发现新增的待办默认是「已完成」的。

@ab690257072
Copy link

@FrankFang 已修改,麻烦方方老师啦

@FrankFang
Copy link
Contributor Author

@wlf1112 都是自己写的么,很棒啊

@wuhanjun
Copy link

wuhanjun commented Jan 18, 2017

预览地址
代码地址
WHJ

@wlf1112
Copy link

wlf1112 commented Jan 18, 2017

我参考官网的了@FrankFang

@MasterGaoJin
Copy link

preview
code

@n313893254
Copy link

预览
代码

@success-cg
Copy link

陈功-task3
todolist 预览
demo

@FrankFang
Copy link
Contributor Author

sorry 没时间看了

@13hoop
Copy link

13hoop commented May 31, 2017

预览
代码

@boloog
Copy link

boloog commented Jun 11, 2017

vue-todo boloog

@kumabearplus
Copy link

预览
代码

@komolei
Copy link

komolei commented Jun 13, 2017

vue-todo 空末

@selectyang
Copy link

效果预览
代码

@lc123123
Copy link

lc123123 commented Jul 1, 2017

效果
代码

@chengfengfengwang
Copy link

预览
代码

@jettzhang95
Copy link

Preview
Code
后续还会进行改进

@jamesXiao-coder
Copy link

预览
代码

1 similar comment
@jamesXiao-coder
Copy link

预览
代码

@robbchan
Copy link

预览
代码

@zhaipanyu
Copy link

预览

@imgwho
Copy link

imgwho commented Jul 16, 2017

预览地址
仓库地址
1705 郭文华

@forsuccess
Copy link

预览
代码

@tcitds1
Copy link

tcitds1 commented Jul 24, 2017

预览

@HuangHongRui
Copy link

| Show |
| Code |

@andreaxiang
Copy link

预览vue-todolist 已优化css
已保存newTodo内容,但是没有添加显示创建日期功能。
@FrankFang

@huoguozhang
Copy link

github地址

@zhuyutrisla
Copy link

预览

@clementlxd
Copy link

@Zainking
Copy link

@Alfred-ZF
Copy link

预览
代码

@nciilin
Copy link

nciilin commented Dec 23, 2017

代码
预览

@wobenng
Copy link

wobenng commented Jan 16, 2018

任务15班董杭彬
代码
预览

@o0Chivas0o
Copy link

o0Chivas0o commented Feb 26, 2018

任务15班� 李智颖
预览
代码

@upupdayday
Copy link

预览
代码

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests