By Sheldon L | Published at 2020-03-12 | Updated at 2020-03-12 |
Install node.js
;
Install Vue.js devtools
in chrome extension;
Install Vue CLI (v4.2 in this moment)
with sudo npm install -g @vue/cli
;
Opt 1. cd project_folder
, vue create todo
;
Opt 2. vue ui
start Manager UI in port 8000;
vetur
extension, run server with npm run serve
;npm i uuid axios
Add vue router
on the upper-right corner in the GUI;
App.vue
<template>
<div id="app">
<Header />
<router-view />
</div>
</template>
<script>
import Header from './components/layout/Header';
export default {
name: "App",
components: {
Header
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
}
#nav {
padding: 30px;
}
#nav a {
font-weight: bold;
color: #2c3e50;
}
#nav a.router-link-exact-active {
color: #42b983;
}
</style>
comeponents/layout/Header.vue
<template>
<header class="header">
<h1>Todo List</h1>
<div>
<router-link to="/">Home</router-link>
|
<router-link to="/about">About</router-link>
</div>
</header>
</template>
<script>
export default {
name: "Header",
}
</script>
<style scoped>
.header {
background: #333;
color: #fff;
text-align: center;
padding: 10px;
}
.header a {
color: #fff;
padding: 5px;
text-decoration: none;
}
</style>
views/Home.vue
<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 AddTodo from '../components/AddTodo';
import axios from 'axios';
export default {
name: 'Home',
components: {
Todos,
AddTodo,
},
data() {
return {
todos: []
}
},
methods: {
deleteTodo(id) {
axios.delete(`http://jsonplaceholder.typicode.com/todos/${id}`)
.then(this.todos = this.todos.filter(todo => todo.id !== id))
.catch(err => console.log(err))
},
addTodo(newTodo) {
const { title, completed } = newTodo;
axios.post('http://jsonplaceholder.typicode.com/todos', {
title,
completed
})
.then(res => this.todos = [...this.todos, newTodo, res.data])
.catch(err => console.log(err))
},
// get todo sample from jsonplaceholder
created() {
axios.get('http://jsonplaceholder.typicode.com/todos?_limit=5')
.then(res => this.todos = res.data)
.catch(err => console.log(err))
}
}
}
</script>
<style>
* {
box-sizing: border-box;
margin: 0;
padding: 0%;
}
body {
font-family: Arial, Helvetica, sans-serif;
line-height: 1.4;
}
.btn {
display: inline-block;
border: none;
background: #555;
color: #fff;
padding: 7px 20px;
cursor: pointer;
}
.btn:hover {
background: #666;
}
</style>
components/Todos.vue
<template>
<div>
<div v-bind:key="todo.id" v-for="todo in todos">
<TodoItem v-bind:todo="todo" v-on:del-todo="$emit('del-todo', todo.id)" />
</div>
</div>
</template>
<script>
import TodoItem from './TodoItem';
export default {
name: "Todos",
components: {
TodoItem,
},
props: ["todos"],
}
</script>
<style scoped>
</style>
components/TodoItem.vue
<template>
<div class="todo-item" v-bind:class="{'is-complete': todo.completed}">
<p>
<input type="checkbox" v-on:change="markComplete">
<button @click="$emit('del-todo', todo.id)" class="del"></button>
</p>
</div>
</template>
<script>
export default {
name: "TodoItem",
props: ["todo"],
methods: {
markComplete() {
this.todo.completed = !this.todo.completed;
}
}
}
</script>
<style scoped>
.todo-item {
background: #eee;
padding: 10px;
border-bottom: 1px #bbb dotted;
}
.is-complete {
text-decoration: line-through;
}
.del {
background: #ff0000;
color: #fff;
border: none;
padding: 5px 9px;
border-radius: 50%;
cursor: pointer;
float: right;
}
</style>
components/AddTodo.vue
<template>
<div>
<form @submit="addTodo">
<input type="text" v-model="title" name="title" placeholder="Add Todo...">
<input type="submit" value="Submit" class="btn">
</form>
</div>
</template>
<script>
export default {
name: "AddTodo",
data() {
return {
title: '',
}
},
methods: {
addTodo(e) {
e.preventDefault(); // Environment parameter
const newTodo = {
title: this.title,
completed: false,
};
// Send up to parent
this.$emit('add-todo', newTodo);
this.title = '';
// console.log(this.id);
}
},
}
</script>
<style scoped>
form {
display: flex;
}
input[type="text"] {
flex: 10;
padding: 5px;
}
input[type="submit"] {
flex: 2;
}
</style>