Notions Technical Notes

website·Indexed 30 days ago

https://christyoung.github.io/notions/

A collection of personal technical notes and tips covering front-end development, including CSS layout techniques, JavaScript utilities, React key usage, Vue 3 with TypeScript and Vite, Angular library construction, RxJS operators, and VS Code configurations.

Tokens
17.9K
Snippets
128
Records
149
Agent score
74%

What's inside Notions

  1. Install and initialize MSW v1.2.3 in Angular

    To set up MSW v1.2.3 for API mocking in an Angular project, install the package and initialize the service worker. Running the init command generates the necessary mockServiceWorker.js file in the source directory.
    npm install msw@1.2.3
    npx msw init src/ --save
  2. Validate passwords and character sets

    Regular expressions for password length and character composition requirements.
    // Password length between 6 and 18 digits
    const passwordLengthRegex = /^\d{6,18}$/;
    
    // Ensure password contains both letters and numbers
    const passwordCharRegex = /[A-Za-z]+[0-9]/;
    
    // String consisting only of alphanumeric characters or underscores
    const alphanumericRegex = /^\w+$/;
    
    // Only Chinese characters
    const chineseRegex = /^[\u4e00-\u9fa5]{0,}$/;
  3. Activate MSW worker in Angular main.ts

    To start intercepting network requests, import the worker from your mock configuration and call .start() in the application's entry point (main.ts).
    // main.ts
    import { worker } from './mock/browser';
    
    worker.start();
  4. Prevent input events during IME composition

    When using Input Method Editors (IME) for languages like Chinese, the input event may trigger while the user is still selecting a word from a candidate list, before the text is actually committed to the field. To ensure the input event only triggers after the final text is entered, use compositionstart and compositionend events to create a lock.
    var node = document.querySelector('#person');
    var cpLock = false;
    
    // Lock when composition starts (e.g., typing in Chinese IME)
    node.addEventListener('compositionstart', function() {
        cpLock = true;
    });
    
    // Unlock when composition ends (text is committed)
    node.addEventListener('compositionend', function() {
        cpLock = false;
    });
    
    // Only execute logic if the user is not currently composing text
    node.addEventListener('input', function() {
        if (!cpLock) {
            console.log(this.value);
        }
    });
  5. Prevent flex items from shrinking to enable horizontal scrolling

    By default, flex items will shrink to fit within the container's width even if their defined widths exceed it, which prevents overflow-x: auto from triggering a scrollbar. To maintain the fixed width of child elements and enable horizontal scrolling when the total width exceeds the parent container, set flex-shrink: 0 on the child elements.
    .container {
      display: flex;
      width: 100%;
      height: 600px;
      background: green;
      overflow-x: auto; /* Enables horizontal scrolling */
    }
    
    .chzn-choices {
      width: 20%;
      height: 200px;
      background: red;
      flex-shrink: 0; /* Prevents the item from shrinking, forcing the container to scroll */
    }
  6. Configure CSS for print styles using media queries

    Use the @media print query to define styles specifically for printing. Instead of rewriting all CSS, only override the properties that differ from the screen display. It is recommended to manually set colors (e.g., black text on white background) because browsers may automatically alter colors to save ink.
    @media print {
      body {
        color: #000;
        background: #fff;
      }
      
      /* Hide irrelevant elements like navigation or sidebars */
      nav, aside {
        display: none;
      }
    }
  7. Create and subscribe to a basic RxJS Observable

    To use RxJS, you create an Observable instance and call .subscribe() to start receiving values. The Observable defines the data production logic via a subscriber, while the subscription defines how to handle those values.
    import { Observable } from 'rxjs';
    
    (() => {
        // Define the Observable and its data production
        const _instance = new Observable(subscriber => {
            subscriber.next(1);
            subscriber.complete();
        });
    
        // Subscribe to the Observable to handle the values
        _instance.subscribe({
            next: (val) => console.log(`hello ${val}`),
            complete: () => console.log('i have been already finished~')
        });
    })();
  8. Understand core RxJS terminology

    RxJS uses specific terminology to describe the flow of data and the management of streams:

    • Observable: The class that carries RxJS operators and represents a stream of data.
    • Observer: Defines how to handle values when they change (the logic for processing the data).
    • Subscription: An object returned by the subscribe method that allows you to cancel the execution using .unsubscribe().
    • Subscriber: An object instantiated from the Observer's parameters; it inherits from Subscription and acts as both an Observer and a Subscription handler.
    • subscribe: The action of connecting an Observer to an Observable. It defines what operations occur during initialization and passes the Observer to the stream to receive values (similar to how then works in Promises).
  9. Simulate fixed positioning relative to a parent element using an assistor wrapper

    Standard position: fixed anchors an element to the viewport. To make an element appear 'fixed' relative to a specific parent container (where the element stays put while other content inside that parent scrolls), use a wrapper element (an 'assistor') with position: relative.

    By placing the 'fixed' child as a direct descendant of the relative assistor and the scrollable content inside a separate parent div, the child remains positioned relative to the assistor's boundaries and does not move when the inner parent's scrollbar is used.

    <div class="assistor">
      <div class="parent">
        <div class="child">Fixed Position Area</div>
        <div class="placeholder">Scrollable Content Area</div>
      </div>
    </div>
    .assistor {
      position: relative; /* Essential: provides the coordinate system for the child */
      display: block;
      width: 500px;
      height: 300px;
      background-color: #ddd;
    }
    
    .parent {
      width: 500px;
      height: 300px;
      background-color: #888;
      overflow: auto; /* Essential: enables scrolling for the content */
    }
    
    .child {
      position: absolute; /* Essential: positions relative to .assistor, not .parent */
      width: 120px;
      height: 120px;
      margin: 100px 50px;
      background-color: #333;
      color: #fff;
    }
    
    .placeholder {
      width: 1000px;
      height: 1000px;
      color: #fff;
    }
  10. Create project-specific code snippets in VS Code

    To create code snippets that are scoped only to a specific project, create a .vscode folder in the project root and add a file named snippets.code-snippets. Define snippets in this file using a JSON format containing a prefix, body (as an array of strings), and a description.
    {
      "snippet": {
        "prefix": "mySnippet",
        "body": [
          "console.log('Hello, World!');"
        ],
        "description": "My custom code snippet"
      }
    }
  11. Manage multiple remote origins in a Git repository

    You can add multiple remote servers (origins) to a single local repository to push code to different platforms (e.g., both GitHub and Gitee).
    # List existing remote repositories
    git remote -v
    
    # Add a new remote repository with a specific name
    git remote add [origin-name] [repo-url]
    
    # Push code to a specific remote
    git push [origin-name]
  12. Maintain reactivity when destructuring Pinia store state

    When destructuring state from a Pinia store in Vue 3, the reactivity behavior depends on the data type:

    • If the state is an object, destructuring it results in a reactive object.
    • If the state is a primitive (basic variable), destructuring it causes the loss of reactivity.

    To ensure consistency and maintain reactivity regardless of whether the state is an object or a primitive, use the storeToRefs utility to convert the destructured properties into Ref variables.

    import { storeToRefs } from 'pinia'
    import { useUserStore } from '@/stores/user'
    
    const store = useUserStore()
    // Use storeToRefs to maintain reactivity for both primitives and objects
    const { name, settings } = storeToRefs(store)