🎑 VUE小教程-建一个TODO list (下)

0. 前情提要

0.1. 进度提要

网页大致的样子已经出来的。

  • 每个task有checkbox和删除的功能。
  • 页面排版有了header、tasks 和 add,但并没有实质的功能。

0.2. 知识点小结

  • 组件

    • 组件是可复用的 Vue 实例

    • 一个组件的 data 选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝:

      data: function(){
          return { count: 0 }
      }
      
    • 通常一个应用会以一棵嵌套的组件树🎄的形式来组织


      ja
    • 每个组件必须只有一个根元素,就是用一个<div> tag把全部东西包起来

      <div class="blog-post">�
        <h3>{{ title }}</h3>�
        <div v-html="content"></div>�
      </div>
      
  • Prop

    • Prop 是你可以在子组件上注册的一些自定义特性。当一个父组件的值传递给一个 prop 特性的时候,它就变成了那个子组件实例的一个属性。
    • 一个组件默认可以拥有任意数量的 prop
  • v-bind

    我们可以使用 v-bind 来动态传递 prop ,从父级传到子级。

    <blog-post�
      v-for="post in posts"�
      v-bind:key="post.id"�
      v-bind:title="post.title"�>
    </blog-post>�
    
  • v-on & $emit

    通过事件向父级组件发送消息,从子级传到父级。

    自定义事件的系统来解决这个问题。我们可以调用内建的 $emit 方法并传入事件的名字,来向父级组件触发一个件:

    <button v-on:click="$emit('enlarge-text')">�
      Enlarge text
    �</button>�
    
  • v-model

    v-model是一个语法糖,利用v-bind和v-on实现双向绑定

    <input v-model="searchText">
    

    等价于:

    <input
    v-bind:value="searchText"
    v-on:input="searchText = $event.target.value">
    

1. 完善add new task这个功能

1.1 创建newTodo

当用于点了add按钮后,vue要生成一个newTodo的object,然后把它传到父级的App.vue中,等待写入数据库。

这个newTodo长这样:

newTodo = {
  id: 'ID', // 这里使用uuid这个库生成一个id,但是如果使用mongodb之类其实会自动生成
  title: 'TITLE', // 使用v-model,把用户的文字存进来
  completed: false // 因为task都是还没做的
}

所以首先,需要安装uuid。
在shell中跑一下

npm install uuid

接着,AddTodo.vue改成这样👇:

<template>
  <form v-on:submit="addTodo">
      <input type="text" v-model="title" name="title" placeholder="Add new task ...">
      <input type="submit" value="Add" class="btn">
  </form>
</template>

<script>
  import uuid from 'uuid'
  export default {
      name: "AddTodo",
      data(){ return { title:''} }, // related to v-model 
      methods:{
          addTodo(e){
              e.preventDefault();// make sure id is unique
              const newTodo = {
                  id: uuid.v4(), // generate id
                  title: this.title,
                  completed: false
              };
              this.$emit('add-todo', newTodo); // pass newTodo to parent component
              this.title = ''; // reset placeholder to default
          }
      }
  }
</script>

1.2 在App.vue中修改data

接着,修改App.vue,使用新建的addTodo这个method,把子级的newTodo传入data中👇:

<template>
<div id="app">
  <Header />
  <AddTodo v-on:add-todo="addTodo"/>
  <Todos v-bind:todos="todos" v-on:del-todo="deleteTodo"/>
</div>
</template>

<script>
import Todos from './components/Todos'
import Header from "./components/layout/Header";
import AddTodo from "./components/AddTodo";
export default {
name: 'app',
components: {
  AddTodo,
  Header,
  Todos
},
data(){
  return {
    todos: [...]
  }
},
methods: {
  deleteTodo(id){
    this.todos = this.todos.filter(todo => todo.id != id)
  },
  addTodo(newTodo){
    this.todos = [...this.todos, newTodo]
  }
}
}
</script>

1.3 结构diagram

内部的关系,大概是这样👇:


2. 使用jsonplaceholder模拟一个后端

2.0 使用axios来请求

2.0.1

  • 安装axios

    npm install axios
    
  • 🌰 get请求

    axios.get('/user?ID=12345')
      .then(function (response) {
        console.log(response);
      })
      .catch(function (error) {
        console.log(error);
      });
    
  • 🌰 post请求

    axios.post('/user', {
      firstName: 'Fred',
      lastName: 'Flintstone'
    })
      .then(function (response) {
        console.log(response);
      })
      .catch(function (error) {
        console.log(error);
      });
    

2.0.2 Jsonplaceholder

此处用Jsonplaceholder的todo来模拟一个对后端请求。它的 REST API:

http://jsonplaceholder.typicode.com/todos

2.1 get请求后端的tasks

因为随后会向API请求数据,就不需要本地的data了,就直接清除App.vue里头的data,像这样👇

export default{
  // balah balah...
  data(){
    return { todos: [] }
  }
}

接下来,在App.vue中增加一个created()的method,从后端GET请求数据👇

import ...
import axios from "axios";

export default {
  name: 'app',
  components: {...},
  data(){ return { todo: [] }},
  methods: { ... },
  created(){
    axios.get('http://jsonplaceholder.typicode.com/todos?_limit=5')
            .then( res => this.todos = res.data )
            .catch( err => console.log(err) );
  }
}

2.2 post上传task到后端

因为jsonplaceholder会生成id,所以在AddTodo.vue中,就不需要uuid了,把它comment掉就好了。
接着,在App.vue的methods中,把addTodo改成POST请求👇

addTodo(newTodo){
  axios.post('http://jsonplaceholder.typicode.com/todos', newTodo)
          .then( res => this.todos = [...this.todos, newTodo] )
          .catch( err => console.log(err))

2.3 请求删除后端的task

同理,把delete也改成POST请求:

deleteTodo(id){
  axios.delete(`http://jsonplaceholder.typicode.com/todos/${id}`, id)
          .then( res => this.todos = this.todos.filter(todo => todo.id != id) )
          .catch( err => console.log(err) )
}

3. vue-router

3.1 警告🤞🤞🤞

  1. 接下来用vue ui安装vue-router,会覆盖掉全部的App.vue。所以要backup一下,等安装完,再把原先App.vue的内容复制回Home.vue。
  2. 如果用npm安装完vue-router,会无法运行。网上说仿佛是webpack和npm之前的啥问题...解决的办法是把webpack降级。
npm install webpack@4.28.4

(感觉这个教程顺序完全不对...之后要先安装vue-router,再开始写。晚点重来一次...)

3.2 调整一下

  1. 把Home.vue中的header全部删掉。

  2. 把header放到App.vue中。

<template>
  <div id="app">
    <Header />
    <router-view/>
  </div>
</template>
  1. 把router link放到Header.vue中。
<template>
    <header class="header">
        <h1>Todo List</h1>
        <router-link to="/">Home</router-link> |
        <router-link to="/about">About</router-link>
    </header>
</template>

好的...👍
完结...🤞🤞
撒花...🙌🙌🙌
好像之后得再写一遍,一方面是vue-router那个部分跟💩一样...另一方面则是巩固一下学习。
明天要坐游轮🚢去冲绳啦哈哈~~~临行前还是能做完还是比较开心的!

Ronn Liu 🙋‍♂️
2019/01/22 📌

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,589评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,615评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,933评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,976评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,999评论 6 393
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,775评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,474评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,359评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,854评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,007评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,146评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,826评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,484评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,029评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,153评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,420评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,107评论 2 356