From a65de96b29450ec53a02d2bc645672bff18c6d35 Mon Sep 17 00:00:00 2001 From: Brandon Labuschagne <blabuschagne@gitlab.com> Date: Wed, 11 Nov 2020 17:45:44 +0000 Subject: [PATCH] Refactor based on review feedback Place a general explaination at the top level style guide and link to it from the vue and vuex guides. --- doc/development/fe_guide/style/vue.md | 60 +++++++++++++++++++++++++++ doc/development/fe_guide/vue.md | 29 +++++++------ doc/development/fe_guide/vuex.md | 4 +- 3 files changed, 78 insertions(+), 15 deletions(-) diff --git a/doc/development/fe_guide/style/vue.md b/doc/development/fe_guide/style/vue.md index 4588117f51d06..6b6ca9a6c71ea 100644 --- a/doc/development/fe_guide/style/vue.md +++ b/doc/development/fe_guide/style/vue.md @@ -57,6 +57,66 @@ Please check this [rules](https://github.com/vuejs/eslint-plugin-vue#bulb-rules) 1. Use `.vue` for Vue templates. Do not use `%template` in HAML. +1. Explicitly define data being passed into the Vue app + + ```javascript + // bad + return new Vue({ + el: '#element', + components: { + componentName + }, + provide: { + ...someDataset + }, + props: { + ...anotherDataset + }, + render: createElement => createElement('component-name'), + })); + + // good + const { foobar, barfoo } = someDataset; + const { foo, bar } = anotherDataset; + + return new Vue({ + el: '#element', + components: { + componentName + }, + provide: { + foobar, + barfoo + }, + props: { + foo, + bar + }, + render: createElement => createElement('component-name'), + })); + ``` + + We discourage the use of the spread operator in this specific case in + order to keep our codebase explicit, discoverable, and searchable. + This applies in any place where we'll benefit from the above, such as + when [initializing Vuex state](../vuex.md#why-not-just-spread-the-initial-state). + The pattern above also enables us to easily parse non scalar values during + instantiation. + + ```javascript + return new Vue({ + el: '#element', + components: { + componentName + }, + props: { + foo, + bar: parseBoolean(bar) + }, + render: createElement => createElement('component-name'), + })); + ``` + ## Naming 1. **Extensions**: Use `.vue` extension for Vue components. Do not use `.js` as file extension ([#34371](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/34371)). diff --git a/doc/development/fe_guide/vue.md b/doc/development/fe_guide/vue.md index b90566bc2fcd4..578c364052e45 100644 --- a/doc/development/fe_guide/vue.md +++ b/doc/development/fe_guide/vue.md @@ -66,29 +66,32 @@ You should only do this while initializing the application, because the mounted The advantage of providing data from the DOM to the Vue instance through `props` in the `render` function instead of querying the DOM inside the main Vue component is avoiding the need to create a fixture or an HTML element in the unit test, -which will make the tests easier. See the following example: +which will make the tests easier. + +See the following example, also, please refer to our [Vue style guide](style/vue.md#basic-rules) for additional +information on why we explicitly declare the data being passed into the Vue app; ```javascript // haml #js-vue-app{ data: { endpoint: 'foo' }} // index.js -document.addEventListener('DOMContentLoaded', () => new Vue({ - el: '#js-vue-app', - data() { - const dataset = this.$options.el.dataset; - return { - endpoint: dataset.endpoint, - }; - }, +const el = document.getElementById('js-vue-app'); + +if (!el) return false; + +const { endpoint } = el.dataset; + +return new Vue({ + el, render(createElement) { return createElement('my-component', { props: { - endpoint: this.endpoint, + endpoint }, }); }, -})); +} ``` > When adding an `id` attribute to mount a Vue application, please make sure this `id` is unique across the codebase @@ -100,7 +103,7 @@ By following this practice, we can avoid the need to mock the `gl` object, which It should be done while initializing our Vue instance, and the data should be provided as `props` to the main component: ```javascript -document.addEventListener('DOMContentLoaded', () => new Vue({ +return new Vue({ el: '.js-vue-app', render(createElement) { return createElement('my-component', { @@ -109,7 +112,7 @@ document.addEventListener('DOMContentLoaded', () => new Vue({ }, }); }, -})); +}); ``` #### Accessing feature flags diff --git a/doc/development/fe_guide/vuex.md b/doc/development/fe_guide/vuex.md index fb64095bbaae1..7765ba04d40cf 100644 --- a/doc/development/fe_guide/vuex.md +++ b/doc/development/fe_guide/vuex.md @@ -360,8 +360,8 @@ export default initialState => ({ ``` We've made the conscious decision to avoid this pattern to aid in the -discoverability and searchability of our frontend codebase. The reasoning for -this is described in [this +discoverability and searchability of our frontend codebase. The same applies +when [providing data to a Vue app](vue.md#providing-data-from-haml-to-javascript). The reasoning for this is described in [this discussion](https://gitlab.com/gitlab-org/frontend/rfcs/-/issues/56#note_302514865): > Consider a `someStateKey` is being used in the store state. You _may_ not be -- GitLab