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
|
||||
|
||||
![Vue Architecture](img/vue_arch.png)
|
||||
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