<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                # Vue > 原文:[https://docs.gitlab.com/ee/development/fe_guide/vue.html](https://docs.gitlab.com/ee/development/fe_guide/vue.html) * [Examples](#examples) * [Vue architecture](#vue-architecture) * [Components and Store](#components-and-store) * [An `index.js` file](#an-indexjs-file) * [Bootstrapping Gotchas](#bootstrapping-gotchas) * [Providing data from HAML to JavaScript](#providing-data-from-haml-to-javascript) * [Accessing the `gl` object](#accessing-the-gl-object) * [Accessing feature flags](#accessing-feature-flags) * [A folder for Components](#a-folder-for-components) * [A folder for the Store](#a-folder-for-the-store) * [Vuex](#vuex) * [Mixing Vue and jQuery](#mixing-vue-and-jquery) * [Style guide](#style-guide) * [Testing Vue Components](#testing-vue-components) * [Test the component’s output](#test-the-components-output) * [Events](#events) * [Vue.js Expert Role](#vuejs-expert-role) * [Vue 2 -> Vue 3 Migration](#vue-2---vue-3-migration) * [Appendix - Vue component subject under test](#appendix---vue-component-subject-under-test) # Vue[](#vue "Permalink") 要開始使用 Vue,請通讀[其文檔](https://vuejs.org/v2/guide/) . ## Examples[](#examples "Permalink") 在以下示例中可以找到以下各節中描述的內容: * [Web IDE](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/app/assets/javascripts/ide/stores) * [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) ## Vue architecture[](#vue-architecture "Permalink") 用 Vue.js 構建的所有新功能都必須遵循[Flux 架構](https://facebook.github.io/flux/) . 我們試圖實現的主要目標是只有一個數據流和一個數據條目. 為了實現此目標,我們使用[vuex](#vuex) . 您還可以在 Vue 文檔中了解有關[狀態管理](https://vuejs.org/v2/guide/state-management.html#Simple-State-Management-from-Scratch)和[數據流的一種方式的](https://vuejs.org/v2/guide/components.html#One-Way-Data-Flow)此體系結構. ### Components and Store[](#components-and-store "Permalink") 在使用 Vue.js 實現的某些功能(例如[問題](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/app/assets/javascripts/boards)公告[板](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/app/assets/javascripts/boards)或[環境表)中,](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/app/assets/javascripts/environments)您可以找到明確的關注點分離: ``` new_feature ├── components │ └── component.vue │ └── ... ├── store │ └── new_feature_store.js ├── index.js ``` *為了保持一致性,我們建議您采用相同的結構.* Let’s look into each of them: ### An `index.js` file[](#an-indexjs-file "Permalink") 這是新功能的索引文件. 這是新功能的根 Vue 實例所在的位置. 應在此文件中導入和初始化商店和服務,并作為主要組件的道具提供. 請務必閱讀[特定](./performance.html#page-specific-javascript)于[頁面的 JavaScript](./performance.html#page-specific-javascript) . ### Bootstrapping Gotchas[](#bootstrapping-gotchas "Permalink") #### Providing data from HAML to JavaScript[](#providing-data-from-haml-to-javascript "Permalink") 掛載 Vue 應用程序時,可能需要從 Rails 向 JavaScript 提供數據. 為此,您可以使用 HTML 元素中的`data`屬性,并在安裝應用程序時查詢它們. *Note:* You should only do this while initializing the application, because the mounted element will be replaced with Vue-generated DOM. 通過`render`函數中的`props`將數據從 DOM 提供給 Vue 實例而不是查詢主 Vue 組件內部的 DOM 的好處是避免了在單元測試中創建固定裝置或 HTML 元素的需要,因為它將進行測試更輕松. 請參見以下示例: ``` // 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, }; }, render(createElement) { return createElement('my-component', { props: { endpoint: this.endpoint, }, }); }, })); ``` #### Accessing the `gl` object[](#accessing-the-gl-object "Permalink") 當我們需要查詢`gl`對象以獲取在應用程序生命周期內不會更改的數據時,我們應該在查詢 DOM 的同一位置進行處理. 通過遵循這種做法,我們可以避免模擬`gl`對象的需求,這將使測試更加容易. 應該在初始化我們的 Vue 實例時完成,并且數據應作為主要組件的`props`提供: ``` document.addEventListener('DOMContentLoaded', () => new Vue({ el: '.js-vue-app', render(createElement) { return createElement('my-component', { props: { username: gon.current_username, }, }); }, })); ``` #### Accessing feature flags[](#accessing-feature-flags "Permalink") 使用 Vue 的[提供/注入](https://vuejs.org/v2/api/#provide-inject)機制使功能標志可用于 Vue 應用程序中的任何后代組件. `glFeatures`對象已經在`commons/vue.js` ,因此僅需要 mixin 即可使用這些標志: ``` // An arbitrary descendant component import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; export default { // ... mixins: [glFeatureFlagsMixin()], // ... created() { if (this.glFeatures.myFlag) { // ... } }, } ``` 這種方法有一些好處: * 任意深度嵌套的組件都可以選擇加入并訪問該標志,而中間組件則不知道(例如,通過 prop 將標志向下傳遞). * 良好的可測試性,因為可以從`vue-test-utils`將該標志提供給`mount` / `shallowMount` ,只是作為一個道具. ``` import { shallowMount } from '@vue/test-utils'; shallowMount(component, { provide: { glFeatures: { myFlag: true }, }, }); ``` * 除了在應用程序的[入口點](#accessing-the-gl-object)之外,無需訪問全局變量. ### A folder for Components[](#a-folder-for-components "Permalink") 此文件夾包含此新功能特定的所有組件. 如果您需要使用或創建可能在其他地方使用的組件,請參考`vue_shared/components` . 了解何時創建組件的一個很好的經驗法則是考慮它是否可以在其他地方重用. 例如,表在整個 GitLab 中被大量使用,表非常適合組件. 另一方面,僅在一個表中使用的表單元格不能很好地利用此模式. 您可以在 Vue.js 網站[Component System 中](https://vuejs.org/v2/guide/#Composing-with-Components)閱讀有關組件的更多信息. ### A folder for the Store[](#a-folder-for-the-store "Permalink") #### Vuex[](#vuex "Permalink") 檢查此[頁面](vuex.html)以獲取更多詳細信息. ### Mixing Vue and jQuery[](#mixing-vue-and-jquery "Permalink") * 不建議將 Vue 和 jQuery 混合使用. * 如果您需要在 Vue 中使用特定的 jQuery 插件,請[圍繞它創建一個包裝器](https://vuejs.org/v2/examples/select2.html) . * Vue 使用 jQuery 事件偵聽器偵聽現有的 jQuery 事件是可以接受的. * 不建議為 Vue 添加新的 jQuery 事件以與 jQuery 交互. ## Style guide[](#style-guide "Permalink") 在編寫 Vue 組件和模板時,請參考我們的[樣式指南](style/vue.html)的 Vue 部分以獲取最佳實踐. ## Testing Vue Components[](#testing-vue-components "Permalink") 每個 Vue 組件都有一個唯一的輸出. 此輸出始終存在于 render 函數中. 盡管我們可以分別測試 Vue 組件的每種方法,但我們的目標必須是測試 render / template 函數的輸出,該輸出始終代表狀態. 這是[此 Vue 組件](#appendix---vue-component-subject-under-test)結構良好的單元測試的示例: ``` import { shallowMount } from '@vue/test-utils'; import { GlLoadingIcon } from '@gitlab/ui'; import MockAdapter from 'axios-mock-adapter'; import axios from '~/lib/utils/axios_utils'; import App from '~/todos/app.vue'; const TEST_TODOS = [ { text: 'Lorem ipsum test text' }, { text: 'Lorem ipsum 2' }, ]; const TEST_NEW_TODO = 'New todo title'; const TEST_TODO_PATH = '/todos'; describe('~/todos/app.vue', () => { let wrapper; let mock; beforeEach(() => { // IMPORTANT: Use axios-mock-adapter for stubbing axios API requests mock = new MockAdapter(axios); mock.onGet(TEST_TODO_PATH).reply(200, TEST_TODOS); mock.onPost(TEST_TODO_PATH).reply(200); }); afterEach(() => { // IMPORTANT: Clean up the component instance and axios mock adapter wrapper.destroy(); wrapper = null; mock.restore(); }); // NOTE: It is very helpful to separate setting up the component from // its collaborators (i.e. Vuex, axios, etc.) const createWrapper = (props = {}) => { wrapper = shallowMount(App, { propsData: { path: TEST_TODO_PATH, ...props, }, }); }; // NOTE: Helper methods greatly help test maintainability and readability. const findLoader = () => wrapper.find(GlLoadingIcon); const findAddButton = () => wrapper.find('[data-testid="add-button"]'); const findTextInput = () => wrapper.find('[data-testid="text-input"]'); const findTodoData = () => wrapper.findAll('[data-testid="todo-item"]').wrappers.map(wrapper => ({ text: wrapper.text() })); describe('when mounted and loading', () => { beforeEach(() => { // Create request which will never resolve mock.onGet(TEST_TODO_PATH).reply(() => new Promise(() => {})); createWrapper(); }); it('should render the loading state', () => { expect(findLoader().exists()).toBe(true); }); }); describe('when todos are loaded', () => { beforeEach(() => { createWrapper(); // IMPORTANT: This component fetches data asynchronously on mount, so let's wait for the Vue template to update return wrapper.vm.$nextTick(); }); it('should not show loading', () => { expect(findLoader().exists()).toBe(false); }); it('should render todos', () => { expect(findTodoData()).toEqual(TEST_TODOS); }); it('when todo is added, should post new todo', () => { findTextInput().vm.$emit('update', TEST_NEW_TODO) findAddButton().vm.$emit('click'); return wrapper.vm.$nextTick() .then(() => { expect(mock.history.post.map(x => JSON.parse(x.data))).toEqual([{ text: TEST_NEW_TODO }]); }); }); }); }); ``` ### Test the component’s output[](#test-the-components-output "Permalink") Vue 組件的主要返回值是渲染的輸出. 為了測試組件,我們需要測試渲染的輸出. [Vue](https://vuejs.org/v2/guide/unit-testing.html)指南的單元測試向我們確切地表明: ### Events[](#events "Permalink") 我們應該測試響應組件中的操作而發出的事件,這對于驗證是否使用正確的參數觸發了正確的事件很有用. 對于任何 DOM 事件,我們都應使用[`trigger`](https://vue-test-utils.vuejs.org/api/wrapper/#trigger)來觸發事件. ``` // Assuming SomeButton renders: <button>Some button</button> wrapper = mount(SomeButton); ... it('should fire the click event', () => { const btn = wrapper.find('button') btn.trigger('click'); ... }) ``` 當我們需要觸發 Vue 事件時,我們應該使用[`emit`](https://vuejs.org/v2/guide/components-custom-events.html)事件來觸發事件. ``` wrapper = shallowMount(DropdownItem); ... it('should fire the itemClicked event', () => { DropdownItem.vm.$emit('itemClicked'); ... }) ``` 我們應該通過對[`emitted()`](https://vue-test-utils.vuejs.org/api/wrapper/#emitted)方法的結果進行斷言來驗證事件已被觸發 ## Vue.js Expert Role[](#vuejs-expert-role "Permalink") 僅當您自己的合并請求并且您的評論顯示時,您才應該申請成為 Vue.js 專家: * 對 Vue 和 Vuex 反應性的深入了解 * Vue 和 Vuex 代碼是根據官方規范和我們的準則構建的 * 全面了解測試 Vue 和 Vuex 應用程序 * Vuex 代碼遵循[記錄的模式](vuex.html#naming-pattern-request-and-receive-namespaces) * 有關現有 Vue 和 Vuex 應用程序以及現有可重用組件的知識 ## Vue 2 -> Vue 3 Migration[](#vue-2---vue-3-migration "Permalink") > 暫時添加此部分是為了支持將代碼庫從 Vue 2.x 遷移到 Vue 3.x 的工作. 當前,我們建議盡量減少向代碼庫中添加某些功能,以防止增加最終遷移的技??術負擔: * filters; * 活動巴士; * 功能模板化 * `slot` attributes 您可以找到有關[遷移到 Vue 3 的](vue3_migration.html)更多詳細信息 ## Appendix - Vue component subject under test[](#appendix---vue-component-subject-under-test "Permalink") 這是示例組件的模板,已在" [測試 Vue 組件"](#testing-vue-components)部分中進行了[測試](#testing-vue-components) : ``` <template> <div class="content"> <gl-loading-icon v-if="isLoading" /> <template v-else> <div v-for="todo in todos" :key="todo.id" :class="{ 'gl-strike': todo.isDone }" data-testid="todo-item" >{{ toddo.text }}</div> <footer class="gl-border-t-1 gl-mt-3 gl-pt-3"> <gl-form-input type="text" v-model="todoText" data-testid="text-input" > <gl-button variant="success" data-testid="add-button" @click="addTodo" >Add</gl-button> </footer> </template> </div> </template> ```
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看