True modularity
Front-end modularization began very early. Whether it is required.js, browserify for modular packaging, or Angular for dependency injection, we can divide the JS code into small modules and assemble them. Then we will also use less or sass to break the CSS file into small modules to write, and we even feel the object-oriented characteristics of encapsulation, inheritance, polymorphism, etc. in the CSS code.
However, before webpack came out, what we called modularity could not be considered modularity at all. Why do we say this? Because there is an important problem that has not been solved, which is the dependence of JS module on CSS modules.
For example, if we have a JS module modal, can we directly import and call it to pop up a dialog box? Is it OK as shown in the figure below?
Theoretically, this should be the case, but in fact, this modal actually relies on a corresponding CSS module modal.less. If we do not import this module, we cannot pop up a normal dialog box. Moreover, importing this CSS module is not written in the same place as importing the JS module, but in another CSS file. In other words, the dependency is actually like this:
In order to use a module, we need to do an import operation in two files one by one. This is actually a very strange and unreasonable thing! Why do we need to be modular? It is to encapsulate a module, which can be used after importing it. How it is implemented and what dependencies it has are entirely handled by this module itself. That is, the dependency on modal.css in the figure above should be handled by modal.js itself.
But we have been writing modules like this for the front-end that we have written for N years, not because it is right, but because we are used to this wrong way. Now using Vue, we can completely encapsulate all the dependencies of a module. Whether it is templates, CSS or JS, we don’t need to care about it anymore. Just introduce this module and it can use it, and the dependencies of the module are handled by itself.
Then our dependency becomes:
modal.vue contains all the required dependencies, so we no longer need to deal with the corresponding CSS or even templates ourselves. This is the effect that modularity should achieve.
Create a Vue project
Vue provides a tool vue-cli to create a project template: https://github.com/vuejs/vue-cli
Here I first tried another template project: https://github.com/vuejs-templates/webpack
Then we can write modules instead of using pure JS, but use webpack to write all the content related to a module into a file. Taking the previous todo list as an example, in fact, the previous chapter only talked about the usage of component, so I wrote that way. Let's change it to a better writing method as follows:
List.vue:
<template> <ul> <li v-for='todo in list'> <label v-bind:class="{ done : todo.done }" > <input type="checkbox" v-model="todo.done"/> {{todo.title}} </label> </li> </ul></template><script>export default { props: { initList: { type: Array } }, data () { return { list: [] } }, events: { add (input) { if (!input) return false this.list.unshift({ title: input, done: false }) } }}</script><style lang="less" scoped>ul { margin-left: 2rem; padding: 0; .done { text-decoration: line-through; }}</style>Form.vue:
<template> <h1>{{username}}'s Todo List</h1> <form v-on:submit="add" v-on:submit.prevent> <input type="text" v-model="input"/> <input type="submit" value='add' /> </form></template><script>export default { props: { username: { type: String, default: 'Unnamed' } }, data () { return { input: '' } }, methods: { add () { this.$dispatch('add', this.input) this.input = '' } }}</script>Todo.vue:
<template> <div id="todo"> <todo-form username='Lily'></todo-form> <todo-list></todo-list> </div></template><script>import Form from './Form.vue'import List from './List.vue'export default { components: { 'todo-form': Form, 'todo-list': List }, events: { add (input) { this.$broadcast('add', input) } }}</script><style></style>App.vue:
<template> <todo></todo></template><script>import Todo from './components/Todo.vue'export default { components: { 'todo': Todo }}</script><style></style>In this way, we rewritten the previous Todo List as modularly. Modularity is one of the foundations for building large applications, but this is not enough, we still need to do:
•Best state management, independent management of state shared by different components
•Automated testing
•Routing, etc.
Here we only do one of them, which is to separate State into a separate module. Obviously, for a Todo List application, the data structure that saves the todo list is the State shared by different components.
Why did we need to broadcast events before? It was because the data to be operated between different components was saved in List.vue. Therefore, when you want to add a piece of data in Form.vue, you need to notify List.vue to add it through events.
In other words, this data is not private by List.vue, and should be at least publicly owned by these two components. Now that it is owned by List.vue, Form.vue cannot modify it and has to notify it through the event.
Although the event method is elegant, we can actually do better, which is to separate the data, so that both Form.vue and List.vue can directly modify the data without having to send notifications.
Here we add a Store.js file:
export default { list: [ ], add (title) { if (!title) return this.list.unshift({ title: title, done: false }) }}Then we can change List.vue to this, and only the JS part of the code is posted here:
import Store from '../Store.js'export default { props: { initList: { type: Array } }, data () { return Store }}Form.vue does not require broadcasting, you can add it by calling the Store.add method directly:
import Store from '../Store.js'export default { props: { username: { type: String, default: 'Unnamed' } }, data () { return { input: '' } }, methods: { add () { Store.add(this.input) this.input = '' } }}After this change, the entire logic will be much clearer, and the more complex the application is, the more you should extract the public store, otherwise there will be broadcast events flying all over the sky.
In addition, after using this project template, hot-reload is so cool and refreshing is saved.
The above source code is here: https://github.com/lihongxun945/vue-webpack-todo-list
The above is all the content of this article. I hope it will be helpful to everyone's learning and I hope everyone will support Wulin.com more.