Remove old service architecture from Vue docs
This commit is contained in:
		
							parent
							
								
									0399b644ec
								
							
						
					
					
						commit
						5cb48d3686
					
				
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 9.6 KiB | 
|  | @ -2,27 +2,24 @@ | |||
| 
 | ||||
| To get started with Vue, read through [their documentation][vue-docs]. | ||||
| 
 | ||||
| ## Examples | ||||
| 
 | ||||
| What is described in the following sections can be found in these examples: | ||||
| 
 | ||||
| - web ide: https://gitlab.com/gitlab-org/gitlab-ce/tree/master/app/assets/javascripts/ide/stores | ||||
| - security products: https://gitlab.com/gitlab-org/gitlab-ee/tree/master/ee/app/assets/javascripts/vue_shared/security_reports | ||||
| - registry: https://gitlab.com/gitlab-org/gitlab-ce/tree/master/app/assets/javascripts/registry/stores | ||||
| 
 | ||||
| ## Vue architecture | ||||
| 
 | ||||
| All new features built with Vue.js must follow a [Flux architecture][flux]. | ||||
| The main goal we are trying to achieve is to have only one data flow and only one data entry. | ||||
| In order to achieve this goal, you can either use [vuex](#vuex) or use the [store pattern][state-management], explained below: | ||||
| 
 | ||||
| Each Vue bundle needs a Store - where we keep all the data -, a Service - that we use to communicate with the server - and a main Vue component. | ||||
| 
 | ||||
| Think of the Main Vue Component as the entry point of your application. This is the only smart | ||||
| component that should exist in each Vue feature. | ||||
| This component is responsible for: | ||||
| 1. Calling the Service to get data from the server | ||||
| 1. Calling the Store to store the data received | ||||
| 1. Mounting all the other components | ||||
| 
 | ||||
|  | ||||
| In order to achieve this goal we use [vuex](#vuex). | ||||
| 
 | ||||
| You can also read about this architecture in vue docs about [state management][state-management] | ||||
| and about [one way data flow][one-way-data-flow]. | ||||
| 
 | ||||
| ### Components, Stores and Services | ||||
| ### Components and Store | ||||
| 
 | ||||
| In some features implemented with Vue.js, like the [issue board][issue-boards] | ||||
| or [environments table][environments-table] | ||||
|  | @ -33,10 +30,8 @@ new_feature | |||
| ├── components | ||||
| │   └── component.vue | ||||
| │   └── ... | ||||
| ├── stores | ||||
| ├── store | ||||
| │  └── new_feature_store.js | ||||
| ├── services # only when not using vuex | ||||
| │  └── new_feature_service.js | ||||
| ├── index.js | ||||
| ``` | ||||
| _For consistency purposes, we recommend you to follow the same structure._ | ||||
|  | @ -125,217 +120,6 @@ You can read more about components in Vue.js site, [Component System][component- | |||
| #### Vuex | ||||
| Check this [page](vuex.md) for more details. | ||||
| 
 | ||||
| #### Flux like state management | ||||
| The Store is a class that allows us to manage the state in a single | ||||
| source of truth. It is not aware of the service or the components. | ||||
| 
 | ||||
| The concept we are trying to follow is better explained by Vue documentation | ||||
| itself, please read this guide: [State Management][state-management] | ||||
| 
 | ||||
| ### A folder for the Service | ||||
| 
 | ||||
| **If you are using Vuex you won't need this step** | ||||
| 
 | ||||
| The Service is a class used only to communicate with the server. | ||||
| It does not store or manipulate any data. It is not aware of the store or the components. | ||||
| We use [axios][axios] to communicate with the server. | ||||
| Refer to [axios](axios.md) for more details. | ||||
| 
 | ||||
| Axios instance should only be imported in the service file. | ||||
| 
 | ||||
| ```javascript | ||||
| import axios from '~/lib/utils/axios_utils'; | ||||
| ``` | ||||
| 
 | ||||
| ### End Result | ||||
| 
 | ||||
| The following example shows an application: | ||||
| 
 | ||||
| ```javascript | ||||
| // store.js | ||||
| export default class Store { | ||||
| 
 | ||||
|   /** | ||||
|    * This is where we will iniatialize the state of our data. | ||||
|    * Usually in a small SPA you don't need any options when starting the store. | ||||
|    * In that case you do need guarantee it's an Object and it's documented. | ||||
|    * | ||||
|    * @param  {Object} options | ||||
|    */ | ||||
|   constructor(options) { | ||||
|     this.options = options; | ||||
| 
 | ||||
|     // Create a state object to handle all our data in the same place | ||||
|     this.todos = []; | ||||
|   } | ||||
| 
 | ||||
|   setTodos(todos = []) { | ||||
|     this.todos = todos; | ||||
|   } | ||||
| 
 | ||||
|   addTodo(todo) { | ||||
|     this.todos.push(todo); | ||||
|   } | ||||
| 
 | ||||
|   removeTodo(todoID) { | ||||
|     const state = this.todos; | ||||
| 
 | ||||
|     const newState = state.filter((element) => {element.id !== todoID}); | ||||
| 
 | ||||
|     this.todos = newState; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| // service.js | ||||
| import axios from '~/lib/utils/axios_utils' | ||||
| 
 | ||||
| export default class Service { | ||||
|   constructor(options) { | ||||
|     this.todos = axios.create({ | ||||
|       baseURL: endpoint.todosEndpoint | ||||
|     }); | ||||
| 
 | ||||
|   } | ||||
| 
 | ||||
|   getTodos() { | ||||
|     return this.todos.get(); | ||||
|   } | ||||
| 
 | ||||
|   addTodo(todo) { | ||||
|     return this.todos.put(todo); | ||||
|   } | ||||
| } | ||||
| // todo_component.vue | ||||
| <script> | ||||
| export default { | ||||
|   props: { | ||||
|     data: { | ||||
|       type: Object, | ||||
|       required: true, | ||||
|     }, | ||||
|   }, | ||||
| }; | ||||
| </script> | ||||
| <template> | ||||
|   <div> | ||||
|     <h1> | ||||
|       Title: {{data.title}} | ||||
|     </h1> | ||||
|     <p> | ||||
|       {{data.text}} | ||||
|     </p> | ||||
|   </div> | ||||
| </template> | ||||
| 
 | ||||
| // todos_main_component.vue | ||||
| <script> | ||||
| import Store from 'store'; | ||||
| import Service from 'service'; | ||||
| import TodoComponent from 'todoComponent'; | ||||
| export default { | ||||
|   components: { | ||||
|     todo: TodoComponent, | ||||
|   }, | ||||
|   /** | ||||
|    * Although most data belongs in the store, each component it's own state. | ||||
|    * We want to show a loading spinner while we are fetching the todos, this state belong | ||||
|    * in the component. | ||||
|    * | ||||
|    * We need to access the store methods through all methods of our component. | ||||
|    * We need to access the state of our store. | ||||
|    */ | ||||
|   data() { | ||||
|     const store = new Store(); | ||||
| 
 | ||||
|     return { | ||||
|       isLoading: false, | ||||
|       store: store, | ||||
|       todos: store.todos, | ||||
|     }; | ||||
|   }, | ||||
| 
 | ||||
|   created() { | ||||
|     this.service = new Service('/todos'); | ||||
| 
 | ||||
|     this.getTodos(); | ||||
|   }, | ||||
| 
 | ||||
|   methods: { | ||||
|     getTodos() { | ||||
|       this.isLoading = true; | ||||
| 
 | ||||
|       this.service | ||||
|         .getTodos() | ||||
|         .then(response => { | ||||
|           this.store.setTodos(response); | ||||
|           this.isLoading = false; | ||||
|         }) | ||||
|         .catch(() => { | ||||
|           this.isLoading = false; | ||||
|           // Show an error | ||||
|         }); | ||||
|     }, | ||||
| 
 | ||||
|     addTodo(event) { | ||||
|       this.service | ||||
|         .addTodo({ | ||||
|           title: 'New entry', | ||||
|           text: `You clicked on ${event.target.tagName}`, | ||||
|         }) | ||||
|         .then(response => { | ||||
|           this.store.addTodo(response); | ||||
|         }) | ||||
|         .catch(() => { | ||||
|           // Show an error | ||||
|         }); | ||||
|     }, | ||||
|   }, | ||||
| }; | ||||
| </script> | ||||
| <template> | ||||
|   <div class="container"> | ||||
|     <div v-if="isLoading"> | ||||
|       <i | ||||
|         class="fa fa-spin fa-spinner" | ||||
|         aria-hidden="true" /> | ||||
|     </div> | ||||
| 
 | ||||
|     <div | ||||
|       v-if="!isLoading" | ||||
|       class="js-todo-list"> | ||||
|       <template v-for='todo in todos'> | ||||
|         <todo :data="todo" /> | ||||
|       </template> | ||||
| 
 | ||||
|       <button | ||||
|         @click="addTodo" | ||||
|         class="js-add-todo"> | ||||
|         Add Todo | ||||
|       </button> | ||||
|     </div> | ||||
|   <div> | ||||
| </template> | ||||
| 
 | ||||
| // index.js | ||||
| import todoComponent from 'todos_main_component.vue'; | ||||
| 
 | ||||
| new Vue({ | ||||
|   el: '.js-todo-app', | ||||
|   components: { | ||||
|     todoComponent, | ||||
|   }, | ||||
|   render: createElement => createElement('todo-component' { | ||||
|     props: { | ||||
|       someProp: [], | ||||
|     } | ||||
|   }), | ||||
| }); | ||||
| 
 | ||||
| ``` | ||||
| 
 | ||||
| The [issue boards service][issue-boards-service] | ||||
| is a good example of this pattern. | ||||
| 
 | ||||
| ## Style guide | ||||
| 
 | ||||
| Please refer to the Vue section of our [style guide](style_guide_js.md#vue-js) | ||||
|  | @ -446,6 +230,5 @@ need to test the rendered output. [Vue][vue-test] guide's to unit test show us e | |||
| [state-management]: https://vuejs.org/v2/guide/state-management.html#Simple-State-Management-from-Scratch | ||||
| [one-way-data-flow]: https://vuejs.org/v2/guide/components.html#One-Way-Data-Flow | ||||
| [vue-test]: https://vuejs.org/v2/guide/unit-testing.html | ||||
| [issue-boards-service]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/app/assets/javascripts/boards/services/board_service.js.es6 | ||||
| [flux]: https://facebook.github.io/flux | ||||
| [axios]: https://github.com/axios/axios | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue