Skip to content

Commit 685d7fc

Browse files
committed
feat(vue-router): introduce router
1 parent dc41a32 commit 685d7fc

File tree

10 files changed

+84
-24
lines changed

10 files changed

+84
-24
lines changed

package-lock.json

+5
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
"todomvc-app-css": "^2.3.0",
1616
"uuid": "^3.3.3",
1717
"vue": "^2.6.10",
18+
"vue-router": "^3.1.3",
1819
"vuex": "^3.1.2"
1920
},
2021
"devDependencies": {

src/components/App.vue

+6-11
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,18 @@
11
<template>
22
<div id="app">
3-
<section class="todoapp">
4-
<Header />
5-
<List />
6-
<Footer />
7-
</section>
3+
<router-view />
84
<CopyRight />
95
</div>
106
</template>
117

128
<script>
139
import { mapActions, mapState } from 'vuex';
14-
import Header from './Header.vue';
15-
import List from './List.vue';
16-
import Footer from './Footer.vue';
1710
import CopyRight from './CopyRight.vue';
1811
import { TodoLocal } from '../services/TodoLocal';
1912
2013
export default {
2114
name: 'app',
22-
components: { Header, List, Footer, CopyRight },
15+
components: { CopyRight },
2316
computed: {
2417
...mapState(['todos'])
2518
},
@@ -29,8 +22,10 @@
2922
mounted() {
3023
this.onLoad(TodoLocal.loadTodos());
3124
},
32-
beforeUpdate() {
33-
TodoLocal.storeTodos(this.todos);
25+
watch: {
26+
todos() {
27+
TodoLocal.storeTodos(this.todos);
28+
},
3429
}
3530
}
3631
</script>

src/components/Footer.vue

+3-7
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,9 @@
33
<span class="todo-count"><strong>{{ itemsLeft }}</strong><span> {{ itemText }} left</span></span>
44
<ul class="filters">
55
<li v-for="filterKey in Object.keys(filterTitles)" :key="filterKey">
6-
<a
7-
href="#"
8-
:class="{ selected: filterKey === filter }"
9-
@click="onFilterSelect(filterKey)"
10-
>
6+
<router-link :class="{ selected: filterKey === filter }" :to="`/${filterKey}`" >
117
{{ filterTitles[filterKey] }}
12-
</a>
8+
</router-link>
139
</li>
1410
</ul>
1511
<button v-if="!!completedCount" class="clear-completed" @click="onClearCompleted">Clear completed</button>
@@ -23,7 +19,7 @@
2319
export default {
2420
name: 'Footer',
2521
methods: {
26-
...mapActions(['onClearCompleted', 'onFilterSelect'])
22+
...mapActions(['onClearCompleted']),
2723
},
2824
computed: {
2925
...mapState(['todos', 'filter']),

src/components/Header.spec.js

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { expect } from 'chai';
2+
import { createLocalVue, shallowMount } from '@vue/test-utils';
3+
import Vuex from 'vuex';
4+
import Header from './Header.vue';
5+
import { storeFactory } from '../store/factory';
6+
7+
describe('Header', function() {
8+
it('should add new element to store', function() {
9+
const localVue = createLocalVue();
10+
localVue.use(Vuex);
11+
const store = storeFactory();
12+
13+
const wrapper = shallowMount(Header, { localVue, store });
14+
15+
wrapper.vm.name = 'New';
16+
wrapper.find('input').trigger('keyup.enter');
17+
18+
expect(store.state.todos).to.eql([]);
19+
});
20+
});

src/components/List.vue

+3-4
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,20 @@
44
<label htmlFor="toggle-all" @click="onCompleteAll"></label>
55

66
<ul class="todo-list">
7-
<Item v-for="todo in todos" :key="todo.id" :todo="todo" @remove="onRemove" @update="onUpdate" />
7+
<Item v-for="todo in visibleTodos" :key="todo.id" :todo="todo" @remove="onRemove" @update="onUpdate" />
88
</ul>
99
</section>
1010
</template>
1111

1212
<script>
13-
import { mapState, mapActions, mapGetters } from 'vuex';
13+
import { mapActions, mapGetters } from 'vuex';
1414
import Item from './Item.vue';
1515
1616
export default {
1717
name: 'List',
1818
components: { Item },
1919
computed: {
20-
...mapState(['todos']),
21-
...mapGetters(['areAllCompleted'])
20+
...mapGetters(['areAllCompleted', 'visibleTodos'])
2221
},
2322
methods: {
2423
...mapActions(['onRemove', 'onUpdate', 'onCompleteAll'])

src/components/Todos.vue

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<template>
2+
<section class="todoapp">
3+
<Header />
4+
<List />
5+
<Footer />
6+
</section>
7+
</template>
8+
9+
<script>
10+
import { mapActions } from 'vuex';
11+
import Header from './Header.vue';
12+
import List from './List.vue';
13+
import Footer from './Footer.vue';
14+
import { FILTERS } from '../constants/Filters';
15+
16+
export default {
17+
name: 'todos',
18+
components: { Header, List, Footer },
19+
methods: {
20+
...mapActions(['onFilterSelect']),
21+
},
22+
mounted() {
23+
this.onFilterSelect(this.$route.params.filter || FILTERS.all);
24+
},
25+
watch: {
26+
$route() {
27+
this.onFilterSelect(this.$route.params.filter || FILTERS.all);
28+
}
29+
}
30+
}
31+
</script>

src/main.js

+4
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
import Vue from 'vue';
22
import Vuex from 'vuex';
3+
import VueRouter from 'vue-router';
34
import App from './components/App.vue';
45
import 'todomvc-app-css/index.css';
56
import { storeFactory } from './store/factory';
7+
import { routerFactory } from './routes';
68

79
Vue.config.productionTip = false;
810
Vue.use(Vuex);
11+
Vue.use(VueRouter);
912

1013
new Vue({
1114
store: storeFactory(),
15+
router: routerFactory(),
1216
render: h => h(App)
1317
}).$mount('#app');

src/routes.js

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import VueRouter from 'vue-router';
2+
import Todos from './components/Todos.vue';
3+
4+
const routes = [
5+
{ path: '/', component: Todos },
6+
{ path: '/:filter', component: Todos },
7+
];
8+
9+
export const routerFactory = () => new VueRouter({ routes });

src/store/factory.spec.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ import { storeFactory } from './factory';
55

66
describe('storeFactory', function() {
77
it('should create a new instance of vuex store', function() {
8-
const vue = createLocalVue();
9-
vue.use(Vuex);
8+
const localVue = createLocalVue();
9+
localVue.use(Vuex);
1010
const store = storeFactory();
1111

1212
expect(store.state.todos).to.eql([]);

0 commit comments

Comments
 (0)