不使用router-view
,利用router-link
達到換頁
npm install vuex-router-sync
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import { sync } from 'vuex-router-sync'
Vue.config.productionTip = false
// 使用vuex-router-sync 需加上
sync(store, router)
Vue.directive('focus', {
// 当被绑定的元素插入到 DOM 中時
inserted: function(el) {
// 聚焦元素
el.focus()
}
})
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
routes: [
{
path: '/all',
name: 'all'
},
{
path: '/active',
name: 'active'
},
{
path: '/complete',
name: 'complete'
},
{
path: '*',
redirect: '/all'
}
]
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
// localStorage得操作
const LS = {
load() {
return JSON.parse(localStorage.getItem('vue-todos') || '[]')
},
save(data) {
localStorage.setItem('vue-todos', JSON.stringify(data))
}
}
const filter = {
all(todos) {
return todos
},
active(todos) {
return todos.filter(({ complete }) => !complete)
},
complete(todos) {
return todos.filter(({ complete }) => complete)
}
}
const getters = {
// 取得內容在陣列中的位置
// ex. return [0,1,2...]
todoIndex(state) {
return filter[state.route.name](state.todos).map(todo =>
state.todos.indexOf(todo)
)
}
}
export default new Vuex.Store({
strict: true,
state: {
todos: []
},
getters,
mutations: {
setTodos(state, data) {
state.todos = data
LS.save(state.todos)
},
addTodo(state, data) {
state.todos.push(data)
LS.save(state.todos)
},
updateTodo(state, { index, content }) {
state.todos[index].content = content
LS.save(state.todos)
},
doneTodo(state, index) {
state.todos[index].complete = !state.todos[index].complete
LS.save(state.todos)
},
removeTodo(state, index) {
state.todos.splice(index, 1)
LS.save(state.todos)
}
},
actions: {
INIT_TODOS({ commit }) {
// 讀取localStorage
commit('setTodos', LS.load())
}
}
})
<div class="app" id="app">
<div class="container">
<section>
<div class="title">
<router-link to="/all" class="content">全部</router-link> |
<router-link to="/active" class="content">未完成</router-link> |
<router-link to="/complete" class="content">完成</router-link>
</div>
<TodoInput />
<TodoList v-for="index in todoIndex" :key="index" :index="index" />
</section>
</div>
</div>
import TodoInput from '@/components/TodoInput'
import TodoList from '@/components/TodoList'
export default {
components: {
TodoInput,
TodoList
},
computed: {
todoIndex() {
return this.$store.getters.todoIndex
}
},
mounted() {
this.$store.dispatch('INIT_TODOS')
}
}
<div class="list">
<input
type="text"
v-model.trim="edit"
v-if="edit !== null"
v-focus
@keyup.enter="submitHandler"
@keyup.esc="cancelHandler"
@blur="cancelHandler"
/>
<template v-else>
<span
:class="{'dot-checked':todo.complete,'dot':!todo.complete}"
@click="doneHandler"
></span>
<p :class="{'finished':todo.complete}" @dblclick="editHandler">
{{ todo.content }}
</p>
<span class="cross" @click="removeHandler"></span>
</template>
</div>
export default {
name: 'todoList',
data() {
return {
edit: null
}
},
props: {
index: {
type: Number,
required: true
}
},
computed: {
todo() {
return this.$store.state.todos[this.index]
}
},
methods: {
doneHandler() {
this.$store.commit('doneTodo', this.index)
},
removeHandler() {
if (confirm(`是否確認刪除${this.todo.content}?`)) {
this.$store.commit('removeTodo', this.index)
}
},
editHandler() {
if (this.todo.complete) return
this.edit = this.todo.content
},
submitHandler() {
if (!this.edit) return false
this.$store.commit('updateTodo', {
index: this.index,
content: this.edit
})
this.cancelHandler()
},
cancelHandler() {
this.edit = null
}
}
}
<div class="input-txt">
<input
type="text"
placeholder="請輸入代辦事項"
v-model.trim="todo"
@keyup.enter="submitHandler"
v-focus
/>
</div>
export default {
name: 'todoInput',
data() {
return {
todo: null
}
},
methods: {
submitHandler() {
if (!this.todo) return
this.$store.commit('addTodo', { content: this.todo, complete: false })
this.todo = null
}
}
}