Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'doc/development/fe_guide/vue.md')
-rw-r--r--doc/development/fe_guide/vue.md99
1 files changed, 96 insertions, 3 deletions
diff --git a/doc/development/fe_guide/vue.md b/doc/development/fe_guide/vue.md
index 119a91e33b5..65ceb9f0220 100644
--- a/doc/development/fe_guide/vue.md
+++ b/doc/development/fe_guide/vue.md
@@ -16,11 +16,23 @@ What is described in the following sections can be found in these examples:
- [Security products](https://gitlab.com/gitlab-org/gitlab/-/tree/master/ee/app/assets/javascripts/vue_shared/security_reports)
- [Registry](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/app/assets/javascripts/registry/stores)
+## When to add Vue application
+
+Sometimes, HAML page is enough to satisfy requirements. This statement is correct primarily for the static pages or pages that have very little logic. How do we know it's worth adding a Vue application to the page? The answer is "when we need to maintain application state and synchronize the rendered page with it".
+
+To better explain this, let's imagine the page that has one toggle, and toggling it sends an API request. This case does not involve any state we want to maintain, we send the request and switch the toggle. However, if we add ont more toggle that should always be the opposite to the first one, we need a _state_: one toggle should be "aware" about the state of another one. When written in plain JavaScript, this logic usually involves listening to DOM event and reacting with modifying DOM. Cases like this are much easier to handle with Vue.js so we should create a Vue application here.
+
+### What are some flags signaling that you might need Vue application?
+
+- when you need to define complex conditionals based on multiple factors and update them on user interaction;
+- when you have to maintain any form of application state and share it between tags/elements;
+- when you expect complex logic to be added in the future - it's easier to start with basic Vue application than having to rewrite JS/HAML to Vue on the next step.
+
## Vue architecture
-All new features built with Vue.js must follow a [Flux architecture](https://facebook.github.io/flux/).
+All new features built with Vue.js must follow a [Flux architecture](https://facebookarchive.github.io/flux/).
The main goal we are trying to achieve is to have only one data flow, and only one data entry.
-To achieve this goal we use [Vuex](#vuex).
+To achieve this goal we use [Vuex](#vuex) or [Apollo Client](graphql.md#libraries)
You can also read about this architecture in Vue documentation about
[state management](https://v2.vuejs.org/v2/guide/state-management.html#Simple-State-Management-from-Scratch)
@@ -121,7 +133,7 @@ export default {
```javascript
//index.js
import MyComponent from './my_component.vue'
-import initSimpleApp from '~/helpers/init_simple_app_helper'
+import { initSimpleApp } from '~/helpers/init_simple_app_helper'
initSimpleApp('#js-my-element', MyComponent)
```
@@ -391,6 +403,87 @@ You can read more about components in Vue.js site, [Component System](https://v2
Check this [page](vuex.md) for more details.
+### Vue Router
+
+To add [Vue Router](https://router.vuejs.org/) to a page:
+
+1. Add a catch-all route to the Rails route file using a wildcard named `*vueroute`:
+
+ ```ruby
+ # example from ee/config/routes/project.rb
+
+ resources :iteration_cadences, path: 'cadences(/*vueroute)', action: :index
+ ```
+
+ The above example serves the `index` page from `iteration_cadences` controller to any route
+ matching the start of the `path`, for example `groupname/projectname/-/cadences/123/456/`.
+1. Pass the base route (everything before `*vueroute`) to the frontend to use as the `base` parameter to initialize Vue Router:
+
+ ```haml
+ .js-my-app{ data: { base_path: project_iteration_cadences_path(project) } }
+ ```
+
+1. Initialize the router:
+
+ ```javascript
+ Vue.use(VueRouter);
+
+ export function createRouter(basePath) {
+ return new VueRouter({
+ routes: createRoutes(),
+ mode: 'history',
+ base: basePath,
+ });
+ }
+ ```
+
+1. Add a fallback for unrecognised routes with `path: '*'`. Either:
+ - Add a redirect to the end of your routes array:
+
+ ```javascript
+ const routes = [
+ {
+ path: '/',
+ name: 'list-page',
+ component: ListPage,
+ },
+ {
+ path: '*',
+ redirect: '/',
+ },
+ ];
+ ```
+
+ - Add a fallback component to the end of your routes array:
+
+ ```javascript
+ const routes = [
+ {
+ path: '/',
+ name: 'list-page',
+ component: ListPage,
+ },
+ {
+ path: '*',
+ component: NotFound,
+ },
+ ];
+ ```
+
+1. Optional. To also allow using the path helper for child routes, add `controller` and `action`
+ parameters to use the parent controller.
+
+ ```ruby
+ resources :iteration_cadences, path: 'cadences(/*vueroute)', action: :index do
+ resources :iterations, only: [:index, :new, :edit, :show], constraints: { id: /\d+/ }, controller: :iteration_cadences, action: :index
+ end
+ ```
+
+ This means routes like `/cadences/123/iterations/456/edit` can be validated on the backend,
+ for example to check group or project membership.
+ It also means we can use the `_path` helper, which means we can load the page in feature specs
+ without manually building the `*vueroute` part of the path..
+
### Mixing Vue and jQuery
- Mixing Vue and jQuery is not recommended.