javaweb-Day02-JavaScript&vue

TJCcc 发布于 23 天前 20 次阅读


JavaScript笔记

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>📘 JavaScript 核心笔记 · 中等难度</title>
    <link rel="preconnect" href="https://fonts.googleapis.com" />
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
    <link href="https://fonts.googleapis.com/css2?family=Inter:opsz@14..32&family=JetBrains+Mono:wght@400;600&display=swap" rel="stylesheet" />
    <style>
        /* ===== 基础重置 & 全局 ===== */
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: 'Inter', system-ui, -apple-system, sans-serif;
            background: #f1f5f9;
            color: #0b1120;
            line-height: 1.6;
            padding: 2rem 1rem;
        }

        .container {
            max-width: 1100px;
            margin: 0 auto;
            background: #ffffff;
            padding: 2.5rem 2.8rem;
            border-radius: 28px;
            box-shadow: 0 20px 60px rgba(0, 0, 0, 0.06);
        }

        /* ===== 头部 ===== */
        .header {
            margin-bottom: 2.5rem;
            border-bottom: 2px solid #eef2f6;
            padding-bottom: 1.8rem;
        }

        .header h1 {
            font-size: 2.6rem;
            font-weight: 700;
            letter-spacing: -0.02em;
            background: linear-gradient(135deg, #d97706, #dc2626);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
            background-clip: text;
            display: inline-block;
        }

        .header .sub {
            display: block;
            font-size: 1rem;
            color: #475569;
            margin-top: 0.4rem;
            font-weight: 400;
            -webkit-text-fill-color: #475569;
        }

        /* ===== 通用组件 ===== */
        section {
            margin-bottom: 3rem;
        }

        h2 {
            font-size: 1.6rem;
            font-weight: 600;
            letter-spacing: -0.01em;
            color: #0b1120;
            display: flex;
            align-items: center;
            gap: 0.6rem;
            margin-bottom: 1.2rem;
        }

        h2 .badge {
            font-size: 0.7rem;
            font-weight: 500;
            background: #fef3c7;
            color: #b45309;
            padding: 0.15rem 0.8rem;
            border-radius: 40px;
            letter-spacing: 0.01em;
        }

        h3 {
            font-size: 1.1rem;
            font-weight: 600;
            margin: 1.6rem 0 0.6rem 0;
            color: #1e293b;
        }

        .grid-2col {
            display: grid;
            grid-template-columns: 1fr 1fr;
            gap: 1.8rem;
            margin: 1rem 0;
        }

        .card {
            background: #f9fbfd;
            border-radius: 18px;
            padding: 1.4rem 1.6rem;
            border: 1px solid #edf2f7;
            transition: background 0.15s;
        }

        .card:hover {
            background: #f1f5f9;
        }

        .card h4 {
            font-weight: 600;
            font-size: 1rem;
            margin-bottom: 0.5rem;
            color: #0b1120;
        }

        .card p,
        .card li {
            color: #334155;
            font-size: 0.95rem;
        }

        .card ul {
            list-style: none;
            padding: 0;
            margin-top: 0.4rem;
        }

        .card ul li {
            padding: 0.2rem 0 0.2rem 1.4rem;
            position: relative;
        }

        .card ul li::before {
            content: "▹";
            position: absolute;
            left: 0;
            color: #d97706;
            font-weight: 600;
        }

        /* ===== 代码块 (JS 高亮风格) ===== */
        .code-block {
            background: #0b1120;
            color: #e2e8f0;
            padding: 1.2rem 1.6rem;
            border-radius: 16px;
            font-family: 'JetBrains Mono', 'Fira Code', monospace;
            font-size: 0.85rem;
            overflow-x: auto;
            margin: 0.8rem 0 1.2rem 0;
            line-height: 1.8;
            white-space: pre-wrap;
            word-break: break-word;
            border: 1px solid #1e293b;
        }

        .code-block .comment { color: #94a3b8; font-style: italic; }
        .code-block .keyword { color: #c084fc; }      // const, let, function, etc.
        .code-block .string { color: #34d399; }        // "hello"
        .code-block .number { color: #fbbf24; }        // 42
        .code-block .func { color: #60a5fa; }          // console.log
        .code-block .variable { color: #f472b6; }      // 变量名
        .code-block .operator { color: #f472b6; }      // =, +, =>
        .code-block .bracket { color: #e2e8f0; }

        .inline-code {
            background: #eef2f6;
            color: #1e293b;
            padding: 0.15rem 0.5rem;
            border-radius: 6px;
            font-family: 'JetBrains Mono', monospace;
            font-size: 0.85rem;
            font-weight: 500;
        }

        /* ===== 提示框 ===== */
        .tip {
            background: #ecfdf5;
            border-left: 4px solid #10b981;
            padding: 0.8rem 1.2rem;
            border-radius: 12px;
            margin: 1.2rem 0;
            color: #065f46;
        }
        .tip strong { color: #047857; }

        .warning {
            background: #fffbeb;
            border-left: 4px solid #f59e0b;
            padding: 0.8rem 1.2rem;
            border-radius: 12px;
            margin: 1.2rem 0;
            color: #92400e;
        }
        .warning strong { color: #b45309; }

        .demo-box {
            display: flex;
            gap: 0.6rem;
            flex-wrap: wrap;
            margin: 0.6rem 0;
        }
        .demo-tag {
            background: #dbeafe;
            color: #1e3a8a;
            padding: 0.2rem 0.9rem;
            border-radius: 40px;
            font-size: 0.8rem;
            font-weight: 500;
        }

        /* ===== 响应式 ===== */
        @media (max-width: 700px) {
            .container { padding: 1.5rem 1.2rem; }
            .header h1 { font-size: 2rem; }
            .grid-2col { grid-template-columns: 1fr; gap: 1rem; }
            .code-block { font-size: 0.75rem; padding: 1rem; }
        }

        .footer {
            margin-top: 3rem;
            border-top: 1px solid #e2e8f0;
            padding-top: 1.5rem;
            text-align: center;
            color: #64748b;
            font-size: 0.9rem;
        }
    </style>
</head>
<body>

<div class="container">

    <!-- ===== 头部 ===== -->
    <header class="header">
        <h1>🧬 JavaScript 核心笔记</h1>
        <span class="sub">中等难度 · 聚焦 ES6+ 实用特性 · 告别基础「小白」阶段</span>
    </header>

    <!-- ========================================================== -->
    <!-- 第一部分:变量与声明 -->
    <!-- ========================================================== -->
    <section>
        <h2>📦 变量声明 <span class="badge">let · const · var</span></h2>
        <div class="grid-2col">
            <div class="card">
                <h4>🔹 let &amp; const (ES6)</h4>
                <ul>
                    <li><span class="inline-code">let</span>:可变变量,块级作用域 <span class="inline-code">{ }</span>。</li>
                    <li><span class="inline-code">const</span>:常量(不可重新赋值),块级作用域。</li>
                    <li><span class="inline-code">const</span> 对象/数组内容可变,但引用不可变。</li>
                    <li><strong>优先使用</strong> <span class="inline-code">const</span>,确实需要修改时用 <span class="inline-code">let</span>。</li>
                </ul>
                <div class="code-block">
                    <span class="keyword">let</span> <span class="variable">age</span> <span class="operator">=</span> <span class="number">25</span>;
                    <span class="variable">age</span> <span class="operator">=</span> <span class="number">26</span>; <span class="comment">// ✅ 可以修改</span>

                    <span class="keyword">const</span> <span class="variable">birthYear</span> <span class="operator">=</span> <span class="number">1995</span>;
                    <span class="comment">// birthYear = 1996; ❌ 报错</span>

                    <span class="keyword">const</span> <span class="variable">user</span> <span class="operator">=</span> <span class="bracket">{</span> <span class="variable">name</span>: <span class="string">'Alice'</span> <span class="bracket">}</span>;
                    <span class="variable">user</span>.<span class="variable">name</span> <span class="operator">=</span> <span class="string">'Bob'</span>; <span class="comment">// ✅ 内容可变</span>
                </div>
                <div class="tip">💡 <strong>块级作用域</strong>:<span class="inline-code">if</span>、<span class="inline-code">for</span>、<span class="inline-code">{ }</span> 都会产生块级作用域,<span class="inline-code">var</span> 无视块级(函数级),容易产生 bug,<strong>尽量不用 var</strong>。</div>
            </div>

            <div class="card">
                <h4>🔸 变量提升 (Hoisting)</h4>
                <ul>
                    <li><span class="inline-code">var</span> 会提升到作用域顶部,初始为 <span class="inline-code">undefined</span>。</li>
                    <li><span class="inline-code">let</span> / <span class="inline-code">const</span> 也会提升,但存在「暂时性死区 (TDZ)」,在声明前访问会报错。</li>
                </ul>
                <div class="code-block">
                    <span class="comment">// var 的例子 (不推荐)</span>
                    <span class="keyword">console</span>.<span class="func">log</span>(<span class="variable">x</span>); <span class="comment">// undefined</span>
                    <span class="keyword">var</span> <span class="variable">x</span> <span class="operator">=</span> <span class="number">5</span>;

                    <span class="comment">// let/const TDZ 示例</span>
                    <span class="comment">// console.log(y); // ❌ ReferenceError</span>
                    <span class="keyword">let</span> <span class="variable">y</span> <span class="operator">=</span> <span class="number">10</span>;
                </div>
            </div>
        </div>
    </section>

    <!-- ========================================================== -->
    <!-- 第二部分:函数 (箭头函数 & 默认参数) -->
    <!-- ========================================================== -->
    <section>
        <h2>⚡ 函数进阶 <span class="badge">箭头 · 默认值 · 回调</span></h2>
        <div class="grid-2col">
            <div class="card">
                <h4>🏹 箭头函数 (Arrow Function)</h4>
                <ul>
                    <li>更简洁的语法,<strong>没有自己的 <span class="inline-code">this</span></strong>(继承外层作用域)。</li>
                    <li>如果函数体只有一行 <span class="inline-code">return</span>,可以省略 <span class="inline-code">{ }</span> 和 <span class="inline-code">return</span>(隐式返回)。</li>
                </ul>
                <div class="code-block">
                    <span class="comment">// 传统函数</span>
                    <span class="keyword">function</span> <span class="func">add</span>(<span class="variable">a</span>, <span class="variable">b</span>) <span class="bracket">{</span>
                    <span class="keyword">return</span> <span class="variable">a</span> <span class="operator">+</span> <span class="variable">b</span>;
                    <span class="bracket">}</span>

                    <span class="comment">// 箭头函数</span>
                    <span class="keyword">const</span> <span class="variable">addArrow</span> <span class="operator">=</span> (<span class="variable">a</span>, <span class="variable">b</span>) <span class="operator">=></span> <span class="variable">a</span> <span class="operator">+</span> <span class="variable">b</span>;
                    <span class="keyword">const</span> <span class="variable">square</span> <span class="operator">=</span> <span class="variable">x</span> <span class="operator">=></span> <span class="variable">x</span> <span class="operator">*</span> <span class="variable">x</span>; <span class="comment">// 参数仅一个时可省略括号</span>

                    <span class="comment">// 多行语句需加 {} 和 return</span>
                    <span class="keyword">const</span> <span class="variable">greet</span> <span class="operator">=</span> (<span class="variable">name</span>) <span class="operator">=></span> <span class="bracket">{</span>
                    <span class="keyword">const</span> <span class="variable">msg</span> <span class="operator">=</span> <span class="string">`Hello, </span><span class="variable">${name}</span><span class="string">`</span>;
                    <span class="keyword">return</span> <span class="variable">msg</span>;
                    <span class="bracket">}</span>;
                </div>
            </div>

            <div class="card">
                <h4>📞 默认参数 &amp; 回调</h4>
                <ul>
                    <li><strong>默认参数</strong>:避免 <span class="inline-code">undefined</span> 带来的意外。</li>
                    <li><strong>回调函数</strong>:作为参数传入其他函数,是异步编程的基础。</li>
                </ul>
                <div class="code-block">
                    <span class="comment">// 默认参数</span>
                    <span class="keyword">function</span> <span class="func">multiply</span>(<span class="variable">a</span>, <span class="variable">b</span> <span class="operator">=</span> <span class="number">1</span>) <span class="bracket">{</span>
                    <span class="keyword">return</span> <span class="variable">a</span> <span class="operator">*</span> <span class="variable">b</span>;
                    <span class="bracket">}</span>
                    <span class="func">multiply</span>(<span class="number">5</span>); <span class="comment">// 5</span>

                    <span class="comment">// 回调函数 (数组 forEach 示例)</span>
                    <span class="keyword">const</span> <span class="variable">nums</span> <span class="operator">=</span> <span class="bracket">[</span><span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span><span class="bracket">]</span>;
                    <span class="variable">nums</span>.<span class="func">forEach</span>(<span class="variable">num</span> <span class="operator">=></span> <span class="bracket">{</span>
                    <span class="keyword">console</span>.<span class="func">log</span>(<span class="variable">num</span> <span class="operator">*</span> <span class="number">2</span>);
                    <span class="bracket">}</span>);
                </div>
            </div>
        </div>
    </section>

    <!-- ========================================================== -->
    <!-- 第三部分:数组 & 对象 (解构 + 展开 + 高阶方法) -->
    <!-- ========================================================== -->
    <section>
        <h2>🧩 数组 &amp; 对象操作 <span class="badge">解构 · 展开 · map/filter/reduce</span></h2>
        <p style="color:#334155; margin-bottom:0.8rem;">
            这部分是 JS 进阶的「分水岭」,熟练使用能让代码更优雅、更函数式。
        </p>

        <div class="grid-2col">
            <div class="card">
                <h4>📤 解构赋值 (Destructuring)</h4>
                <ul>
                    <li><strong>数组解构</strong>:按位置提取。</li>
                    <li><strong>对象解构</strong>:按属性名提取,可重命名。</li>
                    <li>常用于函数参数、交换变量。</li>
                </ul>
                <div class="code-block">
                    <span class="comment">// 数组解构</span>
                    <span class="keyword">const</span> <span class="variable">colors</span> <span class="operator">=</span> <span class="bracket">[</span><span class="string">'red'</span>, <span class="string">'green'</span>, <span class="string">'blue'</span><span class="bracket">]</span>;
                    <span class="keyword">const</span> <span class="bracket">[</span><span class="variable">first</span>, <span class="variable">second</span><span class="bracket">]</span> <span class="operator">=</span> <span class="variable">colors</span>;
                    <span class="keyword">console</span>.<span class="func">log</span>(<span class="variable">first</span>); <span class="comment">// 'red'</span>

                    <span class="comment">// 对象解构</span>
                    <span class="keyword">const</span> <span class="variable">user</span> <span class="operator">=</span> <span class="bracket">{</span> <span class="variable">name</span>: <span class="string">'John'</span>, <span class="variable">age</span>: <span class="number">30</span> <span class="bracket">}</span>;
                    <span class="keyword">const</span> <span class="bracket">{</span> <span class="variable">name</span>, <span class="variable">age</span>: <span class="variable">userAge</span> <span class="bracket">}</span> <span class="operator">=</span> <span class="variable">user</span>;
                    <span class="keyword">console</span>.<span class="func">log</span>(<span class="variable">name</span>, <span class="variable">userAge</span>); <span class="comment">// 'John' 30</span>
                </div>
            </div>

            <div class="card">
                <h4>🔗 展开运算符 (Spread) &amp; 剩余参数 (Rest)</h4>
                <ul>
                    <li><span class="inline-code">...</span> 用于「展开」数组/对象,或「收集」剩余参数。</li>
                    <li>常用作数组/对象的浅拷贝、合并。</li>
                </ul>
                <div class="code-block">
                    <span class="comment">// 数组展开</span>
                    <span class="keyword">const</span> <span class="variable">arr1</span> <span class="operator">=</span> <span class="bracket">[</span><span class="number">1</span>, <span class="number">2</span><span class="bracket">]</span>;
                    <span class="keyword">const</span> <span class="variable">arr2</span> <span class="operator">=</span> <span class="bracket">[</span><span class="number">3</span>, <span class="number">4</span><span class="bracket">]</span>;
                    <span class="keyword">const</span> <span class="variable">merged</span> <span class="operator">=</span> <span class="bracket">[</span>...<span class="variable">arr1</span>, ...<span class="variable">arr2</span><span class="bracket">]</span>; <span class="comment">// [1,2,3,4]</span>

                    <span class="comment">// 对象展开 (合并)</span>
                    <span class="keyword">const</span> <span class="variable">obj1</span> <span class="operator">=</span> <span class="bracket">{</span> <span class="variable">a</span>: <span class="number">1</span>, <span class="variable">b</span>: <span class="number">2</span> <span class="bracket">}</span>;
                    <span class="keyword">const</span> <span class="variable">obj2</span> <span class="operator">=</span> <span class="bracket">{</span> ...<span class="variable">obj1</span>, <span class="variable">c</span>: <span class="number">3</span> <span class="bracket">}</span>; <span class="comment">// {a:1, b:2, c:3}</span>

                    <span class="comment">// 剩余参数 (函数参数)</span>
                    <span class="keyword">function</span> <span class="func">sum</span>(...<span class="variable">numbers</span>) <span class="bracket">{</span>
                    <span class="keyword">return</span> <span class="variable">numbers</span>.<span class="func">reduce</span>((<span class="variable">acc</span>, <span class="variable">n</span>) <span class="operator">=></span> <span class="variable">acc</span> <span class="operator">+</span> <span class="variable">n</span>, <span class="number">0</span>);
                    <span class="bracket">}</span>
                    <span class="func">sum</span>(<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>); <span class="comment">// 6</span>
                </div>
            </div>
        </div>

        <!-- 数组高阶方法 -->
        <h3>🛠️ 必知必会:map / filter / reduce</h3>
        <div class="grid-2col">
            <div class="card">
                <h4>🔁 .map() — 转换</h4>
                <p>对每个元素执行操作,<strong>返回新数组</strong>(长度不变)。</p>
                <div class="code-block">
                    <span class="keyword">const</span> <span class="variable">nums</span> <span class="operator">=</span> <span class="bracket">[</span><span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span><span class="bracket">]</span>;
                    <span class="keyword">const</span> <span class="variable">doubled</span> <span class="operator">=</span> <span class="variable">nums</span>.<span class="func">map</span>(<span class="variable">n</span> <span class="operator">=></span> <span class="variable">n</span> <span class="operator">*</span> <span class="number">2</span>);
                    <span class="keyword">console</span>.<span class="func">log</span>(<span class="variable">doubled</span>); <span class="comment">// [2, 4, 6]</span>
                </div>
            </div>
            <div class="card">
                <h4>🔍 .filter() — 筛选</h4>
                <p>返回满足条件的元素组成<strong>新数组</strong>(长度可能变)。</p>
                <div class="code-block">
                    <span class="keyword">const</span> <span class="variable">nums</span> <span class="operator">=</span> <span class="bracket">[</span><span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span><span class="bracket">]</span>;
                    <span class="keyword">const</span> <span class="variable">even</span> <span class="operator">=</span> <span class="variable">nums</span>.<span class="func">filter</span>(<span class="variable">n</span> <span class="operator">=></span> <span class="variable">n</span> <span class="operator">%</span> <span class="number">2</span> <span class="operator">===</span> <span class="number">0</span>);
                    <span class="keyword">console</span>.<span class="func">log</span>(<span class="variable">even</span>); <span class="comment">// [2, 4]</span>
                </div>
            </div>
            <div class="card" style="grid-column: 1 / -1;">
                <h4>🧮 .reduce() — 聚合</h4>
                <p>将数组归约为单个值(累加、累乘、拼接等)。<strong>面试高频</strong>。</p>
                <div class="code-block">
                    <span class="keyword">const</span> <span class="variable">nums</span> <span class="operator">=</span> <span class="bracket">[</span><span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span><span class="bracket">]</span>;
                    <span class="keyword">const</span> <span class="variable">sum</span> <span class="operator">=</span> <span class="variable">nums</span>.<span class="func">reduce</span>((<span class="variable">acc</span>, <span class="variable">cur</span>) <span class="operator">=></span> <span class="variable">acc</span> <span class="operator">+</span> <span class="variable">cur</span>, <span class="number">0</span>);
                    <span class="keyword">console</span>.<span class="func">log</span>(<span class="variable">sum</span>); <span class="comment">// 10</span>

                    <span class="comment">// 进阶:统计字符出现次数</span>
                    <span class="keyword">const</span> <span class="variable">letters</span> <span class="operator">=</span> <span class="bracket">[</span><span class="string">'a'</span>, <span class="string">'b'</span>, <span class="string">'a'</span><span class="bracket">]</span>;
                    <span class="keyword">const</span> <span class="variable">count</span> <span class="operator">=</span> <span class="variable">letters</span>.<span class="func">reduce</span>((<span class="variable">acc</span>, <span class="variable">char</span>) <span class="operator">=></span> <span class="bracket">{</span>
                    <span class="variable">acc</span>[<span class="variable">char</span>] <span class="operator">=</span> (<span class="variable">acc</span>[<span class="variable">char</span>] <span class="operator">||</span> <span class="number">0</span>) <span class="operator">+</span> <span class="number">1</span>;
                    <span class="keyword">return</span> <span class="variable">acc</span>;
                    <span class="bracket">}</span>, <span class="bracket">{}</span>); <span class="comment">// { a: 2, b: 1 }</span>
                </div>
            </div>
        </div>
    </section>

    <!-- ========================================================== -->
    <!-- 第四部分:DOM 操作 & 事件 -->
    <!-- ========================================================== -->
    <section>
        <h2>🖱️ DOM 交互 <span class="badge">选择 · 事件 · 动态内容</span></h2>
        <div class="grid-2col">
            <div class="card">
                <h4>🎯 选择元素</h4>
                <ul>
                    <li><span class="inline-code">document.querySelector()</span>:返回第一个匹配元素。</li>
                    <li><span class="inline-code">document.querySelectorAll()</span>:返回所有匹配元素 (NodeList)。</li>
                    <li>支持 CSS 选择器,非常灵活。</li>
                </ul>
                <div class="code-block">
                    <span class="comment">// 通过类选择器</span>
                    <span class="keyword">const</span> <span class="variable">btn</span> <span class="operator">=</span> <span class="variable">document</span>.<span class="func">querySelector</span>(<span class="string">'.my-button'</span>);
                    <span class="comment">// 通过 ID</span>
                    <span class="keyword">const</span> <span class="variable">header</span> <span class="operator">=</span> <span class="variable">document</span>.<span class="func">querySelector</span>(<span class="string">'#main-header'</span>);
                    <span class="comment">// 所有 li</span>
                    <span class="keyword">const</span> <span class="variable">items</span> <span class="operator">=</span> <span class="variable">document</span>.<span class="func">querySelectorAll</span>(<span class="string">'ul li'</span>);
                </div>
            </div>

            <div class="card">
                <h4>⚡ 事件监听</h4>
                <ul>
                    <li><span class="inline-code">addEventListener</span> 绑定事件,可同时绑定多个。</li>
                    <li>常用事件:<span class="inline-code">click</span>, <span class="inline-code">input</span>, <span class="inline-code">submit</span>, <span class="inline-code">mouseover</span>。</li>
                    <li>事件对象 <span class="inline-code">e</span> 包含目标、坐标等信息。</li>
                </ul>
                <div class="code-block">
                    <span class="keyword">const</span> <span class="variable">btn</span> <span class="operator">=</span> <span class="variable">document</span>.<span class="func">querySelector</span>(<span class="string">'#myBtn'</span>);
                    <span class="variable">btn</span>.<span class="func">addEventListener</span>(<span class="string">'click'</span>, (<span class="variable">e</span>) <span class="operator">=></span> <span class="bracket">{</span>
                    <span class="keyword">console</span>.<span class="func">log</span>(<span class="string">'按钮被点击了!'</span>);
                    <span class="variable">e</span>.<span class="variable">target</span>.<span class="variable">style</span>.<span class="variable">backgroundColor</span> <span class="operator">=</span> <span class="string">'yellow'</span>;
                    <span class="bracket">}</span>);

                    <span class="comment">// 动态创建元素</span>
                    <span class="keyword">const</span> <span class="variable">newDiv</span> <span class="operator">=</span> <span class="variable">document</span>.<span class="func">createElement</span>(<span class="string">'div'</span>);
                    <span class="variable">newDiv</span>.<span class="variable">textContent</span> <span class="operator">=</span> <span class="string">'我是动态添加的'</span>;
                    <span class="variable">document</span>.<span class="variable">body</span>.<span class="func">appendChild</span>(<span class="variable">newDiv</span>);
                </div>
            </div>
        </div>
        <div class="tip">💡 <strong>事件委托</strong>:将事件监听挂在父元素上,利用冒泡机制,适用于动态列表,性能更好。</div>
    </section>

    <!-- ========================================================== -->
    <!-- 第五部分:异步编程 (Promise & Async/Await) -->
    <!-- ========================================================== -->
    <section>
        <h2>⏳ 异步编程 <span class="badge">Promise · async/await</span></h2>
        <div class="grid-2col">
            <div class="card">
                <h4>🤝 Promise 基础</h4>
                <ul>
                    <li>表示一个<strong>异步操作的最终结果</strong>(成功或失败)。</li>
                    <li>状态:<span class="inline-code">pending</span> → <span class="inline-code">fulfilled</span> 或 <span class="inline-code">rejected</span>。</li>
                    <li>链式调用 <span class="inline-code">.then()</span> 和 <span class="inline-code">.catch()</span>。</li>
                </ul>
                <div class="code-block">
                    <span class="keyword">const</span> <span class="variable">fetchData</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="func">Promise</span>((<span class="variable">resolve</span>, <span class="variable">reject</span>) <span class="operator">=></span> <span class="bracket">{</span>
                    <span class="keyword">setTimeout</span>(() <span class="operator">=></span> <span class="bracket">{</span>
                    <span class="keyword">const</span> <span class="variable">success</span> <span class="operator">=</span> <span class="keyword">true</span>;
                    <span class="variable">success</span> <span class="operator">?</span> <span class="func">resolve</span>(<span class="string">'数据加载成功'</span>) <span class="operator">:</span> <span class="func">reject</span>(<span class="string">'出错了'</span>);
                    <span class="bracket">}</span>, <span class="number">1000</span>);
                    <span class="bracket">}</span>);

                    <span class="variable">fetchData</span>
                    .<span class="func">then</span>(<span class="variable">res</span> <span class="operator">=></span> <span class="keyword">console</span>.<span class="func">log</span>(<span class="variable">res</span>))
                    .<span class="func">catch</span>(<span class="variable">err</span> <span class="operator">=></span> <span class="keyword">console</span>.<span class="func">log</span>(<span class="variable">err</span>));
                </div>
            </div>

            <div class="card">
                <h4>🚀 async / await (语法糖)</h4>
                <ul>
                    <li>让异步代码看起来像同步,<strong>更易读</strong>。</li>
                    <li><span class="inline-code">async</span> 函数返回 Promise,<span class="inline-code">await</span> 等待结果。</li>
                    <li>必须用 <span class="inline-code">try...catch</span> 捕获错误。</li>
                </ul>
                <div class="code-block">
                    <span class="comment">// 模拟 API 请求</span>
                    <span class="keyword">async</span> <span class="keyword">function</span> <span class="func">getUser</span>() <span class="bracket">{</span>
                    <span class="keyword">try</span> <span class="bracket">{</span>
                    <span class="keyword">const</span> <span class="variable">response</span> <span class="operator">=</span> <span class="keyword">await</span> <span class="func">fetch</span>(<span class="string">'https://api.example.com/user'</span>);
                    <span class="keyword">const</span> <span class="variable">data</span> <span class="operator">=</span> <span class="keyword">await</span> <span class="variable">response</span>.<span class="func">json</span>();
                    <span class="keyword">console</span>.<span class="func">log</span>(<span class="variable">data</span>);
                    <span class="bracket">}</span> <span class="keyword">catch</span> (<span class="variable">error</span>) <span class="bracket">{</span>
                    <span class="keyword">console</span>.<span class="func">log</span>(<span class="string">'请求失败:'</span>, <span class="variable">error</span>);
                    <span class="bracket">}</span>
                    <span class="bracket">}</span>
                    <span class="func">getUser</span>();
                </div>
                <div class="warning">⚠️ <strong>注意</strong>:<span class="inline-code">await</span> 只能在 <span class="inline-code">async</span> 函数内部使用。</div>
            </div>
        </div>
    </section>

    <!-- ========================================================== -->
    <!-- 第六部分:作用域 & 闭包 (简) -->
    <!-- ========================================================== -->
    <section>
        <h2>🔭 作用域 &amp; 闭包 <span class="badge">理解核心</span></h2>
        <div class="grid-2col">
            <div class="card">
                <h4>📦 作用域链</h4>
                <ul>
                    <li><strong>全局作用域</strong>:在任何地方都可以访问。</li>
                    <li><strong>函数作用域</strong>:<span class="inline-code">var</span> 和传统函数。</li>
                    <li><strong>块级作用域</strong>:<span class="inline-code">let</span> / <span class="inline-code">const</span>。</li>
                    <li>内部函数可以访问外部函数的变量(作用域链)。</li>
                </ul>
                <div class="code-block">
                    <span class="keyword">let</span> <span class="variable">global</span> <span class="operator">=</span> <span class="string">'全局'</span>;
                    <span class="keyword">function</span> <span class="func">outer</span>() <span class="bracket">{</span>
                    <span class="keyword">let</span> <span class="variable">outerVar</span> <span class="operator">=</span> <span class="string">'外部'</span>;
                    <span class="keyword">function</span> <span class="func">inner</span>() <span class="bracket">{</span>
                    <span class="keyword">let</span> <span class="variable">innerVar</span> <span class="operator">=</span> <span class="string">'内部'</span>;
                    <span class="keyword">console</span>.<span class="func">log</span>(<span class="variable">global</span>, <span class="variable">outerVar</span>, <span class="variable">innerVar</span>); <span class="comment">// 都能访问</span>
                    <span class="bracket">}</span>
                    <span class="func">inner</span>();
                    <span class="bracket">}</span>
                    <span class="func">outer</span>();
                </div>
            </div>

            <div class="card">
                <h4>🧊 闭包 (Closure)</h4>
                <ul>
                    <li><strong>定义</strong>:内部函数可以记住并访问其外部函数的变量,即使外部函数已经执行完毕。</li>
                    <li>常用于封装私有变量、柯里化、防抖/节流。</li>
                </ul>
                <div class="code-block">
                    <span class="keyword">function</span> <span class="func">counter</span>() <span class="bracket">{</span>
                    <span class="keyword">let</span> <span class="variable">count</span> <span class="operator">=</span> <span class="number">0</span>;
                    <span class="keyword">return</span> <span class="keyword">function</span>() <span class="bracket">{</span>
                    <span class="variable">count</span><span class="operator">++</span>;
                    <span class="keyword">return</span> <span class="variable">count</span>;
                    <span class="bracket">}</span>;
                    <span class="bracket">}</span>
                    <span class="keyword">const</span> <span class="variable">increment</span> <span class="operator">=</span> <span class="func">counter</span>();
                    <span class="func">increment</span>(); <span class="comment">// 1</span>
                    <span class="func">increment</span>(); <span class="comment">// 2</span>
                    <span class="comment">// count 变量被「闭包」保护,外部无法直接修改</span>
                </div>
            </div>
        </div>
    </section>

    <!-- ========================================================== -->
    <!-- 第七部分:调试 & 最佳实践 -->
    <!-- ========================================================== -->
    <section>
        <h2>🪲 调试 &amp; 好习惯 <span class="badge">工具 · 规范</span></h2>
        <div class="grid-2col">
            <div class="card">
                <h4>🔧 开发者工具</h4>
                <ul>
                    <li><strong>console.log()</strong>:最常用的调试方法。</li>
                    <li><strong>console.table()</strong>:以表格形式展示数组/对象。</li>
                    <li><strong>debugger</strong>:在代码中设置断点。</li>
                    <li>Chrome DevTools 的 Sources 面板:断点调试、查看调用栈。</li>
                </ul>
            </div>
            <div class="card">
                <h4>✅ 编码好习惯</h4>
                <ul>
                    <li>变量/函数命名使用 <span class="inline-code">camelCase</span>(如 <span class="inline-code">getUserData</span>)。</li>
                    <li>使用 <span class="inline-code">===</span> 代替 <span class="inline-code">==</span>(避免隐式类型转换)。</li>
                    <li>尽量使用 <span class="inline-code">const</span>,除非需要重新赋值。</li>
                    <li>使用 <span class="inline-code">try...catch</span> 处理异步错误。</li>
                    <li>写注释解释“为什么”而不是“是什么”。</li>
                </ul>
            </div>
        </div>
        <div class="tip">
            🧠 <strong>总结</strong>:JavaScript 是一门灵活但需要严谨对待的语言。理解作用域、异步和数组方法,能让你从“会用”跨越到“精通”。
        </div>
    </section>

    <!-- 页脚 -->
    <footer class="footer">
        ✦ JavaScript 核心笔记 · 持续积累 ✦<br />
        多练多写,理解原理,写出健壮的代码。
    </footer>

</div>
<!-- end container -->

</body>
</html>

Vue笔记

这是一份为您梳理的 Vue 3 框架核心知识笔记。Vue 3 是当前的主流版本,与 Vue 2 相比,它在性能、开发体验和代码组织上都有了显著的提升。这份笔记将聚焦于 Vue 3 的核心概念与最佳实践,希望能帮助您建立扎实的知识体系。

🌱 一、Vue.js 是什么?

Vue (读音 /vjuː/,类似 view) 是一款用于构建用户界面的 JavaScript 框架。它基于标准 HTML、CSS 和 JavaScript 构建,提供了一套声明式组件化的编程模型,能帮助我们高效地开发界面。

它的核心优势在于数据驱动组件化,其核心库只关注视图层,非常易于上手,并能与第三方库或既有项目整合。

🏗️ 二、创建一个 Vue 应用

每个 Vue 应用都是通过 createApp 函数来创建的。

import { createApp } from 'vue'
import App from './App.vue' // 根组件

const app = createApp(App)
app.mount('#app') // 将应用挂载到 DOM 元素上
  • 应用实例 (app):通过 createApp 返回,用于管理全局资源,如注册组件、指令、插件等。所有全局注册都必须在 app.mount() 之前完成。
  • 根组件 (App.vue):每个应用都需要一个“根组件”,其他组件将作为其子组件,形成一棵组件树
  • 挂载 (app.mount()):将应用渲染到页面指定的 DOM 容器中。

🧩 三、核心概念与基础语法

1. 模板语法

Vue 使用基于 HTML 的模板语法,将组件实例的数据声明式地绑定到 DOM 上。

  • 插值 (文本):使用 {{ }} 语法。
    html <span>{{ message }}</span>
  • 指令 (Directives):带有 v- 前缀的特殊 attribute,用于在 DOM 上应用响应式行为。
    • v-bind:动态绑定一个或多个 attribute,或一个组件 prop 到表达式。简写为 :
      html <img :src="imageUrl" />
    • v-model:在表单 <input><textarea><select> 元素上创建双向数据绑定
      html <input v-model="username" />
    • v-for:基于源数据多次渲染元素或模板块。
      html <li v-for="item in items" :key="item.id">{{ item.name }}</li>
    • v-if / v-else-if / v-else:条件性地渲染一块内容。
      html ¨K12K
    • v-show:通过切换元素的 display CSS 属性来显示/隐藏元素。与 v-if 不同,v-show 不会销毁/重建元素,适用于频繁切换的场景。
    • v-on:绑定事件监听器。简写为 @
      html <button @click="handleClick">点击我</button>

2. 响应式数据

Vue 3 提供了两种主要方式来声明响应式数据。

  • ref():用于定义任何类型的响应式数据。在 JavaScript 中访问或修改其值,需要通过 .value 属性。在模板中会自动“解包”,无需 .valueimport { ref } from 'vue' const count = ref(0) console.log(count.value) // 0 count.value++
  • reactive():用于定义对象类型(如 Object、Array)的响应式数据。可以直接访问其属性,无需 .valueimport { reactive } from 'vue' const state = reactive({ count: 0 }) state.count++ // 直接修改 注意reactive() 有一些限制,比如不能直接重新赋值整个对象(会丢失响应式),解构时也会丢失响应式。因此,在 Vue 3 的实践中,更推荐使用 ref() 并结合 .value 来管理所有状态,这样更统一和可预测。

3. 计算属性 (Computed) 与侦听器 (Watcher)

  • computed():用于声明计算属性,其值依赖于其他响应式数据,并且具有缓存特性,只有依赖项变化时才会重新计算。
    • import { ref, computed } from 'vue'
    • const firstName = ref('张')
    • const lastName = ref('三')
    • const fullName = computed(() => firstName.value + ' ' + lastName.value)
  • watch():用于侦听一个或多个响应式数据源,并在数据变化时执行特定的副作用(如异步请求)。
    • import { ref, watch } from 'vue'
    • const question = ref('')
    • watch(question, (newQuestion, oldQuestion) => {
    • // 当 question 变化时,执行一些操作
    • console.log(`问题从 "${oldQuestion}" 变为 "${newQuestion}"`)
    • })
  • watchEffect():会立即执行传入的函数,并自动追踪其内部所有响应式依赖。当任何依赖发生变化时,该函数会重新运行。
    • import { ref, watchEffect } from 'vue'
    • const count = ref(0)
    • watchEffect(() => {
    • // 立即输出: "count 的值是: 0"
    • console.log(`count 的值是: ${count.value}`)
    • })

🧱 四、组件化开发

组件是 Vue 的核心,它允许我们将 UI 拆分为独立、可复用的部分。

  • 父子组件通信
    • 父 → 子:通过 props 传递数据。
    • 子 → 父:通过 $emit 触发事件。
  • <script setup> 语法糖
    这是 Vue 3 中最推荐的组件编写方式,它让组合式 API 的写法更简洁。
    • <template>
    • <h1>{{ title }}</h1>
    • <button @click="increment">{{ count }}</button>
    • </template>
    • <script setup>
    • import { ref, defineProps, defineEmits } from 'vue' // 定义 props
    • const props = defineProps(['title']) // 定义事件
    • const emit = defineEmits(['update'])
    • const count = ref(0)
    • function increment() {
    • count.value++
    • emit('update', count.value)
    • }
    • </script>

⚙️ 五、组合式 API (Composition API)

这是 Vue 3 最重大的革新,它提供了一种更灵活、更强大的方式来组织和复用组件逻辑。

  • 为什么需要它?
    • 更好的逻辑复用:可以将相关的逻辑(数据、方法、生命周期等)封装到一个独立的组合式函数 (Composables) 中,并在多个组件间轻松复用。
    • 更清晰的代码组织:对于复杂组件,可以按功能(而非选项类型)来组织代码,极大提升了可读性和可维护性。
    • 更佳的 TypeScript 支持:组合式 API 基于函数,天然具有优秀的类型推断能力。
  • 组合式函数 (Composables) 示例
    • 定义组合式函数:
    • // 在useCounter.js文件中
    • import { ref } from 'vue'
    • /**
    • 创建一个包含计数状态及其操作方法的组合式函数
    • @param {number} initialValue - 初始计数值,默认为 0
    • @returns {Object} 包含 count(ref)、increment、decrement 的对象
      */
      export function useCounter(initialValue = 0) {
      // 响应式状态
      const count = ref(initialValue) // 状态操作函数
      const increment = () => {
      count.value++
      }
    • const decrement = () => {
      count.value--
      } // 将状态和操作暴露出去
      return {
      count,
      increment,
      decrement
      }
      }
    • 在vue组件中使用:
    • //CounterComponent.vue
    • <template>
    • <div>
    • <p>当前计数:{{ count }}</p>
    • <button @click="increment">增加</button>
    • <button @click="decrement">减少</button>
    • </div>
    • </template>
    • <script setup>
    • import { useCounter } from './useCounter.js'
    • // 使用组合式函数,传入初始值 10
    • const { count, increment, decrement } = useCounter(10) </script>

♻️ 六、生命周期钩子 (Lifecycle Hooks)

每个 Vue 组件实例在创建时都会经历一系列初始化步骤——例如,设置数据侦听、编译模板、挂载实例到 DOM、以及在数据变化时更新 DOM 等。在这个过程中,Vue 提供了生命周期钩子,让我们能在特定阶段添加自己的代码。

在组合式 API 中,生命周期钩子以 on 为前缀,并且必须在 setup() 中同步调用

选项式 API (Vue 2 / 3)组合式 API (Vue 3)描述
beforeCreate直接写在 setup()组件实例被创建之初,数据观测和事件配置之前。
created直接写在 setup()组件实例创建完成,属性已绑定,但 DOM 还未生成。
beforeMountonBeforeMount在挂载开始之前被调用。
mountedonMounted组件被挂载到 DOM 上之后调用,常用于发起异步请求或操作 DOM。
beforeUpdateonBeforeUpdate数据更新时调用,发生在虚拟 DOM 打补丁之前。
updatedonUpdated由于数据更改导致的虚拟 DOM 重新渲染和打补丁之后调用。
beforeDestroy (Vue 2)onBeforeUnmount实例销毁之前调用。
destroyed (Vue 2)onUnmounted实例销毁后调用。

🧭 七、生态与工程化

  • 路由 (Vue Router):官方路由管理器,用于构建单页应用 (SPA)。
  • 状态管理 (Pinia):Vue 官方推荐的新一代轻量级状态管理库,完美支持组合式 API。
  • 构建工具 (Vite):一个由 Vue 作者开发的现代前端构建工具,以其极快的启动和热更新速度著称,是 Vue 3 项目的官方推荐。
唯有极致沉淀,才能造就辉煌。
最后更新于 2026-08-01