jsbay Knowledge Base

website·Indexed 30 days ago

https://jsbay.github.io/vuepress/

A personal technical knowledge base featuring guides and notes on Vue 2, including dynamic components, router lazy loading, and provide/inject. It also covers web development topics like CSS BEM, axios interceptors, webpack configuration, and oAuth 2.0, as well as system administration for Linux, Windows, and Mac, Docker usage for Oracle servers, and Git workflow constraints.

Tokens
10.7K
Snippets
53
Records
68
Agent score
75%

What's inside jsbay Knowledge Base

  1. Understand Vue's Progressive Framework Architecture

    Vue is defined as a progressive framework for building user interfaces, meaning it is designed to be adopted incrementally from the bottom up. Unlike monolithic frameworks, Vue's core library focuses exclusively on the view layer, making it easy to integrate with third-party libraries or existing projects. In a progressive design, the architecture is layered; each layer is optional, allowing developers to flexibly swap specific layers with alternative solutions or architectural patterns.
  2. Implement CDN for external dependencies in Vue 2

    To reduce bundle size and server bandwidth, you can exclude large, stable libraries (like Vue, Vuex, or Element-UI) from the Webpack bundle using externals and inject them via CDN links in the HTML template.

    1. Define the external mapping in vue.config.js using externals.
    2. Pass the CDN URLs to the HTML plugin via chainWebpack.
    3. Update public/index.html to iterate over the CDN arrays and inject the <link> and <script> tags.
    // vue.config.js
    const cdn = {
      css: [
        "https://unpkg.com/element-ui/lib/theme-chalk/index.css",
      ],
      js: [
        "https://unpkg.com/vue/2.5.22/vue.min.js",
        "https://unpkg.com/element-ui/lib/index.js",
        "https://unpkg.com/vuex/3.1.0/vuex.min.js",
      ],
    };
    
    module.exports = {
      externals: {
        vue: "Vue",
        "element-ui": "ELEMENT",
        vuex: "Vuex",
      },
      chainWebpack: (config) => {
        config.plugin("html").tap((args) => {
          args[0].cdn = cdn;
          return args;
        });
      },
    };
    <!-- /public/index.html -->
    <head>
      <% if (process.env.NODE_ENV === 'production') { %>
        <!-- Inject CSS from CDN -->
        <% for(var css of htmlWebpackPlugin.options.cdn.css) { %>
        <link rel="stylesheet" href="<%=css%>" />
        <% } %>
        <!-- Inject JS from CDN -->
        <% for(var js of htmlWebpackPlugin.options.cdn.js) { %>
        <script src="<%=js%>"></script>
        <% } %>
      <% } %>
    </head>
  3. Set up a Mock server for Vue.js using Mockjs

    To implement a mock server that supports both frontend interception and a backend dev-server proxy with hot-reloading, create a mock directory with the following structure:

    • mock/index.js: Main entry point for mock definitions and frontend XHR interception.
    • mock/mock-server.js: Express middleware for the dev server that handles requests and supports hot-reloading via chokidar.
    • mock/utils.js: Utility functions for parsing URL parameters.
    • mock/modules/*.js: Individual mock data modules (e.g., sys.js) defining endpoints, HTTP methods, and response logic.
    package.json
    mock
      |---modules
            |---sys.js
      |---mock-server.js
      |---index.js
      |---utils.js
  4. Cache dynamic components using keep-alive

    Wrap the <component> element in a <keep-alive> tag to preserve the state of components when they are switched out. This prevents the component from being destroyed and re-created, improving performance and maintaining user input or scroll positions.
    <keep-alive>
      <component :is="currentTabComponent"></component>
    </keep-alive>
  5. Implement cross-component communication using provide and inject in Vue 2

    The provide and inject options allow an ancestor component to inject a dependency into all its descendants, regardless of the component hierarchy depth. This acts as a wide-scope alternative to props, enabling one-way data flow from an ancestor to any child, grandchild, or deeper descendant component.
    // Ancestor component providing data
    export default {
      name: "father",
      provide: {
        test: "wawawa",
        age: "20",
      },
      data() {},
    };
    
    // Descendant component (child, grandchild, etc.) injecting data
    export default {
      name: 'children',
      // Inject the keys provided by the ancestor
      inject: ['test', 'age'], 
      created() {
        console.log(this.test); // "wawawa"
        console.log(this.age);  // "20"
      },
    }
  6. Install dependencies for Mock server

    The mock server implementation requires mockjs for data generation and chalk for formatted console logging. If using the server-side mock, chokidar (for file watching) and body-parser (for request parsing) are also needed.
    {
      "devDependencies": {
        "chalk": "2.4.2",
        "mockjs": "1.0.1-beta3"
      }
    }
  7. Register Nginx as a Windows system service using WinSW

    To run Nginx as a background service on Windows, use WinSW (Windows Service Wrapper). This allows Nginx to start automatically on boot and be managed via the Windows Services manager (services.msc).

    Steps:

    1. Download Nginx from the official site and extract it to a directory (e.g., Directory A).
    2. Download the WinSW binary from the Jenkins repository.
    3. Rename the WinSW executable (e.g., winsw-xxx-bin.exe) to nginx-service.exe and place it in Directory A.
    4. Create a configuration file named nginx-service.xml in Directory A to define the service parameters.
    5. Open a Command Prompt as Administrator, navigate to Directory A, and run nginx-service.exe install to register the service.
    6. Start the service via services.msc or the command line.
    # Install the service
    nginx-service.exe install
    
    # Uninstall the service
    nginx-service.exe uninstall
  8. Implement two-way data binding with the .sync modifier in Vue 2

    The .sync modifier in Vue 2 provides a shorthand for syncing a prop from a parent component to a child component. To implement this, the child component must emit an event named update:propName whenever the value changes. In the provided example, the child component uses a local copy of the prop and a watcher to emit the update event back to the parent, ensuring the parent's state remains synchronized with the child's internal state.
    <!-- Parent Component -->
    <template>
      <div>
        <button @click="localModal = true">show</button>
        <!-- The .sync modifier tells Vue to listen for 'update:modal' events -->
        <item :modal.sync="localModal"></item>
      </div>
    </template>
    
    <!-- Child Component (item) -->
    <script>
    export default {
      name: "item",
      props: ["modal"],
      data() {
        return {
          // Initialize local state with the prop value
          localModal: this.modal,
        };
      },
      watch: {
        // Sync prop changes from parent to child
        modal(val) {
          this.localModal = val;
        },
        // Sync local changes from child back to parent
        localModal(val) {
          this.$emit("update:modal", val);
        },
      },
    };
    </script>
  9. Implement dynamic component switching in Vue 2

    Use the <component> element with the :is attribute to dynamically switch between different components at a single mount point. The :is attribute can accept a component name (string) or a component definition object.
    <template>
      <div class="home">
        <!-- The :is attribute determines which component to render -->
        <component :is="currentComponent"></component>
      </div>
    </template>
    
    <script>
    import Tab0 from "@/components/Tab0.vue";
    import Tab1 from "@/components/Tab1.vue";
    
    export default {
      data: () => {
        return {
          currentIndex: 0
        }
      },
      components: {
        "tab-0": Tab0,
        "tab-1": Tab1
      },
      computed: {
        currentComponent() {
          return `tab-${this.currentIndex}`; // Returns "tab-0" or "tab-1"
        }
      }
    }
    </script>
  10. Modify jbot monitoring activity in Qinglong

    jbot monitoring activity can be modified either via the Qinglong Web UI or directly through the container filesystem.
    # Manual modification via CLI
    docker exec -it qinglong /bin/bash
    cd /ql/data/jbot/conf
    # Remove and recreate jk.json
    rm jk.json && touch jk.json && vi jk.json
  11. Implement BEM CSS naming convention

    BEM (Block, Element, Modifier) is a component-based naming convention used to divide a user interface into independent blocks, enabling code reuse and simplifying the development of complex UIs.

    Core Concepts:

    • Block: A reusable, functionally independent page component (e.g., .search-form).
    • Element: A part of a block that cannot be used independently. It is denoted by two underscores (e.g., .search-form__input).
    • Modifier: Defines the appearance, state, or behavior of a block or element. It is denoted by a single underscore (e.g., .search-form_theme_islands).

    Naming Rules:

    1. No Element Nesting: Elements should not be nested within other elements in the class name. Avoid patterns like block__elem1__elem2. Instead, use block__elem2 or block__elem1-elem2.
    2. Modifier Placement: Modifiers can be applied directly to a block (block-name_modifier-name) or to an element (block-name__element-name_modifier-name).
    3. Key-Value Modifiers: Modifiers can follow a key-value pair format for more specificity: block-name_modifier-name_modifier-value.
    <!-- Correct BEM implementation -->
    <form class="search-form search-form_theme_islands">
      <!-- Element of the block -->
      <input class="search-form__input" />
    
      <!-- Element with a size modifier (key: size, value: m) -->
      <button class="search-form__button search-form__button_size_m">Search</button>
    </form>
    
    <!-- INCORRECT: Avoid nesting elements in the name -->
    <div class="search-form__content">
      <input class="search-form__content__input" /> <!-- Wrong -->
    </div>
  12. Use Grouping and Backreferences for complex patterns

    Grouping allows you to treat multiple characters as a single unit and reuse them:

    • (...): Captures a group for quantification or backreferencing.
    • (?:...): Non-capturing group; matches the pattern but does not save the result for backreferencing.
    • \1, \2, etc.: Backreferences that match the exact text captured by a previous group. This is used to ensure consistency, such as matching a closing HTML tag that matches the opening tag (e.g., <(\w+)>.*<\/\1>).