<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>wjnba的博客</title>
  
  <subtitle>君子以坦荡立于世间，必将步步生花，一路繁华</subtitle>
  <link href="https://www.wjnba.top/atom.xml" rel="self"/>
  
  <link href="https://www.wjnba.top/"/>
  <updated>2026-03-05T08:43:49.768Z</updated>
  <id>https://www.wjnba.top/</id>
  
  <author>
    <name>wjnba</name>
    
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>
  
  <entry>
    <title>CSS 命名规范 - BEM</title>
    <link href="https://www.wjnba.top/articles/202603057adca3656412.html"/>
    <id>https://www.wjnba.top/articles/202603057adca3656412.html</id>
    <published>2026-03-05T08:24:54.000Z</published>
    <updated>2026-03-05T08:43:49.768Z</updated>
    
    <content type="html"><![CDATA[<h2 id="一、BEM基础介绍"><a href="#一、BEM基础介绍" class="headerlink" title="一、BEM基础介绍"></a>一、BEM基础介绍</h2><ol><li><p><strong>定义</strong>：BEM（Block Element Modifier）是由Yandex团队提出的前端CSS类名命名方法论，通过<strong>块、元素、修饰符</strong>三部分构建清晰的组件结构，是现代前端开发中广泛采用的CSS模块化方案。</p></li><li><p><strong>核心价值</strong>：提升CSS代码可维护性、避免样式冲突、支持组件复用，尤其适配中大型前端项目。</p></li><li><p><strong>基础标识</strong>：双下划线<code>__</code>连接块与元素，双连字符<code>--</code>表示修饰符，示例：<code>.menu__item--active</code>。</p></li></ol><h2 id="二、BEM核心概念"><a href="#二、BEM核心概念" class="headerlink" title="二、BEM核心概念"></a>二、BEM核心概念</h2><div class="table-container"><table><thead><tr><th>组成部分</th><th>描述</th><th>示例</th><th>核心作用</th></tr></thead><tbody><tr><td>Block（块）</td><td>独立且有意义的组件</td><td><code>.header</code>、<code>.menu</code>、<code>.card</code></td><td>表示可独立复用的基础组件</td></tr><tr><td>Element（元素）</td><td>块的组成部分</td><td><code>.menu__item</code>、<code>.card__title</code></td><td>块的从属部分，无法独立存在</td></tr><tr><td>Modifier（修饰符）</td><td>块/元素的状态/变体</td><td><code>.menu--vertical</code>、<code>.card__button--disabled</code></td><td>表示组件的不同状态或样式变体</td></tr></tbody></table></div><h2 id="三、命名语法规则"><a href="#三、命名语法规则" class="headerlink" title="三、命名语法规则"></a>三、命名语法规则</h2><h3 id="1-基本语法结构"><a href="#1-基本语法结构" class="headerlink" title="1. 基本语法结构"></a>1. 基本语法结构</h3><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment">/* 块 */</span></span><br><span class="line"><span class="selector-class">.block</span> &#123;&#125;</span><br><span class="line"><span class="comment">/* 块-元素 */</span></span><br><span class="line"><span class="selector-class">.block__element</span> &#123;&#125;</span><br><span class="line"><span class="comment">/* 块-修饰符 */</span></span><br><span class="line"><span class="selector-class">.block--modifier</span> &#123;&#125;</span><br><span class="line"><span class="comment">/* 块-元素-修饰符 */</span></span><br><span class="line"><span class="selector-class">.block__element--modifier</span> &#123;&#125;</span><br></pre></td></tr></table></figure><h3 id="2-分隔符说明"><a href="#2-分隔符说明" class="headerlink" title="2. 分隔符说明"></a>2. 分隔符说明</h3><ul><li><p><code>__</code>（双下划线）：仅用于连接<strong>块</strong>和<strong>元素</strong>，无其他用途；</p></li><li><p><code>--</code>（双连字符）：仅用于连接<strong>块/元素</strong>和<strong>修饰符</strong>；</p></li><li><p><code>-</code>（单连字符）：可选，用于多单词名称的连接，示例：<code>.search-form</code>、<code>.nav__submenu</code>。</p></li></ul><h2 id="四、BEM命名核心原则"><a href="#四、BEM命名核心原则" class="headerlink" title="四、BEM命名核心原则"></a>四、BEM命名核心原则</h2><h3 id="1-块（Block）的独立性"><a href="#1-块（Block）的独立性" class="headerlink" title="1. 块（Block）的独立性"></a>1. 块（Block）的独立性</h3><ul><li><p>可在页面任意位置复用，不依赖其他元素/块；</p></li><li><p>块本身不设置外边距（margin），由其容器控制位置。</p></li></ul><h3 id="2-元素（Element）的从属性"><a href="#2-元素（Element）的从属性" class="headerlink" title="2. 元素（Element）的从属性"></a>2. 元素（Element）的从属性</h3><ul><li><p>元素名称必须归属某个块，格式固定为<code>block__element</code>；</p></li><li><p>同一块内的不同元素可嵌套，无需考虑嵌套层级。</p></li></ul><h3 id="3-修饰符（Modifier）的可选性"><a href="#3-修饰符（Modifier）的可选性" class="headerlink" title="3. 修饰符（Modifier）的可选性"></a>3. 修饰符（Modifier）的可选性</h3><ul><li><p>修饰符不能单独使用，必须与块/元素类名配合；</p></li><li><p>同一元素可添加多个修饰符，实现多状态组合；</p></li><li><p>格式为<code>block--modifier</code>（块修饰）或<code>block__element--modifier</code>（元素修饰）。</p></li></ul><h2 id="五、完整代码示例"><a href="#五、完整代码示例" class="headerlink" title="五、完整代码示例"></a>五、完整代码示例</h2><h3 id="1-HTML结构"><a href="#1-HTML结构" class="headerlink" title="1. HTML结构"></a>1. HTML结构</h3><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment">&lt;!-- 搜索组件（块） --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">form</span> <span class="attr">class</span>=<span class="string">&quot;search-form&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">input</span> <span class="attr">class</span>=<span class="string">&quot;search-form__input&quot;</span> <span class="attr">type</span>=<span class="string">&quot;text&quot;</span> <span class="attr">placeholder</span>=<span class="string">&quot;搜索...&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">button</span> <span class="attr">class</span>=<span class="string">&quot;search-form__button search-form__button--primary&quot;</span> <span class="attr">type</span>=<span class="string">&quot;submit&quot;</span>&gt;</span>搜索<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">button</span> <span class="attr">class</span>=<span class="string">&quot;search-form__button search-form__button--secondary&quot;</span> <span class="attr">type</span>=<span class="string">&quot;reset&quot;</span>&gt;</span>重置<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">form</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- 卡片组件（块+修饰符） --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;card card--featured&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">img</span> <span class="attr">class</span>=<span class="string">&quot;card__image&quot;</span> <span class="attr">src</span>=<span class="string">&quot;image.jpg&quot;</span> <span class="attr">alt</span>=<span class="string">&quot;示例&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">h3</span> <span class="attr">class</span>=<span class="string">&quot;card__title&quot;</span>&gt;</span>特荐产品<span class="tag">&lt;/<span class="name">h3</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">p</span> <span class="attr">class</span>=<span class="string">&quot;card__description card__description--truncated&quot;</span>&gt;</span>这是一个很长的描述文本，会被截断显示...<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">button</span> <span class="attr">class</span>=<span class="string">&quot;card__button&quot;</span>&gt;</span>了解更多<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure><h3 id="2-对应CSS样式"><a href="#2-对应CSS样式" class="headerlink" title="2. 对应CSS样式"></a>2. 对应CSS样式</h3><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment">/* 搜索表单块 */</span></span><br><span class="line"><span class="selector-class">.search-form</span> &#123; <span class="attribute">display</span>: flex; gap: <span class="number">10px</span>; <span class="attribute">padding</span>: <span class="number">20px</span>; <span class="attribute">background</span>: <span class="number">#f5f5f5</span>; &#125;</span><br><span class="line"><span class="comment">/* 搜索表单元素 */</span></span><br><span class="line"><span class="selector-class">.search-form__input</span> &#123; <span class="attribute">flex</span>: <span class="number">1</span>; <span class="attribute">padding</span>: <span class="number">10px</span>; <span class="attribute">border</span>: <span class="number">1px</span> solid <span class="number">#ddd</span>; <span class="attribute">border-radius</span>: <span class="number">4px</span>; &#125;</span><br><span class="line"><span class="selector-class">.search-form__button</span> &#123; <span class="attribute">padding</span>: <span class="number">10px</span> <span class="number">20px</span>; <span class="attribute">border</span>: none; <span class="attribute">border-radius</span>: <span class="number">4px</span>; <span class="attribute">cursor</span>: pointer; &#125;</span><br><span class="line"><span class="comment">/* 搜索表单元素修饰符 */</span></span><br><span class="line"><span class="selector-class">.search-form__button--primary</span> &#123; <span class="attribute">background-color</span>: <span class="number">#007bff</span>; <span class="attribute">color</span>: white; &#125;</span><br><span class="line"><span class="selector-class">.search-form__button--secondary</span> &#123; <span class="attribute">background-color</span>: <span class="number">#6c757d</span>; <span class="attribute">color</span>: white; &#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/* 卡片块 */</span></span><br><span class="line"><span class="selector-class">.card</span> &#123; <span class="attribute">border</span>: <span class="number">1px</span> solid <span class="number">#e0e0e0</span>; <span class="attribute">border-radius</span>: <span class="number">8px</span>; <span class="attribute">padding</span>: <span class="number">20px</span>; <span class="attribute">max-width</span>: <span class="number">300px</span>; &#125;</span><br><span class="line"><span class="comment">/* 卡片块修饰符 */</span></span><br><span class="line"><span class="selector-class">.card--featured</span> &#123; <span class="attribute">border-color</span>: <span class="number">#007bff</span>; <span class="attribute">box-shadow</span>: <span class="number">0</span> <span class="number">4px</span> <span class="number">12px</span> <span class="built_in">rgba</span>(<span class="number">0</span>, <span class="number">123</span>, <span class="number">255</span>, <span class="number">0.2</span>); &#125;</span><br><span class="line"><span class="comment">/* 卡片元素 */</span></span><br><span class="line"><span class="selector-class">.card__title</span> &#123; <span class="attribute">font-size</span>: <span class="number">1.5rem</span>; <span class="attribute">margin-bottom</span>: <span class="number">10px</span>; <span class="attribute">color</span>: <span class="number">#333</span>; &#125;</span><br><span class="line"><span class="selector-class">.card__description</span> &#123; <span class="attribute">color</span>: <span class="number">#666</span>; <span class="attribute">line-height</span>: <span class="number">1.5</span>; &#125;</span><br><span class="line"><span class="selector-class">.card__button</span> &#123; <span class="attribute">margin-top</span>: <span class="number">15px</span>; <span class="attribute">padding</span>: <span class="number">8px</span> <span class="number">16px</span>; <span class="attribute">background-color</span>: <span class="number">#28a745</span>; <span class="attribute">color</span>: white; <span class="attribute">border</span>: none; <span class="attribute">border-radius</span>: <span class="number">4px</span>; &#125;</span><br><span class="line"><span class="comment">/* 卡片元素修饰符 */</span></span><br><span class="line"><span class="selector-class">.card__description--truncated</span> &#123; <span class="attribute">display</span>: -webkit-box; -webkit-line-clamp: <span class="number">3</span>; -webkit-box-orient: vertical; <span class="attribute">overflow</span>: hidden; &#125;</span><br></pre></td></tr></table></figure><h2 id="六、实际项目应用场景"><a href="#六、实际项目应用场景" class="headerlink" title="六、实际项目应用场景"></a>六、实际项目应用场景</h2><h3 id="1-导航菜单"><a href="#1-导航菜单" class="headerlink" title="1. 导航菜单"></a>1. 导航菜单</h3><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">nav</span> <span class="attr">class</span>=<span class="string">&quot;nav&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">ul</span> <span class="attr">class</span>=<span class="string">&quot;nav__list&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">li</span> <span class="attr">class</span>=<span class="string">&quot;nav__item&quot;</span>&gt;</span><span class="tag">&lt;<span class="name">a</span> <span class="attr">class</span>=<span class="string">&quot;nav__link nav__link--active&quot;</span> <span class="attr">href</span>=<span class="string">&quot;#&quot;</span>&gt;</span>首页<span class="tag">&lt;/<span class="name">a</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">li</span> <span class="attr">class</span>=<span class="string">&quot;nav__item nav__item--dropdown&quot;</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">a</span> <span class="attr">class</span>=<span class="string">&quot;nav__link&quot;</span> <span class="attr">href</span>=<span class="string">&quot;#&quot;</span>&gt;</span>服务<span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">ul</span> <span class="attr">class</span>=<span class="string">&quot;nav__submenu&quot;</span>&gt;</span><span class="tag">&lt;<span class="name">li</span> <span class="attr">class</span>=<span class="string">&quot;nav__subitem&quot;</span>&gt;</span><span class="tag">&lt;<span class="name">a</span> <span class="attr">class</span>=<span class="string">&quot;nav__sublink&quot;</span> <span class="attr">href</span>=<span class="string">&quot;#&quot;</span>&gt;</span>设计<span class="tag">&lt;/<span class="name">a</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span><span class="tag">&lt;/<span class="name">ul</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">ul</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">nav</span>&gt;</span></span><br></pre></td></tr></table></figure><h3 id="2-表单控件（带错误状态）"><a href="#2-表单控件（带错误状态）" class="headerlink" title="2. 表单控件（带错误状态）"></a>2. 表单控件（带错误状态）</h3><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;form-field&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">label</span> <span class="attr">class</span>=<span class="string">&quot;form-field__label&quot;</span> <span class="attr">for</span>=<span class="string">&quot;email&quot;</span>&gt;</span>邮箱<span class="tag">&lt;/<span class="name">label</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">input</span> <span class="attr">class</span>=<span class="string">&quot;form-field__input form-field__input--error&quot;</span> <span class="attr">id</span>=<span class="string">&quot;email&quot;</span> <span class="attr">type</span>=<span class="string">&quot;email&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;form-field__error-message&quot;</span>&gt;</span>请输入有效的邮箱地址<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure><h3 id="3-响应式修饰符"><a href="#3-响应式修饰符" class="headerlink" title="3. 响应式修饰符"></a>3. 响应式修饰符</h3><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment">/* 移动端隐藏，平板及以上显示 */</span></span><br><span class="line"><span class="selector-class">.menu__item--hidden-mobile</span> &#123; <span class="attribute">display</span>: none; &#125;</span><br><span class="line"><span class="keyword">@media</span> (<span class="attribute">min-width</span>: <span class="number">768px</span>) &#123;</span><br><span class="line">  <span class="selector-class">.menu__item--hidden-mobile</span> &#123; <span class="attribute">display</span>: block; &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="七、BEM的常见变体"><a href="#七、BEM的常见变体" class="headerlink" title="七、BEM的常见变体"></a>七、BEM的常见变体</h2><h3 id="1-BEM-Sass-SCSS（推荐）"><a href="#1-BEM-Sass-SCSS（推荐）" class="headerlink" title="1. BEM + Sass/SCSS（推荐）"></a>1. BEM + Sass/SCSS（推荐）</h3><p>利用Sass嵌套语法简化书写，通过<code>&amp;</code>引用父选择器，保持代码层级清晰：</p><figure class="highlight scss"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="selector-class">.menu</span> &#123;</span><br><span class="line">  <span class="attribute">display</span>: flex;</span><br><span class="line">  &amp;__list &#123; <span class="attribute">list-style</span>: none; &#125;</span><br><span class="line">  &amp;__item &#123;</span><br><span class="line">    <span class="attribute">margin-right</span>: <span class="number">20px</span>;</span><br><span class="line">    &amp;--active &#123; <span class="attribute">font-weight</span>: bold; &#125;</span><br><span class="line">  &#125;</span><br><span class="line">  &amp;__link &#123;</span><br><span class="line">    <span class="attribute">color</span>: <span class="number">#333</span>;</span><br><span class="line">    &amp;<span class="selector-pseudo">:hover</span> &#123; <span class="attribute">color</span>: <span class="number">#007bff</span>; &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="2-命名空间变体"><a href="#2-命名空间变体" class="headerlink" title="2. 命名空间变体"></a>2. 命名空间变体</h3><p>为类名添加前缀，区分组件类型，提升可读性：</p><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="selector-class">.c-card</span> &#123;&#125;        <span class="comment">/* c-：通用组件（Component） */</span></span><br><span class="line"><span class="selector-class">.l-header</span> &#123;&#125;      <span class="comment">/* l-：布局组件（Layout） */</span></span><br><span class="line"><span class="selector-class">.u-text-center</span> &#123;&#125; <span class="comment">/* u-：工具类（Utility） */</span></span><br><span class="line"><span class="selector-class">.js-modal</span> &#123;&#125;      <span class="comment">/* js-：JavaScript钩子（仅用于JS操作，不写样式） */</span></span><br></pre></td></tr></table></figure><h3 id="3-更严格的BEM"><a href="#3-更严格的BEM" class="headerlink" title="3. 更严格的BEM"></a>3. 更严格的BEM</h3><p>避免元素嵌套式命名，采用扁平结构，防止类名过长：</p><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment">/* 推荐 */</span></span><br><span class="line"><span class="selector-class">.block__element2-child</span> &#123;&#125;</span><br><span class="line"><span class="comment">/* 禁止 */</span></span><br><span class="line"><span class="selector-class">.block__element2__child</span> &#123;&#125;</span><br></pre></td></tr></table></figure><h2 id="八、BEM的优缺点"><a href="#八、BEM的优缺点" class="headerlink" title="八、BEM的优缺点"></a>八、BEM的优缺点</h2><h3 id="优点"><a href="#优点" class="headerlink" title="优点"></a>优点</h3><ol><li><p>结构清晰：直观体现HTML与CSS的对应关系，易读易维护；</p></li><li><p>避免冲突：每个类名都有独立命名空间，解决样式污染问题；</p></li><li><p>减少嵌套：仅需一层选择器，降低CSS选择器特异性，提升渲染性能；</p></li><li><p>便于协作：统一命名规范，减少团队沟通成本；</p></li><li><p>模块化：组件可独立开发、测试和复用，适配工程化开发。</p></li></ol><h3 id="缺点"><a href="#缺点" class="headerlink" title="缺点"></a>缺点</h3><ul><li>类名长度偏长，纯手写时稍显繁琐（可通过Sass/PostCSS工具优化）。</li></ul><h2 id="九、使用注意事项"><a href="#九、使用注意事项" class="headerlink" title="九、使用注意事项"></a>九、使用注意事项</h2><ol><li><p><strong>避免过度使用</strong>：简单项目/小组件无需完整BEM，避免冗余；</p></li><li><p><strong>坚持语义化命名</strong>：根据功能命名，而非样式，示例：用<code>.box__status--error</code>代替<code>.box__red</code>；</p></li><li><p><strong>控制类名长度</strong>：若类名过长，需重新设计组件结构，拆分独立块；</p></li><li><p><strong>兼容其他方案</strong>：可与CSS-in-JS、Bootstrap等框架结合使用，用于自定义组件；</p></li><li><p><strong>修饰符必配合基础类</strong>：不可单独写<code>.button--primary</code>，需与<code>.button</code>配合。</p></li></ol><h2 id="十、BEM与其他CSS命名方法对比"><a href="#十、BEM与其他CSS命名方法对比" class="headerlink" title="十、BEM与其他CSS命名方法对比"></a>十、BEM与其他CSS命名方法对比</h2><div class="table-container"><table><thead><tr><th>方法</th><th>核心理念</th><th>优点</th><th>缺点</th></tr></thead><tbody><tr><td>BEM</td><td>块-元素-修饰符</td><td>结构清晰，避免冲突，易协作</td><td>类名较长</td></tr><tr><td>OOCSS</td><td>对象化CSS</td><td>高度复用，分离结构与皮肤</td><td>需抽象思维，对初学者不友好</td></tr><tr><td>SMACSS</td><td>可扩展模块化架构</td><td>分类清晰，适配大型项目</td><td>规则较多，配置繁琐</td></tr><tr><td>ITCSS</td><td>倒三角CSS</td><td>层次分明，精准控制选择器特异性</td><td>学习曲线较陡</td></tr><tr><td>Atomic CSS</td><td>原子化CSS</td><td>极致复用，样式文件体积小</td><td>类名无语义，可读性差</td></tr></tbody></table></div><h2 id="十一、学习与实践建议"><a href="#十一、学习与实践建议" class="headerlink" title="十一、学习与实践建议"></a>十一、学习与实践建议</h2><ol><li><p><strong>从简入手</strong>：先在单个小组件（如按钮、卡片）上实践，再逐步推广到整个项目；</p></li><li><p><strong>团队统一规范</strong>：约定分隔符、命名空间、多单词连接方式，保持项目内一致性；</p></li><li><p><strong>结合工具</strong>：使用Sass/SCSS嵌套、PostCSS插件简化BEM书写，提升效率；</p></li><li><p><strong>文档化</strong>：为复杂组件编写BEM结构文档，方便团队查阅和维护；</p></li><li><p><strong>灵活适配</strong>：根据项目规模调整BEM严格程度，无需生搬硬套规则。 </p></li></ol>]]></content>
    
    
      
      
    <summary type="html">&lt;h2 id=&quot;一、BEM基础介绍&quot;&gt;&lt;a href=&quot;#一、BEM基础介绍&quot; class=&quot;headerlink&quot; title=&quot;一、BEM基础介绍&quot;&gt;&lt;/a&gt;一、BEM基础介绍&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;定义&lt;/strong&gt;：BEM（Block Ele</summary>
      
    
    
    
    <category term="代码规范" scheme="https://www.wjnba.top/categories/%E4%BB%A3%E7%A0%81%E8%A7%84%E8%8C%83/"/>
    
    
    <category term="css" scheme="https://www.wjnba.top/tags/css/"/>
    
  </entry>
  
  <entry>
    <title>关于this的理解</title>
    <link href="https://www.wjnba.top/articles/202507040a0f7abfb535.html"/>
    <id>https://www.wjnba.top/articles/202507040a0f7abfb535.html</id>
    <published>2025-07-04T07:00:30.000Z</published>
    <updated>2025-12-15T03:40:53.441Z</updated>
    
    <content type="html"><![CDATA[<h2 id="什么是this？"><a href="#什么是this？" class="headerlink" title="什么是this？"></a>什么是this？</h2><p><strong>定义：调用函数时，call后面的第一个值</strong></p><h2 id="如何找到this？"><a href="#如何找到this？" class="headerlink" title="如何找到this？"></a>如何找到this？</h2><p>由定义可知，this就是call后面的第一个值，只要确定了call后面的值，即可找到this。换句话说，只需要<strong>把函数调用改成带有call的调用即可</strong></p><h2 id="函数调用"><a href="#函数调用" class="headerlink" title="函数调用"></a>函数调用</h2><p>JS（ES5）里面有三种函数调用形式：</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">func(p1, p2) </span><br><span class="line">obj.child.method(p1, p2)</span><br><span class="line">func.call(context, p1, p2)</span><br></pre></td></tr></table></figure><p>一般，初学者都知道前两种形式，而且认为前两种形式「优于」第三种形式。</p><p>从看到这篇文章起，你一定要记住，第三种调用形式，才是正常调用形式：</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">func.call(context, p1, p2)</span><br></pre></td></tr></table></figure><p>其他两种都是语法糖，可以等价地变为 call 形式：</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">func(p1, p2) 等价于</span><br><span class="line">func.call(<span class="literal">undefined</span>, p1, p2)</span><br><span class="line"></span><br><span class="line">obj.child.method(p1, p2) 等价于</span><br><span class="line">obj.child.method.call(obj.child, p1, p2)</span><br></pre></td></tr></table></figure><p>请记下来。（我们称此代码为「转换代码」，方便下文引用）</p><p>至此我们的函数调用只有一种形式：</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">func.call(context, p1, p2)</span><br></pre></td></tr></table></figure><p>举个例子吧</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> obj = &#123;</span><br><span class="line">    <span class="attr">foo</span>: <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="built_in">this</span>)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> bar = obj.foo</span><br><span class="line">obj.foo() <span class="comment">// 打印出的 this 是 obj</span></span><br><span class="line">bar() <span class="comment">// 打印出的 this 是 window</span></span><br></pre></td></tr></table></figure><p>可以理解为</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">obj.foo()</span><br><span class="line"><span class="comment">//等价于</span></span><br><span class="line">obj.foo.call(obj)</span><br><span class="line"><span class="comment">//因此this是obj</span></span><br><span class="line"></span><br><span class="line">bar()</span><br><span class="line"><span class="comment">//等价于</span></span><br><span class="line">bar.call(<span class="literal">undefined</span>)</span><br><span class="line"><span class="comment">//因此this是window</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//当传入的上下文是null或undefined时，浏览器默认this就是window，严格状态下是undefined</span></span><br></pre></td></tr></table></figure><h2 id="箭头函数"><a href="#箭头函数" class="headerlink" title="箭头函数"></a>箭头函数</h2><p>箭头函数里并没有 this，如果你在箭头函数里看到 this，你直接把它当作箭头函数外面的 this 即可。外面的 this 是什么，箭头函数里面的 this 就还是什么，因为箭头函数本身不支持 this。</p><p>有人说「箭头函数里面的 this 指向箭头函数外面的 this」，<strong>这很傻</strong>，因为箭头函数内外 this 就是同一个东西，并不存在什么指向不指向。</p><p><strong>贴两个精髓文章</strong></p><p><a href="https://mp.weixin.qq.com/s?__biz=MjM5MDA2MTI1MA==&amp;mid=2649110199&amp;idx=2&amp;sn=253649dc5f721e055979f1b9c0976cad&amp;chksm=be58111a892f980c1de5c817fe170160cd2728ba40ef8925606a3af2595b3a6b1554a9451cc5&amp;scene=27">一文搞懂 this、apply、call、bind</a></p><p><a href="https://www.cnblogs.com/BUBU-Sourire/p/11299447.html">关于this的理解</a></p>]]></content>
    
    
      
      
    <summary type="html">&lt;h2 id=&quot;什么是this？&quot;&gt;&lt;a href=&quot;#什么是this？&quot; class=&quot;headerlink&quot; title=&quot;什么是this？&quot;&gt;&lt;/a&gt;什么是this？&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;定义：调用函数时，call后面的第一个值&lt;/strong&gt;&lt;/p&gt;
&lt;h2 </summary>
      
    
    
    
    <category term="深入浅出js" scheme="https://www.wjnba.top/categories/%E6%B7%B1%E5%85%A5%E6%B5%85%E5%87%BAjs/"/>
    
    
    <category term="javascript" scheme="https://www.wjnba.top/tags/javascript/"/>
    
  </entry>
  
  <entry>
    <title>Sourcetree GIt工作流使用及分支开发模式</title>
    <link href="https://www.wjnba.top/articles/20241022bb4ed2208a4c.html"/>
    <id>https://www.wjnba.top/articles/20241022bb4ed2208a4c.html</id>
    <published>2024-10-22T08:36:27.000Z</published>
    <updated>2025-12-15T03:40:53.435Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://pic.wjnba.top/img/202410/20241022163858.webp" alt="image-20241022163848446"></p><h2 id="一般的企业级开发分支共有5种类型"><a href="#一般的企业级开发分支共有5种类型" class="headerlink" title="一般的企业级开发分支共有5种类型"></a>一般的企业级开发分支共有5种类型</h2><ol><li><code>master</code>，最终发布版本，整个项目中有且只有一个。</li><li><code>develop</code>，项目的开发分支，原则上项目中有且只有一个。</li><li><code>feature</code>，功能分支，用于开发一个新的功能。</li><li><code>release</code>，预发布版本，介于<code>develop</code>和<code>master</code>之间的一个版本，用于测试。</li><li><code>hotfix</code>，修复补丁，用于修复<code>master</code>上的<code>bug</code>，直接作用于<code>master</code>。</li></ol><h2 id="SourceTree一般开发模式："><a href="#SourceTree一般开发模式：" class="headerlink" title="SourceTree一般开发模式："></a>SourceTree一般开发模式：</h2><h4 id="1、开发任务都是在develop分支上完成的，当开发中需要增加一个新的功能时，可新建feature分支，用于增加新功能，并且不影响开发中的develop源码，当新功能增加完成后，完成feature分支，将新功能合并到develop中，更新develop上的代码。"><a href="#1、开发任务都是在develop分支上完成的，当开发中需要增加一个新的功能时，可新建feature分支，用于增加新功能，并且不影响开发中的develop源码，当新功能增加完成后，完成feature分支，将新功能合并到develop中，更新develop上的代码。" class="headerlink" title="1、开发任务都是在develop分支上完成的，当开发中需要增加一个新的功能时，可新建feature分支，用于增加新功能，并且不影响开发中的develop源码，当新功能增加完成后，完成feature分支，将新功能合并到develop中，更新develop上的代码。"></a>1、开发任务都是在<code>develop</code>分支上完成的，当开发中需要增加一个新的功能时，可新建<code>feature</code>分支，用于增加新功能，并且不影响开发中的<code>develop</code>源码，当新功能增加完成后，完成<code>feature</code>分支，将新功能合并到<code>develop</code>中，更新<code>develop</code>上的代码。</h4><p><strong>操作：</strong></p><p>①分支选择<code>develop</code>，点击Git工作流，选择“建立新的功能”，以功能命名分支，并把生成的分支推到远程仓库，如下图：</p><p><img src="https://pic.wjnba.top/img/202410/20241023104051.webp" alt="image-20241023093010382"></p><p><img src="https://pic.wjnba.top/img/202410/20241023104056.webp" alt="image-20241023093120971"></p><p>②完成功能开发后，将当前分支指向该分支（如上图“首页”分支），点击“Git工作流”，选择“完成功能”，将新功能合并到<code>develop</code>中，更新<code>develop</code>上的代码，如下图：</p><p><img src="https://pic.wjnba.top/img/202410/20241023104103.webp" alt="image-20241023093726320"  /></p><p><img src="https://pic.wjnba.top/img/202410/20241023104111.webp" alt="image-20241023093852172"></p><h4 id="2、当开发到一定阶段，可以发布测试版本时，可以从develop分支，建立release分支。"><a href="#2、当开发到一定阶段，可以发布测试版本时，可以从develop分支，建立release分支。" class="headerlink" title="2、当开发到一定阶段，可以发布测试版本时，可以从develop分支，建立release分支。"></a>2、当开发到一定阶段，可以发布测试版本时，可以从<code>develop</code>分支，建立<code>release</code>分支。</h4><p><strong>操作：</strong></p><p>①点击“Git工作流”，选择”建立新的发布版本“，如下图：</p><p><img src="https://pic.wjnba.top/img/202410/20241023104117.webp" alt="image-20241023095559651"></p><p>②输入发布版本名，可以用日期命名，如下图：</p><p><img src="https://pic.wjnba.top/img/202410/20241023104121.webp" alt="image-20241023095835174"></p><h4 id="3、如果在测试过程中发现问题，直接在release（上图20241023）上进行修改，修改完成后进行提交。"><a href="#3、如果在测试过程中发现问题，直接在release（上图20241023）上进行修改，修改完成后进行提交。" class="headerlink" title="3、如果在测试过程中发现问题，直接在release（上图20241023）上进行修改，修改完成后进行提交。"></a>3、如果在测试过程中发现问题，直接在<code>release</code>（上图20241023）上进行修改，修改完成后进行提交。</h4><h4 id="4、对release（上图20241023）分支进行修改后，测试通过，完成发布版本，走完新功能开发流程。"><a href="#4、对release（上图20241023）分支进行修改后，测试通过，完成发布版本，走完新功能开发流程。" class="headerlink" title="4、对release（上图20241023）分支进行修改后，测试通过，完成发布版本，走完新功能开发流程。"></a>4、对<code>release</code>（上图20241023）分支进行修改后，测试通过，完成发布版本，走完新功能开发流程。</h4><p><strong>操作：</strong></p><p>①在当前分支指向该分支下，点击“Git工作流”，选择“完成发布版本”，然后可以在预览中可以看到，该分支向develop和master分别合并，点击确定，如下图：</p><p><img src="https://pic.wjnba.top/img/202410/20241023104126.webp" alt="image-20241023100457252"></p><p><img src="https://pic.wjnba.top/img/202410/20241023104131.webp" alt="image-20241023100656610"></p><h4 id="5、当新功能测试通过后，可以进行正式版本的发布。如下图："><a href="#5、当新功能测试通过后，可以进行正式版本的发布。如下图：" class="headerlink" title="5、当新功能测试通过后，可以进行正式版本的发布。如下图："></a>5、当新功能测试通过后，可以进行正式版本的发布。如下图：</h4><p><img src="https://pic.wjnba.top/img/202410/20241023104135.webp" alt="image-20241023103317697"></p><p><img src="https://pic.wjnba.top/img/202410/20241023104141.webp" alt="image-20241023103506313"></p><h4 id="6、正式版本发布后，develop可继续进行后续开发，当正式版本出现问题时，需要进行问题的修改，可以在主分支（main）分支建立修改补丁hotfix。将当前分支切换到主分支（main），点击“Git工作流”，选择“建立新的修复补丁”。在该分支下进行主分支（main）的问题修改，修改完成后进行提交。当所有补丁问题修改完成后，点击“Git工作流”，选择“完成修复补丁”。"><a href="#6、正式版本发布后，develop可继续进行后续开发，当正式版本出现问题时，需要进行问题的修改，可以在主分支（main）分支建立修改补丁hotfix。将当前分支切换到主分支（main），点击“Git工作流”，选择“建立新的修复补丁”。在该分支下进行主分支（main）的问题修改，修改完成后进行提交。当所有补丁问题修改完成后，点击“Git工作流”，选择“完成修复补丁”。" class="headerlink" title="6、正式版本发布后，develop可继续进行后续开发，当正式版本出现问题时，需要进行问题的修改，可以在主分支（main）分支建立修改补丁hotfix。将当前分支切换到主分支（main），点击“Git工作流”，选择“建立新的修复补丁”。在该分支下进行主分支（main）的问题修改，修改完成后进行提交。当所有补丁问题修改完成后，点击“Git工作流”，选择“完成修复补丁”。"></a>6、正式版本发布后，<code>develop</code>可继续进行后续开发，当正式版本出现问题时，需要进行问题的修改，可以在主分支（<code>main</code>）分支建立修改补丁<code>hotfix</code>。将当前分支切换到主分支（<code>main</code>），点击“Git工作流”，选择“建立新的修复补丁”。在该分支下进行主分支（<code>main</code>）的问题修改，修改完成后进行提交。当所有补丁问题修改完成后，点击“Git工作流”，选择“完成修复补丁”。</h4>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;&lt;img src=&quot;https://pic.wjnba.top/img/202410/20241022163858.webp&quot; alt=&quot;image-20241022163848446&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;一般的企业级开发分支共有5种类型&quot;&gt;&lt;a href=&quot;#一般</summary>
      
    
    
    
    <category term="代码规范" scheme="https://www.wjnba.top/categories/%E4%BB%A3%E7%A0%81%E8%A7%84%E8%8C%83/"/>
    
    
    <category term="Git" scheme="https://www.wjnba.top/tags/Git/"/>
    
    <category term="代码规范" scheme="https://www.wjnba.top/tags/%E4%BB%A3%E7%A0%81%E8%A7%84%E8%8C%83/"/>
    
  </entry>
  
  <entry>
    <title>正则表达式学习</title>
    <link href="https://www.wjnba.top/articles/202410188aafe27d2b6b.html"/>
    <id>https://www.wjnba.top/articles/202410188aafe27d2b6b.html</id>
    <published>2024-10-18T08:06:49.000Z</published>
    <updated>2025-12-15T03:40:53.442Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://pic.wjnba.top/img/202410/20241018162009.webp" alt="image-20241018162004870"></p><h2 id="1-基本匹配"><a href="#1-基本匹配" class="headerlink" title="1. 基本匹配"></a>1. 基本匹配</h2><p>正则表达式只是我们用于在文本中检索字母和数字的模式。例如正则表达式 <code>cat</code>，表示: 字母 <code>c</code> 后面跟着一个字母 <code>a</code>，再后面跟着一个字母 <code>t</code>。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&quot;cat&quot;</span> =&gt; The cat sat on the mat</span><br></pre></td></tr></table></figure><p>正则表达式 <code>123</code> 会匹配字符串 “123”。通过将正则表达式中的每个字符逐个与要匹配的字符串中的每个字符进行比较，来完成正则匹配。 正则表达式通常区分大小写，因此正则表达式 <code>Cat</code> 与字符串 “cat” 不匹配。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&quot;Cat&quot;</span> =&gt; The cat sat on the Cat</span><br></pre></td></tr></table></figure><h2 id="2-元字符"><a href="#2-元字符" class="headerlink" title="2. 元字符"></a>2. 元字符</h2><p>元字符是正则表达式的基本组成元素。元字符在这里跟它通常表达的意思不一样，而是以某种特殊的含义去解释。有些元字符写在方括号内的时候有特殊含义。 元字符如下:</p><div class="table-container"><table><thead><tr><th>元字符</th><th>描述</th></tr></thead><tbody><tr><td>.</td><td>匹配除换行符以外的任意字符。</td></tr><tr><td>[ ]</td><td>字符类，匹配方括号中包含的任意字符。</td></tr><tr><td><sup><a href="#fn_ " id="reffn_ "> </a></sup></td><td>否定字符类。匹配方括号中不包含的任意字符</td></tr><tr><td>*</td><td>匹配前面的子表达式零次或多次</td></tr><tr><td>+</td><td>匹配前面的子表达式一次或多次</td></tr><tr><td>?</td><td>匹配前面的子表达式零次或一次，或指明一个非贪婪限定符。</td></tr><tr><td>{n,m}</td><td>花括号，匹配前面字符至少 n 次，但是不超过 m 次。</td></tr><tr><td>(xyz)</td><td>字符组，按照确切的顺序匹配字符xyz。</td></tr><tr><td>&#124;</td><td>分支结构，匹配符号之前的字符或后面的字符。</td></tr><tr><td>\</td><td>转义符，它可以还原元字符原来的含义，允许你匹配保留字符 [ ] ( ) { } . * + ? ^ $ \ &#124;</td></tr><tr><td>^</td><td>匹配行的开始</td></tr><tr><td>$</td><td>匹配行的结束</td></tr></tbody></table></div><h2 id="2-1-英文句号"><a href="#2-1-英文句号" class="headerlink" title="2.1 英文句号"></a>2.1 英文句号</h2><p>英文句号 <code>.</code> 是元字符的最简单的例子。元字符 <code>.</code> 可以匹配任意单个字符。它不会匹配换行符和新行的字符。例如正则表达式 <code>.ar</code>，表示: 任意字符后面跟着一个字母 <code>a</code>， 再后面跟着一个字母 <code>r</code>。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&quot;.ar&quot;</span> =&gt; The car parked <span class="keyword">in</span> the garage.</span><br></pre></td></tr></table></figure><h2 id="2-2-字符集"><a href="#2-2-字符集" class="headerlink" title="2.2 字符集"></a>2.2 字符集</h2><p>字符集也称为字符类。方括号被用于指定字符集。使用字符集内的连字符来指定字符范围。方括号内的字符范围的顺序并不重要。 例如正则表达式 <code>[Tt]he</code>，表示: 大写 <code>T</code> 或小写 <code>t</code> ，后跟字母 <code>h</code>，再后跟字母 <code>e</code>。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&quot;[Tt]he&quot;</span> =&gt; The car parked <span class="keyword">in</span> the garage.</span><br></pre></td></tr></table></figure><p>然而，字符集中的英文句号表示它字面的含义。正则表达式 <code>ar[.]</code>，表示小写字母 <code>a</code>，后面跟着一个字母 <code>r</code>，再后面跟着一个英文句号 <code>.</code> 字符。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&quot;ar[.]&quot;</span> =&gt; A garage is a good place to park a car.</span><br></pre></td></tr></table></figure><h3 id="2-2-1-否定字符集"><a href="#2-2-1-否定字符集" class="headerlink" title="2.2.1 否定字符集"></a>2.2.1 否定字符集</h3><p>一般来说插入字符 <code>^</code> 表示一个字符串的开始，但是当它在方括号内出现时，它会取消字符集。例如正则表达式 <code>[^c]ar</code>，表示: 除了字母 <code>c</code> 以外的任意字符，后面跟着字符 <code>a</code>， 再后面跟着一个字母 <code>r</code>。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&quot;[^c]ar&quot;</span> =&gt; The car parked <span class="keyword">in</span> the garage.</span><br></pre></td></tr></table></figure><h2 id="2-3-重复"><a href="#2-3-重复" class="headerlink" title="2.3 重复"></a>2.3 重复</h2><p>以下元字符 <code>+</code>，<code>*</code> 或 <code>?</code> 用于指定子模式可以出现多少次。这些元字符在不同情况下的作用不同。</p><h3 id="2-3-1-星号"><a href="#2-3-1-星号" class="headerlink" title="2.3.1 星号"></a>2.3.1 星号</h3><p>该符号 <code>*</code> 表示匹配上一个匹配规则的零次或多次。正则表达式 <code>a*</code> 表示小写字母 <code>a</code> 可以重复零次或者多次。但是它如果出现在字符集或者字符类之后，它表示整个字符集的重复。 例如正则表达式 <code>[a-z]*</code>，表示: 一行中可以包含任意数量的小写字母。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&quot;[a-z]*&quot;</span> =&gt; The car parked <span class="keyword">in</span> the garage <span class="comment">#21.</span></span><br></pre></td></tr></table></figure><p>该 <code>*</code> 符号可以与元符号 <code>.</code> 用在一起，用来匹配任意字符串 <code>.*</code>。该 <code>*</code> 符号可以与空格符 <code>\s</code> 一起使用，用来匹配一串空格字符。 例如正则表达式 <code>\s*cat\s*</code>，表示: 零个或多个空格，后面跟小写字母 <code>c</code>，再后面跟小写字母 <code>a</code>，再再后面跟小写字母 <code>t</code>，后面再跟零个或多个空格。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&quot;\scat\s&quot;</span> =&gt; The fat cat sat on the cat.</span><br></pre></td></tr></table></figure><h3 id="2-3-2-加号"><a href="#2-3-2-加号" class="headerlink" title="2.3.2 加号"></a>2.3.2 加号</h3><p>该符号 <code>+</code> 匹配上一个字符的一次或多次。例如正则表达式 <code>c.+t</code>，表示: 一个小写字母 <code>c</code>，后跟任意数量的字符，后跟小写字母 <code>t</code>。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&quot;c.+t&quot;</span> =&gt; The fat cat sat on the mat.</span><br></pre></td></tr></table></figure><h3 id="2-3-3-问号"><a href="#2-3-3-问号" class="headerlink" title="2.3.3 问号"></a>2.3.3 问号</h3><p>在正则表达式中，元字符 <code>?</code> 用来表示前一个字符是可选的。该符号匹配前一个字符的零次或一次。 例如正则表达式 <code>[T]?he</code>，表示: 可选的大写字母 <code>T</code>，后面跟小写字母 <code>h</code>，后跟小写字母 <code>e</code>。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&quot;[T]he&quot;</span> =&gt; The car is parked <span class="keyword">in</span> the garage.</span><br><span class="line"><span class="string">&quot;[T]?he&quot;</span> =&gt; The car is parked <span class="keyword">in</span> the garage.</span><br></pre></td></tr></table></figure><h2 id="2-4-花括号"><a href="#2-4-花括号" class="headerlink" title="2.4 花括号"></a>2.4 花括号</h2><p>在正则表达式中花括号(也被称为量词 ?)用于指定字符或一组字符可以重复的次数。例如正则表达式 <code>[0-9]&#123;2,3&#125;</code>，表示: 匹配至少2位数字但不超过3位(0到9范围内的字符)。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&quot;[0-9]&#123;2,3&#125;&quot;</span> =&gt; The number was 9.9997 but we rounded it off to 10.0.</span><br></pre></td></tr></table></figure><p>我们可以省略第二个数字。例如正则表达式 <code>[0-9]&#123;2,&#125;</code>，表示: 匹配2个或更多个数字。如果我们也删除逗号，则正则表达式 <code>[0-9]&#123;2&#125;</code>，表示: 匹配正好为2位数的数字。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&quot;[0-9]&#123;2,&#125;&quot;</span> =&gt; The number was 9.9997 but we rounded it off to 10.0.</span><br><span class="line"><span class="string">&quot;[0-9]&#123;2&#125;&quot;</span> =&gt; The number was 9.9997 but we rounded it off to 10.0.</span><br></pre></td></tr></table></figure><h2 id="2-5-字符组"><a href="#2-5-字符组" class="headerlink" title="2.5 字符组"></a>2.5 字符组</h2><p>字符组是一组写在圆括号内的子模式 <code>(...)</code>。正如我们在正则表达式中讨论的那样，如果我们把一个量词放在一个字符之后，它会重复前一个字符。 但是，如果我们把量词放在一个字符组之后，它会重复整个字符组。 例如正则表达式 <code>(ab)*</code> 表示匹配零个或多个的字符串 “ab”。我们还可以在字符组中使用元字符 <code>|</code>。例如正则表达式 <code>(c|g|p)ar</code>，表示: 小写字母 <code>c</code>、<code>g</code> 或 <code>p</code> 后面跟字母 <code>a</code>，后跟字母 <code>r</code>。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&quot;(c|g|p)ar&quot;</span> =&gt; The car is parked <span class="keyword">in</span> the garage.</span><br></pre></td></tr></table></figure><h2 id="2-6-分支结构"><a href="#2-6-分支结构" class="headerlink" title="2.6 分支结构"></a>2.6 分支结构</h2><p>在正则表达式中垂直条 <code>|</code> 用来定义分支结构，分支结构就像多个表达式之间的条件。现在你可能认为这个字符集和分支机构的工作方式一样。 但是字符集和分支结构巨大的区别是字符集只在字符级别上有作用，然而分支结构在表达式级别上依然可以使用。 例如正则表达式 <code>(T|t)he|car</code>，表示: 大写字母 <code>T</code> 或小写字母 <code>t</code>，后面跟小写字母 <code>h</code>，后跟小写字母 <code>e</code> 或小写字母 <code>c</code>，后跟小写字母 <code>a</code>，后跟小写字母 <code>r</code>。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&quot;(T|t)he|car&quot;</span> =&gt; The car is parked <span class="keyword">in</span> the garage.</span><br></pre></td></tr></table></figure><h2 id="2-7-转义特殊字符"><a href="#2-7-转义特殊字符" class="headerlink" title="2.7 转义特殊字符"></a>2.7 转义特殊字符</h2><p>正则表达式中使用反斜杠 <code>\</code> 来转义下一个字符。这将允许你使用保留字符来作为匹配字符 <code>&#123; &#125; [ ] / \ + * . $ ^ | ?</code>。在特殊字符前面加 <code>\</code>，就可以使用它来做匹配字符。 例如正则表达式 <code>.</code> 是用来匹配除了换行符以外的任意字符。现在要在输入字符串中匹配 <code>.</code> 字符，正则表达式 <code>(f|c|m)at\.?</code>，表示: 小写字母 <code>f</code>、<code>c</code> 或者 <code>m</code> 后跟小写字母 <code>a</code>，后跟小写字母 <code>t</code>，后跟可选的 <code>.</code> 字符。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&quot;(f|c|m)at.?&quot;</span> =&gt; The fat cat sat on the mat.</span><br></pre></td></tr></table></figure><h2 id="2-8-定位符"><a href="#2-8-定位符" class="headerlink" title="2.8 定位符"></a>2.8 定位符</h2><p>在正则表达式中，为了检查匹配符号是否是起始符号或结尾符号，我们使用定位符。 定位符有两种类型: 第一种类型是 <code>^</code> 检查匹配字符是否是起始字符，第二种类型是 <code>$</code>，它检查匹配字符是否是输入字符串的最后一个字符。</p><h3 id="2-8-1-插入符号"><a href="#2-8-1-插入符号" class="headerlink" title="2.8.1 插入符号"></a>2.8.1 插入符号</h3><p>插入符号 <code>^</code> 符号用于检查匹配字符是否是输入字符串的第一个字符。如果我们使用正则表达式 <code>^a</code> (如果a是起始符号)匹配字符串 <code>abc</code>，它会匹配到 <code>a</code>。 但是如果我们使用正则表达式 <code>^b</code>，它是匹配不到任何东西的，因为在字符串 <code>abc</code> 中 “b” 不是起始字符。 让我们来看看另一个正则表达式 <code>^(T|t)he</code>，这表示: 大写字母 <code>T</code> 或小写字母 <code>t</code> 是输入字符串的起始符号，后面跟着小写字母 <code>h</code>，后跟小写字母 <code>e</code>。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&quot;(T|t)he&quot;</span> =&gt; The car is parked <span class="keyword">in</span> the garage.</span><br><span class="line"><span class="string">&quot;^(T|t)he&quot;</span> =&gt; The car is parked <span class="keyword">in</span> the garage.</span><br></pre></td></tr></table></figure><h3 id="2-8-2-美元符号"><a href="#2-8-2-美元符号" class="headerlink" title="2.8.2 美元符号"></a>2.8.2 美元符号</h3><p>美元 <script type="math/tex">` 符号用于检查匹配字符是否是输入字符串的最后一个字符。例如正则表达式 `(at\.)</script>，表示: 小写字母 <code>a</code>，后跟小写字母 <code>t</code>，后跟一个 <code>.</code> 字符，且这个匹配器必须是字符串的结尾。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&quot;(at.)&quot;</span> =&gt; The fat cat. sat. on the mat.</span><br><span class="line"><span class="string">&quot;(at.)$&quot;</span> =&gt; The fat cat sat on the mat.</span><br></pre></td></tr></table></figure><h2 id="3-简写字符集"><a href="#3-简写字符集" class="headerlink" title="3. 简写字符集"></a>3. 简写字符集</h2><p>正则表达式为常用的字符集和常用的正则表达式提供了简写。简写字符集如下:</p><div class="table-container"><table><thead><tr><th>简写</th><th>描述</th></tr></thead><tbody><tr><td>.</td><td>匹配除换行符以外的任意字符</td></tr><tr><td>\w</td><td>匹配所有字母和数字的字符: <code>[a-zA-Z0-9_]</code></td></tr><tr><td>\W</td><td>匹配非字母和数字的字符: <code>[^\w]</code></td></tr><tr><td>\d</td><td>匹配数字: <code>[0-9]</code></td></tr><tr><td>\D</td><td>匹配非数字: <code>[^\d]</code></td></tr><tr><td>\s</td><td>匹配空格符: <code>[\t\n\f\r\p&#123;Z&#125;]</code></td></tr><tr><td>\S</td><td>匹配非空格符: <code>[^\s]</code></td></tr></tbody></table></div><h2 id="4-断言"><a href="#4-断言" class="headerlink" title="4. 断言"></a>4. 断言</h2><p>后行断言和先行断言有时候被称为断言，它们是特殊类型的 <strong><em>非捕获组</em></strong> (用于匹配模式，但不包括在匹配列表中)。当我们在一种特定模式之前或者之后有这种模式时，会优先使用断言。 例如我们想获取输入字符串 <script type="math/tex">4.44 and $10.88` 中带有前缀 `</script> 的所有数字。我们可以使用这个正则表达式 <code>(?&lt;=\$)[0-9\.]*</code>，表示: 获取包含 <code>.</code> 字符且前缀为 <code>$</code> 的所有数字。 以下是正则表达式中使用的断言:</p><div class="table-container"><table><thead><tr><th>符号</th><th>描述</th></tr></thead><tbody><tr><td>?=</td><td>正向先行断言</td></tr><tr><td>?!</td><td>负向先行断言</td></tr><tr><td>?&lt;=</td><td>正向后行断言</td></tr><tr><td>?&lt;!</td><td>负向后行断言</td></tr></tbody></table></div><h3 id="4-1-正向先行断言"><a href="#4-1-正向先行断言" class="headerlink" title="4.1 正向先行断言"></a>4.1 正向先行断言</h3><p>正向先行断言认为第一部分的表达式必须是先行断言表达式。返回的匹配结果仅包含与第一部分表达式匹配的文本。 要在一个括号内定义一个正向先行断言，在括号中问号和等号是这样使用的 <code>(?=...)</code>。先行断言表达式写在括号中的等号后面。 例如正则表达式 <code>(T|t)he(?=\sfat)</code>，表示: 匹配大写字母 <code>T</code> 或小写字母 <code>t</code>，后面跟字母 <code>h</code>，后跟字母 <code>e</code>。 在括号中，我们定义了正向先行断言，它会引导正则表达式引擎匹配 <code>The</code> 或 <code>the</code> 后面跟着 <code>fat</code>。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&quot;(T|t)he(?=\sfat)&quot;</span> =&gt; The fat cat sat on the mat.</span><br></pre></td></tr></table></figure><h3 id="4-2-负向先行断言"><a href="#4-2-负向先行断言" class="headerlink" title="4.2 负向先行断言"></a>4.2 负向先行断言</h3><p>当我们需要从输入字符串中获取不匹配表达式的内容时，使用负向先行断言。负向先行断言的定义跟我们定义的正向先行断言一样， 唯一的区别是不是等号 <code>=</code>，我们使用否定符号 <code>!</code>，例如 <code>(?!...)</code>。 我们来看看下面的正则表达式 <code>(T|t)he(?!\sfat)</code>，表示: 从输入字符串中获取全部 <code>The</code> 或者 <code>the</code> 且不匹配 <code>fat</code> 前面加上一个空格字符。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&quot;(T|t)he(?!\sfat)&quot;</span> =&gt; The fat cat sat on the mat.</span><br></pre></td></tr></table></figure><h3 id="4-3-正向后行断言"><a href="#4-3-正向后行断言" class="headerlink" title="4.3 正向后行断言"></a>4.3 正向后行断言</h3><p>正向后行断言是用于获取在特定模式之前的所有匹配内容。正向后行断言表示为 <code>(?&lt;=...)</code>。例如正则表达式 <code>(?&lt;=(T|t)he\s)(fat|mat)</code>，表示: 从输入字符串中获取在单词 <code>The</code> 或 <code>the</code> 之后的所有 <code>fat</code> 和 <code>mat</code> 单词。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&quot;(?&lt;=(T|t)he\s)(fat|mat)&quot;</span> =&gt; The fat cat sat on the mat.</span><br></pre></td></tr></table></figure><h3 id="4-4-负向后行断言"><a href="#4-4-负向后行断言" class="headerlink" title="4.4 负向后行断言"></a>4.4 负向后行断言</h3><p>负向后行断言是用于获取不在特定模式之前的所有匹配的内容。负向后行断言表示为 <code>(?&lt;!...)</code>。例如正则表达式 <code>(?&lt;!(T|t)he\s)(cat)</code>，表示: 在输入字符中获取所有不在 <code>The</code> 或 <code>the</code> 之后的所有单词 <code>cat</code>。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&quot;(?&lt;!(T|t)he\s)(cat)&quot;</span> =&gt; The cat sat on cat.</span><br></pre></td></tr></table></figure><h2 id="5-标记"><a href="#5-标记" class="headerlink" title="5. 标记"></a>5. 标记</h2><p>标记也称为修饰符，因为它会修改正则表达式的输出。这些标志可以以任意顺序或组合使用，并且是正则表达式的一部分。</p><div class="table-container"><table><thead><tr><th>标记</th><th>描述</th></tr></thead><tbody><tr><td>i</td><td>不区分大小写: 将匹配设置为不区分大小写。</td></tr><tr><td>g</td><td>全局搜索: 搜索整个输入字符串中的所有匹配。</td></tr><tr><td>m</td><td>多行匹配: 会匹配输入字符串每一行。</td></tr></tbody></table></div><ul><li><strong>数字</strong>: <code>\d+$</code></li><li><strong>用户名</strong>: <code>^[\w\d_.]&#123;4,16&#125;$</code></li><li><strong>字母数字字符</strong>: <code>^[a-zA-Z0-9]*$</code></li><li><strong>带空格的字母数字字符</strong>: <code>^[a-zA-Z0-9 ]*$</code></li><li><strong>小写字母</strong>: <code>[a-z]+$</code></li><li><strong>大写字母</strong>: <code>[A-Z]+$</code></li><li><strong>网址</strong>: <code>^(((http|https|ftp):\/\/)?([[a-zA-Z0-9]\-\.])+(\.)([[a-zA-Z0-9]])&#123;2,4&#125;([[a-zA-Z0-9]\/+=%&amp;_\.~?\-]*))*$</code></li><li><strong>日期 (MM/DD/YYYY)</strong>: <code>^(0?[1-9]|1[012])[- /.](0?[1-9]|[12][0-9]|3[01])[- /.](19|20)?[0-9]&#123;2&#125;$</code></li><li><strong>日期 (YYYY/MM/DD)</strong>: <code>^(19|20)?[0-9]&#123;2&#125;[- /.](0?[1-9]|1[012])[- /.](0?[1-9]|[12][0-9]|3[01])$</code></li><li><strong>Html标签</strong>: <code>&lt;[^&gt;]+?&gt;</code></li></ul>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;&lt;img src=&quot;https://pic.wjnba.top/img/202410/20241018162009.webp&quot; alt=&quot;image-20241018162004870&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;1-基本匹配&quot;&gt;&lt;a href=&quot;#1-基本匹配&quot; clas</summary>
      
    
    
    
    <category term="正则表达式" scheme="https://www.wjnba.top/categories/%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F/"/>
    
    
    <category term="正则表达式" scheme="https://www.wjnba.top/tags/%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F/"/>
    
  </entry>
  
  <entry>
    <title>vue3常用的API</title>
    <link href="https://www.wjnba.top/articles/20241011497ebe003dad.html"/>
    <id>https://www.wjnba.top/articles/20241011497ebe003dad.html</id>
    <published>2024-10-11T02:47:13.000Z</published>
    <updated>2025-12-15T03:40:53.439Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://pic.wjnba.top/img/202406/20240617110657.webp" alt=""></p><p>Vue2每次都把整个Vue导入，例如Vue2的 <code>main.js</code> 文件中的代码</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> Vue <span class="keyword">from</span> <span class="string">&#x27;vue&#x27;</span></span><br><span class="line"><span class="keyword">import</span> App <span class="keyword">from</span> <span class="string">&#x27;./App.vue&#x27;</span></span><br><span class="line"></span><br><span class="line">Vue.config.productionTip = <span class="literal">false</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">new</span> Vue(&#123;</span><br><span class="line">  <span class="attr">render</span>: <span class="function"><span class="params">h</span> =&gt;</span> h(App)</span><br><span class="line">&#125;).$mount(<span class="string">&#x27;#app&#x27;</span>)</span><br></pre></td></tr></table></figure><p>但很明显我们的项目中不可能用到Vue所有的API，因此很多模块其实是没有用的</p><p>那么在Vue3中，对外暴露了很多的API供开发者使用，我们可以根据自己的需求，将所需要的API从Vue中导入。例如 <code>main.js</code> 中的代码</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; createApp &#125; <span class="keyword">from</span> <span class="string">&#x27;vue&#x27;</span>;</span><br><span class="line"><span class="keyword">import</span> App <span class="keyword">from</span> <span class="string">&#x27;./App.vue&#x27;</span></span><br><span class="line"></span><br><span class="line">createApp(App).mount(<span class="string">&#x27;#app&#x27;</span>)</span><br></pre></td></tr></table></figure><p>利用了 <code>import</code> 和 <code>export</code> 的导入导出语法，实现了按需打包模块的功能，项目打包后的文件体积明显小了很多</p><p>这也是我们本文需要对 <code>Vue3 API</code> 进行详细了解的原因</p><h3 id="（1）setup"><a href="#（1）setup" class="headerlink" title="（1）setup"></a>（1）setup</h3><p><code>setup</code> 函数也是 <code>Compsition API</code> 的入口函数，我们的变量、方法都是在该函数里定义的，来看一下使用方法</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">template</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">p</span>&gt;</span>&#123;&#123; number &#125;&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">button</span> @<span class="attr">click</span>=<span class="string">&quot;add&quot;</span>&gt;</span>增加<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="javascript"></span></span><br><span class="line"><span class="javascript"><span class="comment">// 1. 从 vue 中引入 ref 函数</span></span></span><br><span class="line"><span class="javascript"><span class="keyword">import</span> &#123;ref&#125; <span class="keyword">from</span> <span class="string">&#x27;vue&#x27;</span></span></span><br><span class="line"><span class="javascript"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span></span><br><span class="line"><span class="javascript">  <span class="attr">name</span>: <span class="string">&#x27;App&#x27;</span>,</span></span><br><span class="line"><span class="javascript">  <span class="function"><span class="title">setup</span>(<span class="params"></span>)</span> &#123;</span></span><br><span class="line"><span class="javascript">      <span class="comment">// 2. 用 ref 函数包装一个响应式变量 number</span></span></span><br><span class="line"><span class="javascript">    <span class="keyword">let</span> number = ref(<span class="number">0</span>)</span></span><br><span class="line"><span class="javascript">    </span></span><br><span class="line"><span class="javascript">    <span class="comment">// 3. 设定一个方法</span></span></span><br><span class="line"><span class="javascript">    <span class="function"><span class="keyword">function</span> <span class="title">add</span>(<span class="params"></span>) </span>&#123;</span></span><br><span class="line"><span class="javascript">        <span class="comment">// number是被ref函数包装过了的，其值保存在.value中</span></span></span><br><span class="line"><span class="javascript">      number.value ++</span></span><br><span class="line"><span class="javascript">    &#125;</span></span><br><span class="line"><span class="javascript">    </span></span><br><span class="line"><span class="javascript">    <span class="comment">// 4. 将 number 和 add 返回出去，供template中使用</span></span></span><br><span class="line"><span class="javascript">    <span class="keyword">return</span> &#123;number, add&#125;</span></span><br><span class="line"><span class="javascript">  &#125;</span></span><br><span class="line"><span class="javascript">  </span></span><br><span class="line"><span class="javascript">&#125;</span></span><br><span class="line"><span class="javascript"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure><p>上述代码中用到了 <code>ref</code> 函数，下面会详细讲解，在这里你只需要理解它的作用是包装一个响应式的数据即可，并且你可以将 <code>ref</code> 函数包装过的变量看作是Vue2 <code>data</code> 中的变量</p><p>这样就简单实现了一个点击按钮数字加1的功能</p><hr><p>在Vue2中，我们访问 <code>data</code> 或 <code>props</code> 中的变量，都是通过类似 <code>this.number</code> 这样的形式去获取的，但要特别注意的是，在setup中，<code>this</code> 指向的是 <code>undefined</code>，也就是说不能再向Vue2一样通过 <code>this</code> 去获取变量了</p><p>那么到底该如何获取到 <code>props</code> 中的数据呢？</p><p>其实 <code>setup</code> 函数还有两个参数，分别是 <code>props</code> 、<code>context</code>，前者存储着定义当前组件允许外界传递过来的参数名称以及对应的值；后者是一个上下文对象，能从中访问到 <code>attr</code> 、<code>emit</code> 、<code>slots</code></p><p>其中 <code>emit</code> 就是我们熟悉的Vue2中与父组件通信的方法，可以直接拿来调用</p><h3 id="（2）生命周期"><a href="#（2）生命周期" class="headerlink" title="（2）生命周期"></a>（2）生命周期</h3><p>Vue2中有 <code>beforeCreate</code> 、<code>created</code> 、<code>beforeMount</code> 、<code>mounted</code> 、<code>beforeUpdate</code> 等生命周期函数</p><p>而在Vue3中，这些生命周期部分有所变化，并且调用的方式也有所改变，下面放上一张变化图来简单了解一下</p><div class="table-container"><table><thead><tr><th>Vue2</th><th>Vue3</th></tr></thead><tbody><tr><td>beforeCreate</td><td>setup</td></tr><tr><td>created</td><td>setup</td></tr><tr><td>beforeMount</td><td>onBeforeMount</td></tr><tr><td>mounted</td><td>onMounted</td></tr><tr><td>beforeUpdate</td><td>onBeforeUpdate</td></tr><tr><td>updated</td><td>onUpdated</td></tr><tr><td>beforeDestory</td><td>onBeforeUnmount</td></tr><tr><td>destoryed</td><td>unMounted</td></tr></tbody></table></div><p>Vue3的这些生命周期调用也很简单，同样是先从 <code>vue</code> 中导入，再进行直接调用</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">template</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="javascript"></span></span><br><span class="line"><span class="javascript"><span class="comment">// 1. 从 vue 中引入 多个生命周期函数</span></span></span><br><span class="line"><span class="javascript"><span class="keyword">import</span> &#123;onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, unMounted&#125; <span class="keyword">from</span> <span class="string">&#x27;vue&#x27;</span></span></span><br><span class="line"><span class="javascript"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span></span><br><span class="line"><span class="javascript">  <span class="attr">name</span>: <span class="string">&#x27;App&#x27;</span>,</span></span><br><span class="line"><span class="javascript">  <span class="function"><span class="title">setup</span>(<span class="params"></span>)</span> &#123;</span></span><br><span class="line"><span class="javascript">    onBeforeMount(<span class="function">() =&gt;</span> &#123;</span></span><br><span class="line"><span class="javascript">      <span class="comment">// 在挂载前执行某些代码</span></span></span><br><span class="line"><span class="javascript">    &#125;)</span></span><br><span class="line"><span class="javascript"></span></span><br><span class="line"><span class="javascript">    onMounted(<span class="function">() =&gt;</span> &#123;</span></span><br><span class="line"><span class="javascript">      <span class="comment">// 在挂载后执行某些代码</span></span></span><br><span class="line"><span class="javascript">    &#125;)</span></span><br><span class="line"><span class="javascript"></span></span><br><span class="line"><span class="javascript">    onBeforeUpdate(<span class="function">() =&gt;</span> &#123;</span></span><br><span class="line"><span class="javascript">      <span class="comment">// 在更新前前执行某些代码</span></span></span><br><span class="line"><span class="javascript">    &#125;)</span></span><br><span class="line"><span class="javascript"></span></span><br><span class="line"><span class="javascript">    onUpdated(<span class="function">() =&gt;</span> &#123;</span></span><br><span class="line"><span class="javascript">      <span class="comment">// 在更新后执行某些代码</span></span></span><br><span class="line"><span class="javascript">    &#125;)</span></span><br><span class="line"><span class="javascript"></span></span><br><span class="line"><span class="javascript">    onBeforeUnmount(<span class="function">() =&gt;</span> &#123;</span></span><br><span class="line"><span class="javascript">      <span class="comment">// 在组件销毁前执行某些代码</span></span></span><br><span class="line"><span class="javascript">    &#125;)</span></span><br><span class="line"><span class="javascript"></span></span><br><span class="line"><span class="javascript">    unMounted(<span class="function">() =&gt;</span> &#123;</span></span><br><span class="line"><span class="javascript">      <span class="comment">// 在组件销毁后执行某些代码</span></span></span><br><span class="line"><span class="javascript">    &#125;)</span></span><br><span class="line"><span class="javascript"></span></span><br><span class="line"><span class="javascript">    <span class="keyword">return</span> &#123;&#125;</span></span><br><span class="line"><span class="javascript">  &#125;</span></span><br><span class="line"><span class="javascript">  </span></span><br><span class="line"><span class="javascript">&#125;</span></span><br><span class="line"><span class="javascript"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure><p>要特别说明一下的就是，<code>setup</code> 函数代替了 <code>beforeCreate</code> 和 <code>created</code> 两个生命周期函数，因此我们可以认为它的执行时间在<code>beforeCreate</code> 和 <code>created</code> 之间</p><h3 id="（3）reactive"><a href="#（3）reactive" class="headerlink" title="（3）reactive"></a>（3）reactive</h3><p><code>reactive</code> 方法是用来创建一个响应式的数据对象，该API也很好地解决了Vue2通过 <code>defineProperty</code> 实现数据响应式的缺陷</p><p>用法很简单，只需将数据作为参数传入即可，代码如下</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">template</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span><br><span class="line">      <span class="comment">&lt;!-- 4. 访问响应式数据对象中的 count  --&gt;</span></span><br><span class="line">      &#123;&#123; state.count &#125;&#125;</span><br><span class="line">  <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="javascript"></span></span><br><span class="line"><span class="javascript"><span class="comment">// 1. 从 vue 中导入 reactive </span></span></span><br><span class="line"><span class="javascript"><span class="keyword">import</span> &#123;reactive&#125; <span class="keyword">from</span> <span class="string">&#x27;vue&#x27;</span></span></span><br><span class="line"><span class="javascript"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span></span><br><span class="line"><span class="javascript">  <span class="attr">name</span>: <span class="string">&#x27;App&#x27;</span>,</span></span><br><span class="line"><span class="javascript">  <span class="function"><span class="title">setup</span>(<span class="params"></span>)</span> &#123;</span></span><br><span class="line"><span class="javascript">       <span class="comment">// 2. 创建响应式的数据对象</span></span></span><br><span class="line"><span class="javascript">    <span class="keyword">const</span> state = reactive(&#123;<span class="attr">count</span>: <span class="number">3</span>&#125;)</span></span><br><span class="line"><span class="javascript"></span></span><br><span class="line"><span class="javascript">    <span class="comment">// 3. 将响应式数据对象state return 出去，供template使用</span></span></span><br><span class="line"><span class="javascript">    <span class="keyword">return</span> &#123;state&#125;</span></span><br><span class="line"><span class="javascript">  &#125;</span></span><br><span class="line"><span class="javascript">&#125;</span></span><br><span class="line"><span class="javascript"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure><h3 id="（4）ref"><a href="#（4）ref" class="headerlink" title="（4）ref"></a>（4）ref</h3><p>在介绍 <code>setup</code> 函数时，我们使用了 <code>ref</code> 函数包装了一个响应式的数据对象，这里表面上看上去跟 <code>reactive</code> 好像功能一模一样啊，确实差不多，因为 <code>ref</code> 就是通过 <code>reactive</code> 包装了一个对象 ，然后是将值传给该对象中的 <code>value</code> 属性，这也就解释了为什么每次访问时我们都需要加上 <code>.value</code></p><p>我们可以简单地把 <code>ref(obj)</code> 理解为这个样子 <code>reactive(&#123;value: obj&#125;)</code></p><p>这里我们写一段代码来具体看一下</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">&lt;script&gt;</span><br><span class="line"><span class="keyword">import</span> &#123;ref, reactive&#125; <span class="keyword">from</span> <span class="string">&#x27;vue&#x27;</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span><br><span class="line">  <span class="attr">name</span>: <span class="string">&#x27;App&#x27;</span>,</span><br><span class="line">  <span class="function"><span class="title">setup</span>(<span class="params"></span>)</span> &#123;</span><br><span class="line">      <span class="keyword">const</span> obj = &#123;<span class="attr">count</span>: <span class="number">3</span>&#125;</span><br><span class="line">      <span class="keyword">const</span> state1 = ref(obj)</span><br><span class="line">      <span class="keyword">const</span> state2 = reactive(obj)</span><br><span class="line"></span><br><span class="line">    <span class="built_in">console</span>.log(state1)</span><br><span class="line">    <span class="built_in">console</span>.log(state2)</span><br><span class="line">  &#125;</span><br><span class="line">  </span><br><span class="line">&#125;</span><br><span class="line">&lt;/script&gt;</span><br></pre></td></tr></table></figure><p>来看一下打印结果</p><p><img src="https://pic.wjnba.top/img/202410/20241011105621.png" alt="在这里插入图片描述"></p><blockquote><p><strong>注意：</strong> 这里指的 <code>.value</code> 是在 <code>setup</code> 函数中访问 <code>ref</code> 包装后的对象时才需要加的，在 <code>template</code> 模板中访问时是不需要的，因为在编译时，会自动识别其是否为 <code>ref</code> 包装过的</p></blockquote><p>那么我们到底该如何选择 <code>ref</code> 和 <code>reactive</code> 呢？</p><p><strong>建议：</strong></p><ol><li>基本类型值（<code>String</code> 、<code>Nmuber</code> 、<code>Boolean</code> 等）或单值对象（类似像 <code>&#123;count: 3&#125;</code> 这样只有一个属性值的对象）使用 <code>ref</code></li><li>引用类型值（<code>Object</code> 、<code>Array</code>）使用 <code>reactive</code></li></ol><h3 id="（5）toRef"><a href="#（5）toRef" class="headerlink" title="（5）toRef"></a>（5）toRef</h3><p><code>toRef</code> 是将某个对象中的某个值转化为响应式数据，其接收两个参数，第一个参数为 <code>obj</code> 对象；第二个参数为对象中的属性名</p><p>代码如下：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">&lt;script&gt;</span><br><span class="line"><span class="comment">// 1. 导入 toRef</span></span><br><span class="line"><span class="keyword">import</span> &#123;toRef&#125; <span class="keyword">from</span> <span class="string">&#x27;vue&#x27;</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span><br><span class="line">    <span class="function"><span class="title">setup</span>(<span class="params"></span>)</span> &#123;</span><br><span class="line">        <span class="keyword">const</span> obj = &#123;<span class="attr">count</span>: <span class="number">3</span>&#125;</span><br><span class="line">        <span class="comment">// 2. 将 obj 对象中属性count的值转化为响应式数据</span></span><br><span class="line">        <span class="keyword">const</span> state = toRef(obj, <span class="string">&#x27;count&#x27;</span>)</span><br><span class="line">        </span><br><span class="line">              <span class="comment">// 3. 将toRef包装过的数据对象返回供template使用</span></span><br><span class="line">        <span class="keyword">return</span> &#123;state&#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">&lt;/script&gt;</span><br></pre></td></tr></table></figure><p>但其实表面上看上去 <code>toRef</code> 这个API好像非常的没用，因为这个功能也可以用 <code>ref</code> 实现，代码如下</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">&lt;script&gt;</span><br><span class="line"><span class="comment">// 1. 导入 ref</span></span><br><span class="line"><span class="keyword">import</span> &#123;ref&#125; <span class="keyword">from</span> <span class="string">&#x27;vue&#x27;</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span><br><span class="line">    <span class="function"><span class="title">setup</span>(<span class="params"></span>)</span> &#123;</span><br><span class="line">        <span class="keyword">const</span> obj = &#123;<span class="attr">count</span>: <span class="number">3</span>&#125;</span><br><span class="line">        <span class="comment">// 2. 将 obj 对象中属性count的值转化为响应式数据</span></span><br><span class="line">        <span class="keyword">const</span> state = ref(obj.count)</span><br><span class="line">        </span><br><span class="line">              <span class="comment">// 3. 将ref包装过的数据对象返回供template使用</span></span><br><span class="line">        <span class="keyword">return</span> &#123;state&#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">&lt;/script&gt;</span><br></pre></td></tr></table></figure><p>乍一看好像还真是，其实这两者是有区别的，我们可以通过一个案例来比较一下，代码如下</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">template</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">p</span>&gt;</span>&#123;&#123; state1 &#125;&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">button</span> @<span class="attr">click</span>=<span class="string">&quot;add1&quot;</span>&gt;</span>增加<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">p</span>&gt;</span>&#123;&#123; state2 &#125;&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">button</span> @<span class="attr">click</span>=<span class="string">&quot;add2&quot;</span>&gt;</span>增加<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="javascript"></span></span><br><span class="line"><span class="javascript"><span class="keyword">import</span> &#123;ref, toRef&#125; <span class="keyword">from</span> <span class="string">&#x27;vue&#x27;</span></span></span><br><span class="line"><span class="javascript"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span></span><br><span class="line"><span class="javascript">    <span class="function"><span class="title">setup</span>(<span class="params"></span>)</span> &#123;</span></span><br><span class="line"><span class="javascript">        <span class="keyword">const</span> obj = &#123;<span class="attr">count</span>: <span class="number">3</span>&#125;</span></span><br><span class="line"><span class="javascript">        <span class="keyword">const</span> state1 = ref(obj.count)</span></span><br><span class="line"><span class="javascript">        <span class="keyword">const</span> state2 = toRef(obj, <span class="string">&#x27;count&#x27;</span>)</span></span><br><span class="line"><span class="javascript"></span></span><br><span class="line"><span class="javascript">        <span class="function"><span class="keyword">function</span> <span class="title">add1</span>(<span class="params"></span>) </span>&#123;</span></span><br><span class="line"><span class="javascript">            state1.value ++</span></span><br><span class="line"><span class="javascript">            <span class="built_in">console</span>.log(<span class="string">&#x27;原始值：&#x27;</span>, obj);</span></span><br><span class="line"><span class="javascript">            <span class="built_in">console</span>.log(<span class="string">&#x27;响应式数据对象：&#x27;</span>, state1);</span></span><br><span class="line"><span class="javascript">        &#125;</span></span><br><span class="line"><span class="javascript"></span></span><br><span class="line"><span class="javascript">              <span class="function"><span class="keyword">function</span> <span class="title">add2</span>(<span class="params"></span>) </span>&#123;</span></span><br><span class="line"><span class="javascript">            state2.value ++</span></span><br><span class="line"><span class="javascript">            <span class="built_in">console</span>.log(<span class="string">&#x27;原始值：&#x27;</span>, obj);</span></span><br><span class="line"><span class="javascript">            <span class="built_in">console</span>.log(<span class="string">&#x27;响应式数据对象：&#x27;</span>, state2);</span></span><br><span class="line"><span class="javascript">        &#125;</span></span><br><span class="line"><span class="javascript"></span></span><br><span class="line"><span class="javascript">        <span class="keyword">return</span> &#123;state1, state2, add1, add2&#125;</span></span><br><span class="line"><span class="javascript">    &#125;</span></span><br><span class="line"><span class="javascript">&#125;</span></span><br><span class="line"><span class="javascript"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure><p>我们分别用 <code>ref</code> 和 <code>toRef</code> 将 <code>obj</code> 中的 <code>count</code> 转化为响应式，并声明了两个方法分别使 <code>count</code> 值增加，每次增加后打印一下原始值 <code>obj</code> 和被包装过的响应式数据对象，同时还要看看视图的变化</p><p><strong>ref：</strong></p><p><img src="https://pic.wjnba.top/img/202410/20241011105842.gif" alt="在这里插入图片描述"><br>可以看到，在对响应式数据的值进行 <code>+1</code> 操作后，视图改变了，原始值未改变，响应式数据对象的值也改变了，这说明 <code>ref</code> 是对原数据的一个<strong>拷贝</strong>，不会影响到原始值，同时响应式数据对象值改变后会同步更新视图</p><p><strong>toRef：</strong></p><p><img src="https://pic.wjnba.top/img/202410/20241011110129.gif" alt="在这里插入图片描述"><br>可以看到，在对响应式数据的值进行 <code>+1</code> 操作后，视图未发生改变，原始值改变了，响应式数据对象的值也改变了，这说明 <code>toRef</code> 是对原数据的一个<strong>引用</strong>，会影响到原始值，但是响应式数据对象值改变后会不会更新视图</p><p><strong>总结：</strong></p><ol><li><code>ref</code> 是对传入数据的拷贝；<code>toRef</code> 是对传入数据的引用</li><li><code>ref</code> 的值改变会更新视图；<code>toRef</code> 的值改变不会更新视图</li></ol><h3 id="（6）toRefs"><a href="#（6）toRefs" class="headerlink" title="（6）toRefs"></a>（6）toRefs</h3><p>了解完 <code>toRef</code> 后，就很好理解 <code>toRefs</code> 了，其作用就是将传入的对象里所有的属性的值都转化为响应式数据对象，该函数支持一个参数，即 <code>obj</code> 对象</p><p>我们来看一下它的基本使用</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">&lt;script&gt;</span><br><span class="line"><span class="comment">// 1. 导入 toRefs</span></span><br><span class="line"><span class="keyword">import</span> &#123;toRefs&#125; <span class="keyword">from</span> <span class="string">&#x27;vue&#x27;</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span><br><span class="line">    <span class="function"><span class="title">setup</span>(<span class="params"></span>)</span> &#123;</span><br><span class="line">        <span class="keyword">const</span> obj = &#123;</span><br><span class="line">          <span class="attr">name</span>: <span class="string">&#x27;前端印象&#x27;</span>,</span><br><span class="line">          <span class="attr">age</span>: <span class="number">22</span>,</span><br><span class="line">          <span class="attr">gender</span>: <span class="number">0</span></span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 2. 将 obj 对象中属性count的值转化为响应式数据</span></span><br><span class="line">        <span class="keyword">const</span> state = toRefs(obj)</span><br><span class="line">        </span><br><span class="line">        <span class="comment">// 3. 打印查看一下</span></span><br><span class="line">        <span class="built_in">console</span>.log(state)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">&lt;/script&gt;</span><br></pre></td></tr></table></figure><p>打印结果如下：</p><p><img src="https://pic.wjnba.top/img/202410/20241011110123.png" alt="在这里插入图片描述"><br>返回的是一个对象，对象里包含了每一个包装过后的响应式数据对象</p><h3 id="（7）shallowReactive"><a href="#（7）shallowReactive" class="headerlink" title="（7）shallowReactive"></a>（7）shallowReactive</h3><p>听这个API的名称就知道，这是一个渐层的 <code>reactive</code>，难道意思就是原本的 <code>reactive</code> 是深层的呗，没错，这是一个用于性能优化的API</p><p>其实将 <code>obj</code> 作为参数传递给 <code>reactive</code> 生成响应式数据对象时，若 <code>obj</code> 的层级不止一层，那么会将每一层都用 <code>Proxy</code> 包装一次，我们来验证一下</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">&lt;script&gt;</span><br><span class="line"><span class="keyword">import</span> &#123;reactive&#125; <span class="keyword">from</span> <span class="string">&#x27;vue&#x27;</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span><br><span class="line">    <span class="function"><span class="title">setup</span>(<span class="params"></span>)</span> &#123;</span><br><span class="line">        <span class="keyword">const</span> obj = &#123;</span><br><span class="line">          <span class="attr">a</span>: <span class="number">1</span>,</span><br><span class="line">          <span class="attr">first</span>: &#123;</span><br><span class="line">            <span class="attr">b</span>: <span class="number">2</span>,</span><br><span class="line">            <span class="attr">second</span>: &#123;</span><br><span class="line">              <span class="attr">c</span>: <span class="number">3</span></span><br><span class="line">            &#125;</span><br><span class="line">          &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        </span><br><span class="line">        <span class="keyword">const</span> state = reactive(obj)</span><br><span class="line"></span><br><span class="line">        <span class="built_in">console</span>.log(state)</span><br><span class="line">        <span class="built_in">console</span>.log(state.first)</span><br><span class="line">        <span class="built_in">console</span>.log(state.first.second)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">&lt;/script&gt;</span><br></pre></td></tr></table></figure><p>来看一下打印结果：</p><p><img src="https://pic.wjnba.top/img/202410/20241011105858.png" alt="在这里插入图片描述"><br>设想一下如果一个对象层级比较深，那么每一层都用 <code>Proxy</code> 包装后，对于性能是非常不友好的</p><p>接下来我们再来看看 <code>shallowReactive</code></p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">&lt;script&gt;</span><br><span class="line"><span class="keyword">import</span> &#123;shallowReactive&#125; <span class="keyword">from</span> <span class="string">&#x27;vue&#x27;</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span><br><span class="line">    <span class="function"><span class="title">setup</span>(<span class="params"></span>)</span> &#123;</span><br><span class="line">        <span class="keyword">const</span> obj = &#123;</span><br><span class="line">          <span class="attr">a</span>: <span class="number">1</span>,</span><br><span class="line">          <span class="attr">first</span>: &#123;</span><br><span class="line">            <span class="attr">b</span>: <span class="number">2</span>,</span><br><span class="line">            <span class="attr">second</span>: &#123;</span><br><span class="line">              <span class="attr">c</span>: <span class="number">3</span></span><br><span class="line">            &#125;</span><br><span class="line">          &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        </span><br><span class="line">        <span class="keyword">const</span> state = shallowReactive(obj)</span><br><span class="line"></span><br><span class="line">        <span class="built_in">console</span>.log(state)</span><br><span class="line">        <span class="built_in">console</span>.log(state.first)</span><br><span class="line">        <span class="built_in">console</span>.log(state.first.second)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">&lt;/script&gt;</span><br></pre></td></tr></table></figure><p>来看一下打印结果：</p><p><img src="https://pic.wjnba.top/img/202410/20241011105928.png" alt="在这里插入图片描述"><br>结果非常的明了了，只有第一层被 <code>Proxy</code> 处理了，也就是说只有修改第一层的值时，才会响应式更新，代码如下：</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">template</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">p</span>&gt;</span>&#123;&#123; state.a &#125;&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">p</span>&gt;</span>&#123;&#123; state.first.b &#125;&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">p</span>&gt;</span>&#123;&#123; state.first.second.c &#125;&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">button</span> @<span class="attr">click</span>=<span class="string">&quot;change1&quot;</span>&gt;</span>改变1<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">button</span> @<span class="attr">click</span>=<span class="string">&quot;change2&quot;</span>&gt;</span>改变2<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="javascript"></span></span><br><span class="line"><span class="javascript"><span class="keyword">import</span> &#123;shallowReactive&#125; <span class="keyword">from</span> <span class="string">&#x27;vue&#x27;</span></span></span><br><span class="line"><span class="javascript"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span></span><br><span class="line"><span class="javascript">    <span class="function"><span class="title">setup</span>(<span class="params"></span>)</span> &#123;</span></span><br><span class="line"><span class="javascript">        <span class="keyword">const</span> obj = &#123;</span></span><br><span class="line"><span class="javascript">          <span class="attr">a</span>: <span class="number">1</span>,</span></span><br><span class="line"><span class="javascript">          <span class="attr">first</span>: &#123;</span></span><br><span class="line"><span class="javascript">            <span class="attr">b</span>: <span class="number">2</span>,</span></span><br><span class="line"><span class="javascript">            <span class="attr">second</span>: &#123;</span></span><br><span class="line"><span class="javascript">              <span class="attr">c</span>: <span class="number">3</span></span></span><br><span class="line"><span class="javascript">            &#125;</span></span><br><span class="line"><span class="javascript">          &#125;</span></span><br><span class="line"><span class="javascript">        &#125;</span></span><br><span class="line"><span class="javascript">        </span></span><br><span class="line"><span class="javascript">        <span class="keyword">const</span> state = shallowReactive(obj)</span></span><br><span class="line"><span class="javascript">        </span></span><br><span class="line"><span class="javascript">        <span class="function"><span class="keyword">function</span> <span class="title">change1</span>(<span class="params"></span>) </span>&#123;</span></span><br><span class="line"><span class="javascript">          state.a = <span class="number">7</span></span></span><br><span class="line"><span class="javascript">        &#125;</span></span><br><span class="line"><span class="javascript"></span></span><br><span class="line"><span class="javascript">        <span class="function"><span class="keyword">function</span> <span class="title">change2</span>(<span class="params"></span>) </span>&#123;</span></span><br><span class="line"><span class="javascript">          state.first.b = <span class="number">8</span></span></span><br><span class="line"><span class="javascript">          state.first.second.c = <span class="number">9</span></span></span><br><span class="line"><span class="javascript">          <span class="built_in">console</span>.log(state);</span></span><br><span class="line"><span class="javascript">        &#125;</span></span><br><span class="line"><span class="javascript"></span></span><br><span class="line"><span class="javascript">        <span class="keyword">return</span> &#123;state&#125;</span></span><br><span class="line"><span class="javascript">    &#125;</span></span><br><span class="line"><span class="javascript">&#125;</span></span><br><span class="line"><span class="javascript"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure><p>来看一下具体过程：</p><p><img src="https://pic.wjnba.top/img/202410/20241011105931.gif" alt="在这里插入图片描述"><br>首先我们点击了第二个按钮，改变了第二层的 <code>b</code> 和第三层的 <code>c</code>，虽然值发生了改变，但是视图却没有进行更新；</p><p>当我们点击了第一个按钮，改变了第一层的 <code>a</code> 时，整个视图进行了更新；</p><p>由此可说明，<code>shallowReactive</code> 监听了第一层属性的值，一旦发生改变，则更新视图</p><h3 id="（8）shallowRef"><a href="#（8）shallowRef" class="headerlink" title="（8）shallowRef"></a>（8）shallowRef</h3><p>这是一个浅层的 <code>ref</code>，与 <code>shallowReactive</code> 一样是拿来做性能优化的</p><p><code>shallowReactive</code> 是监听对象第一层的数据变化用于驱动视图更新，那么 <code>shallowRef</code> 则是监听 <code>.value</code> 的值的变化来更新视图的</p><p>我们来看一下具体代码</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">template</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">p</span>&gt;</span>&#123;&#123; state.a &#125;&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">p</span>&gt;</span>&#123;&#123; state.first.b &#125;&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">p</span>&gt;</span>&#123;&#123; state.first.second.c &#125;&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">button</span> @<span class="attr">click</span>=<span class="string">&quot;change1&quot;</span>&gt;</span>改变1<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">button</span> @<span class="attr">click</span>=<span class="string">&quot;change2&quot;</span>&gt;</span>改变2<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="javascript"></span></span><br><span class="line"><span class="javascript"><span class="keyword">import</span> &#123;shallowRef&#125; <span class="keyword">from</span> <span class="string">&#x27;vue&#x27;</span></span></span><br><span class="line"><span class="javascript"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span></span><br><span class="line"><span class="javascript">    <span class="function"><span class="title">setup</span>(<span class="params"></span>)</span> &#123;</span></span><br><span class="line"><span class="javascript">        <span class="keyword">const</span> obj = &#123;</span></span><br><span class="line"><span class="javascript">          <span class="attr">a</span>: <span class="number">1</span>,</span></span><br><span class="line"><span class="javascript">          <span class="attr">first</span>: &#123;</span></span><br><span class="line"><span class="javascript">            <span class="attr">b</span>: <span class="number">2</span>,</span></span><br><span class="line"><span class="javascript">            <span class="attr">second</span>: &#123;</span></span><br><span class="line"><span class="javascript">              <span class="attr">c</span>: <span class="number">3</span></span></span><br><span class="line"><span class="javascript">            &#125;</span></span><br><span class="line"><span class="javascript">          &#125;</span></span><br><span class="line"><span class="javascript">        &#125;</span></span><br><span class="line"><span class="javascript">        </span></span><br><span class="line"><span class="javascript">        <span class="keyword">const</span> state = shallowRef(obj)</span></span><br><span class="line"><span class="javascript">        <span class="built_in">console</span>.log(state);</span></span><br><span class="line"><span class="javascript">        </span></span><br><span class="line"><span class="javascript">        <span class="function"><span class="keyword">function</span> <span class="title">change1</span>(<span class="params"></span>) </span>&#123;</span></span><br><span class="line"><span class="javascript">          <span class="comment">// 直接将state.value重新赋值</span></span></span><br><span class="line"><span class="javascript">          state.value = &#123;</span></span><br><span class="line"><span class="javascript">            <span class="attr">a</span>: <span class="number">7</span>,</span></span><br><span class="line"><span class="javascript">            <span class="attr">first</span>: &#123;</span></span><br><span class="line"><span class="javascript">              <span class="attr">b</span>: <span class="number">8</span>,</span></span><br><span class="line"><span class="javascript">              <span class="attr">second</span>: &#123;</span></span><br><span class="line"><span class="javascript">                <span class="attr">c</span>: <span class="number">9</span></span></span><br><span class="line"><span class="javascript">              &#125;</span></span><br><span class="line"><span class="javascript">            &#125;</span></span><br><span class="line"><span class="javascript">          &#125;</span></span><br><span class="line"><span class="javascript">        &#125;</span></span><br><span class="line"><span class="javascript"></span></span><br><span class="line"><span class="javascript">        <span class="function"><span class="keyword">function</span> <span class="title">change2</span>(<span class="params"></span>) </span>&#123;</span></span><br><span class="line"><span class="javascript">          state.value.first.b = <span class="number">8</span></span></span><br><span class="line"><span class="javascript">          state.value.first.second.c = <span class="number">9</span></span></span><br><span class="line"><span class="javascript">          <span class="built_in">console</span>.log(state);</span></span><br><span class="line"><span class="javascript">        &#125;</span></span><br><span class="line"><span class="javascript"></span></span><br><span class="line"><span class="javascript">              <span class="keyword">return</span> &#123;state, change1, change2&#125;</span></span><br><span class="line"><span class="javascript">    &#125;</span></span><br><span class="line"><span class="javascript">&#125;</span></span><br><span class="line"><span class="javascript"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure><p>首先看一下被 <code>shallowRef</code> 包装过后是怎样的结构</p><p><img src="https://pic.wjnba.top/img/202410/20241011105937.png" alt="在这里插入图片描述"><br>然后再来看看改变其值会有什么变化</p><p><img src="https://pic.wjnba.top/img/202410/20241011105947.gif" alt="在这里插入图片描述"><br>我们先点击了第二个按钮，发现数据确实被改变了，但是视图并没随之更新；</p><p>于是点击了第二个按钮，即将整个 <code>.value</code> 重新赋值了，视图就立马更新了</p><p>这么一看，未免也太过麻烦了，改个数据还要重新赋值，不要担心，此时我们可以用到另一个API，叫做 <code>triggerRef</code> ，调用它就可以立马更新视图，其接收一个参数 <code>state</code> ，即需要更新的 <code>ref</code> 对象</p><p>我们来使用一下</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">template</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">p</span>&gt;</span>&#123;&#123; state.a &#125;&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">p</span>&gt;</span>&#123;&#123; state.first.b &#125;&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">p</span>&gt;</span>&#123;&#123; state.first.second.c &#125;&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">button</span> @<span class="attr">click</span>=<span class="string">&quot;change&quot;</span>&gt;</span>改变<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="javascript"></span></span><br><span class="line"><span class="javascript"><span class="keyword">import</span> &#123;shallowRef, triggerRef&#125; <span class="keyword">from</span> <span class="string">&#x27;vue&#x27;</span></span></span><br><span class="line"><span class="javascript"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span></span><br><span class="line"><span class="javascript">    <span class="function"><span class="title">setup</span>(<span class="params"></span>)</span> &#123;</span></span><br><span class="line"><span class="javascript">        <span class="keyword">const</span> obj = &#123;</span></span><br><span class="line"><span class="javascript">          <span class="attr">a</span>: <span class="number">1</span>,</span></span><br><span class="line"><span class="javascript">          <span class="attr">first</span>: &#123;</span></span><br><span class="line"><span class="javascript">            <span class="attr">b</span>: <span class="number">2</span>,</span></span><br><span class="line"><span class="javascript">            <span class="attr">second</span>: &#123;</span></span><br><span class="line"><span class="javascript">              <span class="attr">c</span>: <span class="number">3</span></span></span><br><span class="line"><span class="javascript">            &#125;</span></span><br><span class="line"><span class="javascript">          &#125;</span></span><br><span class="line"><span class="javascript">        &#125;</span></span><br><span class="line"><span class="javascript">        </span></span><br><span class="line"><span class="javascript">        <span class="keyword">const</span> state = shallowRef(obj)</span></span><br><span class="line"><span class="javascript">        <span class="built_in">console</span>.log(state);</span></span><br><span class="line"><span class="javascript"></span></span><br><span class="line"><span class="javascript">        <span class="function"><span class="keyword">function</span> <span class="title">change</span>(<span class="params"></span>) </span>&#123;</span></span><br><span class="line"><span class="javascript">          state.value.first.b = <span class="number">8</span></span></span><br><span class="line"><span class="javascript">          state.value.first.second.c = <span class="number">9</span></span></span><br><span class="line"><span class="javascript">          <span class="comment">// 修改值后立即驱动视图更新</span></span></span><br><span class="line"><span class="javascript">          triggerRef(state)</span></span><br><span class="line"><span class="javascript">          <span class="built_in">console</span>.log(state);</span></span><br><span class="line"><span class="javascript">        &#125;</span></span><br><span class="line"><span class="javascript"></span></span><br><span class="line"><span class="javascript">              <span class="keyword">return</span> &#123;state, change&#125;</span></span><br><span class="line"><span class="javascript">    &#125;</span></span><br><span class="line"><span class="javascript">&#125;</span></span><br><span class="line"><span class="javascript"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure><p>我们来看一下具体过程</p><p><img src="https://pic.wjnba.top/img/202410/20241011110051.gif" alt="在这里插入图片描述"><br>可以看到，我们没有给 <code>.value</code> 重新赋值，只是在修改值后，调用了 <code>triggerRef</code> 就实现了视图的更新</p><h3 id="（9）toRaw"><a href="#（9）toRaw" class="headerlink" title="（9）toRaw"></a>（9）toRaw</h3><p><code>toRaw</code> 方法是用于获取 <code>ref</code> 或 <code>reactive</code> 对象的原始数据的</p><p>先来看一段代码</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">template</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">p</span>&gt;</span>&#123;&#123; state.name &#125;&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">p</span>&gt;</span>&#123;&#123; state.age &#125;&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">button</span> @<span class="attr">click</span>=<span class="string">&quot;change&quot;</span>&gt;</span>改变<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="javascript"></span></span><br><span class="line"><span class="javascript"><span class="keyword">import</span> &#123;reactive&#125; <span class="keyword">from</span> <span class="string">&#x27;vue&#x27;</span></span></span><br><span class="line"><span class="javascript"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span></span><br><span class="line"><span class="javascript">    <span class="function"><span class="title">setup</span>(<span class="params"></span>)</span> &#123;</span></span><br><span class="line"><span class="javascript">        <span class="keyword">const</span> obj = &#123;</span></span><br><span class="line"><span class="javascript">          <span class="attr">name</span>: <span class="string">&#x27;前端印象&#x27;</span>,</span></span><br><span class="line"><span class="javascript">          <span class="attr">age</span>: <span class="number">22</span></span></span><br><span class="line"><span class="javascript">        &#125;</span></span><br><span class="line"><span class="javascript"></span></span><br><span class="line"><span class="javascript">        <span class="keyword">const</span> state = reactive(obj)    </span></span><br><span class="line"><span class="javascript"></span></span><br><span class="line"><span class="javascript">        <span class="function"><span class="keyword">function</span> <span class="title">change</span>(<span class="params"></span>) </span>&#123;</span></span><br><span class="line"><span class="javascript">          state.age = <span class="number">90</span></span></span><br><span class="line"><span class="javascript">          <span class="built_in">console</span>.log(obj); <span class="comment">// 打印原始数据obj</span></span></span><br><span class="line"><span class="javascript">          <span class="built_in">console</span>.log(state);  <span class="comment">// 打印 reactive对象</span></span></span><br><span class="line"><span class="javascript">        &#125;</span></span><br><span class="line"><span class="javascript"></span></span><br><span class="line"><span class="javascript">        <span class="keyword">return</span> &#123;state, change&#125;</span></span><br><span class="line"><span class="javascript">    &#125;</span></span><br><span class="line"><span class="javascript">&#125;</span></span><br><span class="line"><span class="javascript"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure><p>来看看具体过程</p><p><img src="https://pic.wjnba.top/img/202410/20241011105955.gif" alt="在这里插入图片描述"><br>我们改变了 <code>reactive</code> 对象中的数据，于是看到原始数据 <code>obj</code> 和被 <code>reactive</code> 包装过的对象的值都发生了变化，由此我们可以看出，这两者是一个引用关系</p><p>那么此时我们就想了，那如果直接改变原始数据 <code>obj</code> 的值，会怎么样呢？答案是： <code>reactive</code> 的值也会跟着改变，但是视图不会更新</p><p>由此可见，当我们想修改数据，但不想让视图更新时，可以选择直接修改原始数据上的值，因此需要先获取到原始数据，我们可以使用 Vue3 提供的 <code>toRaw</code> 方法</p><p><code>toRaw</code> 接收一个参数，即 <code>ref</code> 对象或 <code>reactive</code> 对象</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">&lt;script&gt;</span><br><span class="line"><span class="keyword">import</span> &#123;reactive, toRaw&#125; <span class="keyword">from</span> <span class="string">&#x27;vue&#x27;</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span><br><span class="line">    <span class="function"><span class="title">setup</span>(<span class="params"></span>)</span> &#123;</span><br><span class="line">        <span class="keyword">const</span> obj = &#123;</span><br><span class="line">          <span class="attr">name</span>: <span class="string">&#x27;前端印象&#x27;</span>,</span><br><span class="line">          <span class="attr">age</span>: <span class="number">22</span></span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">const</span> state = reactive(obj)    </span><br><span class="line">        <span class="keyword">const</span> raw = toRaw(state)</span><br><span class="line"></span><br><span class="line">        <span class="built_in">console</span>.log(obj === raw)   <span class="comment">// true</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">&lt;/script&gt;</span><br></pre></td></tr></table></figure><p>上述代码就证明了 <code>toRaw</code> 方法从 <code>reactive</code> 对象中获取到的是原始数据，因此我们就可以很方便的通过修改原始数据的值而不更新视图来做一些性能优化了</p><blockquote><p><strong>注意：</strong> 补充一句，当 <code>toRaw</code> 方法接收的参数是 <code>ref</code> 对象时，需要加上 <code>.value</code> 才能获取到原始数据对象</p></blockquote><h3 id="（10）markRaw"><a href="#（10）markRaw" class="headerlink" title="（10）markRaw"></a>（10）markRaw</h3><p><code>markRaw</code> 方法可以将原始数据标记为非响应式的，即使用 <code>ref</code> 或 <code>reactive</code> 将其包装，扔无法实现数据响应式，其接收一个参数，即原始数据，并返回被标记后的数据</p><p>我们来看一下代码</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">template</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">p</span>&gt;</span>&#123;&#123; state.name &#125;&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">p</span>&gt;</span>&#123;&#123; state.age &#125;&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">button</span> @<span class="attr">click</span>=<span class="string">&quot;change&quot;</span>&gt;</span>改变<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="javascript"></span></span><br><span class="line"><span class="javascript"><span class="keyword">import</span> &#123;reactive, markRaw&#125; <span class="keyword">from</span> <span class="string">&#x27;vue&#x27;</span></span></span><br><span class="line"><span class="javascript"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span></span><br><span class="line"><span class="javascript">    <span class="function"><span class="title">setup</span>(<span class="params"></span>)</span> &#123;</span></span><br><span class="line"><span class="javascript">        <span class="keyword">const</span> obj = &#123;</span></span><br><span class="line"><span class="javascript">          <span class="attr">name</span>: <span class="string">&#x27;前端印象&#x27;</span>,</span></span><br><span class="line"><span class="javascript">          <span class="attr">age</span>: <span class="number">22</span></span></span><br><span class="line"><span class="javascript">        &#125;</span></span><br><span class="line"><span class="javascript">        <span class="comment">// 通过markRaw标记原始数据obj, 使其数据更新不再被追踪</span></span></span><br><span class="line"><span class="javascript">        <span class="keyword">const</span> raw = markRaw(obj)   </span></span><br><span class="line"><span class="javascript">        <span class="comment">// 试图用reactive包装raw, 使其变成响应式数据</span></span></span><br><span class="line"><span class="javascript">        <span class="keyword">const</span> state = reactive(raw)    </span></span><br><span class="line"><span class="javascript"></span></span><br><span class="line"><span class="javascript">        <span class="function"><span class="keyword">function</span> <span class="title">change</span>(<span class="params"></span>) </span>&#123;</span></span><br><span class="line"><span class="javascript">          state.age = <span class="number">90</span></span></span><br><span class="line"><span class="javascript">          <span class="built_in">console</span>.log(state);</span></span><br><span class="line"><span class="javascript">        &#125;</span></span><br><span class="line"><span class="javascript"></span></span><br><span class="line"><span class="javascript">        <span class="keyword">return</span> &#123;state, change&#125;</span></span><br><span class="line"><span class="javascript">    &#125;</span></span><br><span class="line"><span class="javascript">&#125;</span></span><br><span class="line"><span class="javascript"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure><p>我们来看一下在被 <code>markRaw</code> 方法处理过后的数据是否还能被 <code>reactive</code> 包装成响应式数据</p><p><img src="https://pic.wjnba.top/img/202410/20241011110000.gif" alt="在这里插入图片描述"><br>从图中可以看到，即使我们修改了值也不会更新视图了，即没有实现数据响应式</p><h3 id="（11）provide-amp-amp-inject"><a href="#（11）provide-amp-amp-inject" class="headerlink" title="（11）provide &amp;&amp; inject"></a>（11）provide &amp;&amp; inject</h3><p>与 Vue2中的 <code>provide</code> 和 <code>inject</code> 作用相同，只不过在Vue3中需要手动从 <code>vue</code> 中导入</p><p>这里简单说明一下这两个方法的作用：</p><ul><li><strong>provide</strong> ：向子组件以及子孙组件传递数据。接收两个参数，第一个参数是 <code>key</code>，即数据的名称；第二个参数为 <code>value</code>，即数据的值</li><li><strong>inject</strong> ：接收父组件或祖先组件传递过来的数据。接收一个参数 <code>key</code>，即父组件或祖先组件传递的数据名称</li></ul><p>假设这有三个组件，分别是 <code>A.vue</code> 、<code>B.vue</code> 、<code>C.vue</code>，其中 <code>B.vue</code> 是 <code>A.vue</code> 的子组件，<code>C.vue</code> 是 <code>B.vue</code> 的子组件</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line">// A.vue</span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="javascript"></span></span><br><span class="line"><span class="javascript"><span class="keyword">import</span> &#123;provide&#125; <span class="keyword">from</span> <span class="string">&#x27;vue&#x27;</span></span></span><br><span class="line"><span class="javascript"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span></span><br><span class="line"><span class="javascript">    <span class="function"><span class="title">setup</span>(<span class="params"></span>)</span> &#123;</span></span><br><span class="line"><span class="javascript">        <span class="keyword">const</span> obj= &#123;</span></span><br><span class="line"><span class="javascript">          <span class="attr">name</span>: <span class="string">&#x27;前端印象&#x27;</span>,</span></span><br><span class="line"><span class="javascript">          <span class="attr">age</span>: <span class="number">22</span></span></span><br><span class="line"><span class="javascript">        &#125;</span></span><br><span class="line"><span class="javascript"></span></span><br><span class="line"><span class="javascript">        <span class="comment">// 向子组件以及子孙组件传递名为info的数据</span></span></span><br><span class="line"><span class="javascript">        provide(<span class="string">&#x27;info&#x27;</span>, obj)</span></span><br><span class="line"><span class="javascript">    &#125;</span></span><br><span class="line"><span class="javascript">&#125;</span></span><br><span class="line"><span class="javascript"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"></span><br><span class="line">// B.vue</span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="javascript"></span></span><br><span class="line"><span class="javascript"><span class="keyword">import</span> &#123;inject&#125; <span class="keyword">from</span> <span class="string">&#x27;vue&#x27;</span></span></span><br><span class="line"><span class="javascript"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span></span><br><span class="line"><span class="javascript">    <span class="function"><span class="title">setup</span>(<span class="params"></span>)</span> &#123;    </span></span><br><span class="line"><span class="javascript">        <span class="comment">// 接收A.vue传递过来的数据</span></span></span><br><span class="line"><span class="javascript">        inject(<span class="string">&#x27;info&#x27;</span>)  <span class="comment">// &#123;name: &#x27;前端印象&#x27;, age: 22&#125;</span></span></span><br><span class="line"><span class="javascript">    &#125;</span></span><br><span class="line"><span class="javascript">&#125;</span></span><br><span class="line"><span class="javascript"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"></span><br><span class="line">// C.vue</span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="javascript"></span></span><br><span class="line"><span class="javascript"><span class="keyword">import</span> &#123;inject&#125; <span class="keyword">from</span> <span class="string">&#x27;vue&#x27;</span></span></span><br><span class="line"><span class="javascript"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span></span><br><span class="line"><span class="javascript">    <span class="function"><span class="title">setup</span>(<span class="params"></span>)</span> &#123;    </span></span><br><span class="line"><span class="javascript">        <span class="comment">// 接收A.vue传递过来的数据</span></span></span><br><span class="line"><span class="javascript">        inject(<span class="string">&#x27;info&#x27;</span>)  <span class="comment">// &#123;name: &#x27;前端印象&#x27;, age: 22&#125;</span></span></span><br><span class="line"><span class="javascript">    &#125;</span></span><br><span class="line"><span class="javascript">&#125;</span></span><br><span class="line"><span class="javascript"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure><h3 id="（12）watch-amp-amp-watchEffect"><a href="#（12）watch-amp-amp-watchEffect" class="headerlink" title="（12）watch &amp;&amp; watchEffect"></a>（12）watch &amp;&amp; watchEffect</h3><p><code>watch</code> 和 <code>watchEffect</code> 都是用来监视某项数据变化从而执行指定的操作的，但用法上还是有所区别</p><p><strong>watch</strong>：watch( source, cb, [options] )</p><p>参数说明：</p><ul><li>source：可以是表达式或函数，用于指定监听的依赖对象</li><li>cb：依赖对象变化后执行的回掉函数</li><li>options：可参数，可以配置的属性有 immediate（立即触发回调函数）、deep（深度监听）</li></ul><p>当监听 <code>ref</code> 类型时：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">&lt;script&gt;</span><br><span class="line"><span class="keyword">import</span> &#123;ref, watch&#125; <span class="keyword">from</span> <span class="string">&#x27;vue&#x27;</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span><br><span class="line">    <span class="function"><span class="title">setup</span>(<span class="params"></span>)</span> &#123;    </span><br><span class="line">        <span class="keyword">const</span> state = ref(<span class="number">0</span>)</span><br><span class="line"></span><br><span class="line">        watch(state, <span class="function">(<span class="params">newValue, oldValue</span>) =&gt;</span> &#123;</span><br><span class="line">          <span class="built_in">console</span>.log(<span class="string">`原值为<span class="subst">$&#123;oldValue&#125;</span>`</span>)</span><br><span class="line">          <span class="built_in">console</span>.log(<span class="string">`新值为<span class="subst">$&#123;newValue&#125;</span>`</span>)</span><br><span class="line">          <span class="comment">/* 1秒后打印结果：</span></span><br><span class="line"><span class="comment">                  原值为0</span></span><br><span class="line"><span class="comment">                  新值为1</span></span><br><span class="line"><span class="comment">          */</span></span><br><span class="line">        &#125;)</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 1秒后将state值+1</span></span><br><span class="line">        <span class="built_in">setTimeout</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">          state.value ++</span><br><span class="line">        &#125;, <span class="number">1000</span>)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">&lt;/script&gt;</span><br></pre></td></tr></table></figure><p>当监听 <code>reactive</code> 类型时：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">&lt;script&gt;</span><br><span class="line"><span class="keyword">import</span> &#123;reactive, watch&#125; <span class="keyword">from</span> <span class="string">&#x27;vue&#x27;</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span><br><span class="line">    <span class="function"><span class="title">setup</span>(<span class="params"></span>)</span> &#123;    </span><br><span class="line">        <span class="keyword">const</span> state = reactive(&#123;<span class="attr">count</span>: <span class="number">0</span>&#125;)</span><br><span class="line"></span><br><span class="line">        watch(<span class="function">() =&gt;</span> state.count, <span class="function">(<span class="params">newValue, oldValue</span>) =&gt;</span> &#123;</span><br><span class="line">          <span class="built_in">console</span>.log(<span class="string">`原值为<span class="subst">$&#123;oldValue&#125;</span>`</span>)</span><br><span class="line">          <span class="built_in">console</span>.log(<span class="string">`新值为<span class="subst">$&#123;newValue&#125;</span>`</span>)</span><br><span class="line">          <span class="comment">/* 1秒后打印结果：</span></span><br><span class="line"><span class="comment">                  原值为0</span></span><br><span class="line"><span class="comment">                  新值为1</span></span><br><span class="line"><span class="comment">          */</span></span><br><span class="line">        &#125;)</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 1秒后将state.count的值+1</span></span><br><span class="line">        <span class="built_in">setTimeout</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">          state.count ++</span><br><span class="line">        &#125;, <span class="number">1000</span>)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">&lt;/script&gt;</span><br></pre></td></tr></table></figure><p>当同时监听多个值时：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line">&lt;script&gt;</span><br><span class="line"><span class="keyword">import</span> &#123;reactive, watch&#125; <span class="keyword">from</span> <span class="string">&#x27;vue&#x27;</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span><br><span class="line">    <span class="function"><span class="title">setup</span>(<span class="params"></span>)</span> &#123;    </span><br><span class="line">        <span class="keyword">const</span> state = reactive(&#123; <span class="attr">count</span>: <span class="number">0</span>, <span class="attr">name</span>: <span class="string">&#x27;zs&#x27;</span> &#125;)</span><br><span class="line"></span><br><span class="line">         watch(</span><br><span class="line">            [<span class="function">() =&gt;</span> state.count, <span class="function">() =&gt;</span> state.name], </span><br><span class="line">            <span class="function">(<span class="params">[newCount, newName], [oldvCount, oldvName]</span>) =&gt;</span> &#123;</span><br><span class="line">              <span class="built_in">console</span>.log(oldvCount) <span class="comment">// 旧的 count 值</span></span><br><span class="line">              <span class="built_in">console</span>.log(newCount) <span class="comment">// 新的 count 值</span></span><br><span class="line">              <span class="built_in">console</span>.log(oldName) <span class="comment">// 旧的 name 值</span></span><br><span class="line">              <span class="built_in">console</span>.log(newvName) <span class="comment">// 新的 name 值</span></span><br><span class="line">            &#125;</span><br><span class="line">          )</span><br><span class="line"></span><br><span class="line">          <span class="built_in">setTimeout</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">            state.count ++</span><br><span class="line">            state.name = <span class="string">&#x27;ls&#x27;</span></span><br><span class="line">          &#125;, <span class="number">1000</span>)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">&lt;/script&gt;</span><br></pre></td></tr></table></figure><p>因为 <code>watch</code> 方法的第一个参数我们已经指定了监听的对象，因此当组件初始化时，不会执行第二个参数中的回调函数，若我们想让其初始化时就先执行一遍，可以在第三个参数对象中设置 <code>immediate: true</code></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">watch` 方法默认是渐层的监听我们指定的数据，例如如果监听的数据有多层嵌套，深层的数据变化不会触发监听的回调，若我们想要其对深层数据也进行监听，可以在第三个参数对象中设置 `deep: true</span><br></pre></td></tr></table></figure><blockquote><p><strong>补充：</strong> watch方法会返回一个stop方法，若想要停止监听，便可直接执行该stop函数</p></blockquote><hr><p>接下来再来聊聊 <code>watchEffect</code>，它与 <code>watch</code> 的区别主要有以下几点：</p><ol><li>不需要手动传入依赖</li><li>每次初始化时会执行一次回调函数来自动获取依赖</li><li>无法获取到原值，只能得到变化后的值</li></ol><p>来看一下该方法如何使用：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line">&lt;script&gt;</span><br><span class="line"><span class="keyword">import</span> &#123;reactive, watchEffect&#125; <span class="keyword">from</span> <span class="string">&#x27;vue&#x27;</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span><br><span class="line">    <span class="function"><span class="title">setup</span>(<span class="params"></span>)</span> &#123;    </span><br><span class="line">          <span class="keyword">const</span> state = reactive(&#123; <span class="attr">count</span>: <span class="number">0</span>, <span class="attr">name</span>: <span class="string">&#x27;zs&#x27;</span> &#125;)</span><br><span class="line"></span><br><span class="line">          watchEffect(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">          <span class="built_in">console</span>.log(state.count)</span><br><span class="line">          <span class="built_in">console</span>.log(state.name)</span><br><span class="line">          <span class="comment">/*  初始化时打印：</span></span><br><span class="line"><span class="comment">                  0</span></span><br><span class="line"><span class="comment">                  zs</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">            1秒后打印：</span></span><br><span class="line"><span class="comment">                  1</span></span><br><span class="line"><span class="comment">                  ls</span></span><br><span class="line"><span class="comment">          */</span></span><br><span class="line">          &#125;)</span><br><span class="line"></span><br><span class="line">          <span class="built_in">setTimeout</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">            state.count ++</span><br><span class="line">            state.name = <span class="string">&#x27;ls&#x27;</span></span><br><span class="line">          &#125;, <span class="number">1000</span>)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">&lt;/script&gt;</span><br></pre></td></tr></table></figure><p>从上述代码中可以看出，我们并没有像 <code>watch</code> 方法一样先给其传入一个依赖，而是直接指定了一个回调函数</p><p>当组件初始化时，将该回调函数执行一次，自动获取到需要检测的数据是 <code>state.count</code> 和 <code>state.name</code></p><p>根据以上特征，我们可以自行选择使用哪一个监听器</p><h3 id="（13）getCurrentInstance"><a href="#（13）getCurrentInstance" class="headerlink" title="（13）getCurrentInstance"></a>（13）getCurrentInstance</h3><p>我们都知道在Vue2的任何一个组件中想要获取当前组件的实例可以通过 <code>this</code> 来得到，而在Vue3中我们大量的代码都在 <code>setup</code> 函数中运行，并且在该函数中 <code>this</code> 指向的是 <code>undefined</code>，那么该如何获取到当前组件的实例呢？</p><p>这时可以用到另一个方法，即 <code>getCurrentInstance</code></p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">template</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">p</span>&gt;</span>&#123;&#123; num &#125;&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="javascript"></span></span><br><span class="line"><span class="javascript"><span class="keyword">import</span> &#123;ref, getCurrentInstance&#125; <span class="keyword">from</span> <span class="string">&#x27;vue&#x27;</span></span></span><br><span class="line"><span class="javascript"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span></span><br><span class="line"><span class="javascript">    <span class="function"><span class="title">setup</span>(<span class="params"></span>)</span> &#123;    </span></span><br><span class="line"><span class="javascript">        <span class="keyword">const</span> num = ref(<span class="number">3</span>)</span></span><br><span class="line"><span class="javascript">        <span class="keyword">const</span> instance = getCurrentInstance()</span></span><br><span class="line"><span class="javascript">        <span class="built_in">console</span>.log(instance)</span></span><br><span class="line"><span class="javascript"></span></span><br><span class="line"><span class="javascript">        <span class="keyword">return</span> &#123;num&#125;</span></span><br><span class="line"><span class="javascript">    &#125;</span></span><br><span class="line"><span class="javascript">&#125;</span></span><br><span class="line"><span class="javascript"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure><p>我们来看一下其打印结果</p><p><img src="https://pic.wjnba.top/img/202410/20241011110015.png" alt="在这里插入图片描述"><br>因为 <code>instance</code> 包含的内容太多，所以没截完整，但是主要的内容都在图上了，我们重点来看一下 <code>ctx</code> 和 <code>proxy</code>，因为这两个才是我们想要的 <code>this</code> 的内容</p><p><img src="https://pic.wjnba.top/img/202410/20241011110026.png" alt="在这里插入图片描述"><br><img src="https://pic.wjnba.top/img/202410/20241011110031.png" alt="在这里插入图片描述"><br>可以看到 <code>ctx</code> 和 <code>proxy</code> 的内容十分类似，只是后者相对于前者外部包装了一层 <code>proxy</code>，由此可说明 <code>proxy</code> 是响应式的</p><h3 id="（14）useStore"><a href="#（14）useStore" class="headerlink" title="（14）useStore"></a>（14）useStore</h3><p>在Vue2中使用 Vuex，我们都是通过 <code>this.$store</code> 来与获取到Vuex实例，但上一部分说了原本Vue2中的 <code>this</code> 的获取方式不一样了，并且我们在Vue3的 <code>getCurrentInstance().ctx</code> 中也没有发现 <code>$store</code> 这个属性，那么如何获取到Vuex实例呢？这就要通过 <code>vuex</code> 中的一个方法了，即 <code>useStore</code></p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// store 文件夹下的 index.js</span></span><br><span class="line"><span class="keyword">import</span> Vuex <span class="keyword">from</span> <span class="string">&#x27;vuex&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> store = Vuex.createStore(&#123;</span><br><span class="line">    <span class="attr">state</span>: &#123;</span><br><span class="line">      <span class="attr">name</span>: <span class="string">&#x27;前端印象&#x27;</span>,</span><br><span class="line">      <span class="attr">age</span>: <span class="number">22</span></span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="attr">mutations</span>: &#123;</span><br><span class="line">      ……</span><br><span class="line">    &#125;,</span><br><span class="line">    ……</span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line"><span class="comment">// example.vue</span></span><br><span class="line">&lt;script&gt;</span><br><span class="line"><span class="comment">// 从 vuex 中导入 useStore 方法</span></span><br><span class="line"><span class="keyword">import</span> &#123;useStore&#125; <span class="keyword">from</span> <span class="string">&#x27;vuex&#x27;</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span><br><span class="line">    <span class="function"><span class="title">setup</span>(<span class="params"></span>)</span> &#123;    </span><br><span class="line">        <span class="comment">// 获取 vuex 实例</span></span><br><span class="line">        <span class="keyword">const</span> store = useStore()</span><br><span class="line"></span><br><span class="line">        <span class="built_in">console</span>.log(store)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">&lt;/script&gt;</span><br></pre></td></tr></table></figure><p>我们来看一下打印结果</p><p><img src="https://pic.wjnba.top/img/202410/20241011110039.png" alt="在这里插入图片描述"><br>然后接下来就可以像之前一样正常使用 <code>vuex</code> 了</p><h3 id="（15）获取标签元素"><a href="#（15）获取标签元素" class="headerlink" title="（15）获取标签元素"></a>（15）获取标签元素</h3><p>最后再补充一个 <code>ref</code> 另外的作用，那就是可以获取到标签元素或组件</p><p>在Vue2中，我们获取元素都是通过给元素一个 <code>ref</code> 属性，然后通过 <code>this.$refs.xx</code> 来访问的，但这在Vue3中已经不再适用了</p><p>接下来看看Vue3中是如何获取元素的吧</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">template</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">ref</span>=<span class="string">&quot;el&quot;</span>&gt;</span>div元素<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="javascript"></span></span><br><span class="line"><span class="javascript"><span class="keyword">import</span> &#123; ref, onMounted &#125; <span class="keyword">from</span> <span class="string">&#x27;vue&#x27;</span></span></span><br><span class="line"><span class="javascript"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span></span><br><span class="line"><span class="javascript">  <span class="function"><span class="title">setup</span>(<span class="params"></span>)</span> &#123;</span></span><br><span class="line"><span class="javascript">    <span class="comment">// 创建一个DOM引用，名称必须与元素的ref属性名相同</span></span></span><br><span class="line"><span class="javascript">    <span class="keyword">const</span> el = ref(<span class="literal">null</span>)</span></span><br><span class="line"><span class="javascript"></span></span><br><span class="line"><span class="javascript">    <span class="comment">// 在挂载后才能通过 el 获取到目标元素</span></span></span><br><span class="line"><span class="javascript">    onMounted(<span class="function">() =&gt;</span> &#123;</span></span><br><span class="line"><span class="javascript">      el.value.innerHTML = <span class="string">&#x27;内容被修改&#x27;</span></span></span><br><span class="line"><span class="javascript">    &#125;)</span></span><br><span class="line"><span class="javascript"></span></span><br><span class="line"><span class="javascript">    <span class="comment">// 把创建的引用 return 出去</span></span></span><br><span class="line"><span class="javascript">    <span class="keyword">return</span> &#123;el&#125;</span></span><br><span class="line"><span class="javascript">  &#125;</span></span><br><span class="line"><span class="javascript">&#125;</span></span><br><span class="line"><span class="javascript"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure><p>获取元素的操作一共分为以下几个步骤：</p><ol><li>先给目标元素的 <code>ref</code> 属性设置一个值，假设为 <code>el</code></li><li>然后在 <code>setup</code> 函数中调用 <code>ref</code> 函数，值为 <code>null</code>，并赋值给变量 <code>el</code>，这里要注意，该变量名必须与我们给元素设置的 <code>ref</code> 属性名相同</li><li>把对元素的引用变量 <code>el</code> 返回（return）出去</li></ol><blockquote><p><strong>补充</strong>：设置的元素引用变量只有在组件挂载后才能访问到，因此在挂载前对元素进行操作都是无效的</p></blockquote><p>当然如果我们引用的是一个组件元素，那么获得的将是该组件的实例对象，这里就不做过多的演示了</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;&lt;img src=&quot;https://pic.wjnba.top/img/202406/20240617110657.webp&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Vue2每次都把整个Vue导入，例如Vue2的 &lt;code&gt;main.js&lt;/code&gt; 文件中的代码&lt;/p&gt;
&lt;f</summary>
      
    
    
    
    <category term="vue3" scheme="https://www.wjnba.top/categories/vue3/"/>
    
    
    <category term="vue" scheme="https://www.wjnba.top/tags/vue/"/>
    
  </entry>
  
  <entry>
    <title>vue3知识整理</title>
    <link href="https://www.wjnba.top/articles/2024061746f272d2cf71.html"/>
    <id>https://www.wjnba.top/articles/2024061746f272d2cf71.html</id>
    <published>2024-06-17T02:42:22.000Z</published>
    <updated>2025-12-15T03:40:53.439Z</updated>
    
    <content type="html"><![CDATA[<h2 id="Vue3"><a href="#Vue3" class="headerlink" title="Vue3"></a>Vue3</h2><p><img src="https://pic.wjnba.top/img/202406/20240617110657.webp" alt=""></p><h3 id="1-Vue3-简介"><a href="#1-Vue3-简介" class="headerlink" title="1.Vue3 简介"></a>1.Vue3 简介</h3><ul><li>2020 年 9 月 18 日，Vue.js 发布 3.0 版本，代号：One Piece（海贼王）</li><li>耗时 2 年多、<a href="https://github.com/vuejs/vue-next/graphs/commit-activity">2600+次提交</a>、<a href="https://github.com/vuejs/rfcs/tree/master/active-rfcs">30+个 RFC</a>、<a href="https://github.com/vuejs/vue-next/pulls?q=is%3Apr+is%3Amerged+-author%3Aapp%2Fdependabot-preview+">600+次 PR</a>、<a href="https://github.com/vuejs/vue-next/graphs/contributors">99 位贡献者</a></li><li>github 上的 tags 地址：<a href="https://github.com/vuejs/vue-next/releases/tag/v3.0.0">https://github.com/vuejs/vue-next/releases/tag/v3.0.0</a></li></ul><h3 id="2-Vue3-带来了什么"><a href="#2-Vue3-带来了什么" class="headerlink" title="2.Vue3 带来了什么"></a>2.Vue3 带来了什么</h3><h4 id="1-性能的提升"><a href="#1-性能的提升" class="headerlink" title="1.性能的提升"></a>1.性能的提升</h4><ul><li><p>打包大小减少 41%</p></li><li><p>初次渲染快 55%, 更新渲染快 133%</p></li><li><p>内存减少 54%</p><p>…</p></li></ul><h4 id="2-源码的升级"><a href="#2-源码的升级" class="headerlink" title="2.源码的升级"></a>2.源码的升级</h4><ul><li><p>使用 Proxy 代替 defineProperty 实现响应式</p></li><li><p>重写虚拟 DOM 的实现和 Tree-Shaking</p><p>…</p></li></ul><h4 id="3-拥抱-TypeScript"><a href="#3-拥抱-TypeScript" class="headerlink" title="3.拥抱 TypeScript"></a>3.拥抱 TypeScript</h4><ul><li>Vue3 可以更好的支持 TypeScript</li></ul><h4 id="4-新的特性"><a href="#4-新的特性" class="headerlink" title="4.新的特性"></a>4.新的特性</h4><ol><li>Composition API（组合 API）<ul><li>setup 配置</li><li>ref 与 reactive</li><li>watch 与 watchEffect</li><li>provide 与 inject</li><li>…</li></ul></li><li>新的内置组件<ul><li>Fragment</li><li>Teleport</li><li>Suspense</li></ul></li><li>其他改变<ul><li>新的生命周期钩子</li><li>data 选项应始终被声明为一个函数</li><li>移除 keyCode 支持作为 v-on 的修饰符</li><li>…</li></ul></li></ol><h2 id="一、创建-Vue3-0-工程"><a href="#一、创建-Vue3-0-工程" class="headerlink" title="一、创建 Vue3.0 工程"></a>一、创建 Vue3.0 工程</h2><h3 id="1-使用-vue-cli-创建"><a href="#1-使用-vue-cli-创建" class="headerlink" title="1.使用 vue-cli 创建"></a>1.使用 vue-cli 创建</h3><p>官方文档：<a href="https://cli.vuejs.org/zh/guide/creating-a-project.html#vue-create">https://cli.vuejs.org/zh/guide/creating-a-project.html#vue-create</a></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">## 查看@vue/cli版本，确保@vue/cli版本在4.5.0以上</span></span><br><span class="line">vue --version</span><br><span class="line"><span class="comment">## 安装或者升级你的@vue/cli</span></span><br><span class="line">npm install -g @vue/cli</span><br><span class="line"><span class="comment">## 创建</span></span><br><span class="line">vue create vue_test</span><br><span class="line"><span class="comment">## 启动</span></span><br><span class="line"><span class="built_in">cd</span> vue_test</span><br><span class="line">npm run serve</span><br></pre></td></tr></table></figure><h3 id="2-使用-vite-创建"><a href="#2-使用-vite-创建" class="headerlink" title="2.使用 vite 创建"></a>2.使用 vite 创建</h3><p>官方文档：<a href="https://v3.cn.vuejs.org/guide/installation.html#vite">https://v3.cn.vuejs.org/guide/installation.html#vite</a></p><p>vite 官网：<a href="https://vitejs.cn/">https://vitejs.cn</a></p><ul><li>什么是 vite？—— 新一代前端构建工具。</li><li>优势如下：<ul><li>开发环境中，无需打包操作，可快速的冷启动。</li><li>轻量快速的热重载（HMR）。</li><li>真正的按需编译，不再等待整个应用编译完成。</li></ul></li><li>传统构建 与 vite 构建对比图</li></ul><p><img src="https://pic.wjnba.top/img/202406/20240617111059.webp" alt=""></p><p><img src="https://pic.wjnba.top/img/202406/20240617111248.webp" alt=""></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">## 创建工程</span></span><br><span class="line">npm init vite-app &lt;project-name&gt;</span><br><span class="line"><span class="comment">## 进入工程目录</span></span><br><span class="line"><span class="built_in">cd</span> &lt;project-name&gt;</span><br><span class="line"><span class="comment">## 安装依赖</span></span><br><span class="line">npm install</span><br><span class="line"><span class="comment">## 运行</span></span><br><span class="line">npm run dev</span><br></pre></td></tr></table></figure><h2 id="二、常用-Composition-API"><a href="#二、常用-Composition-API" class="headerlink" title="二、常用 Composition API"></a>二、常用 Composition API</h2><p>官方文档: <a href="https://v3.cn.vuejs.org/guide/composition-api-introduction.html">https://v3.cn.vuejs.org/guide/composition-api-introduction.html</a></p><h3 id="1-拉开序幕的-setup"><a href="#1-拉开序幕的-setup" class="headerlink" title="1.拉开序幕的 setup"></a>1.拉开序幕的 setup</h3><ol><li>理解：Vue3.0 中一个新的配置项，值为一个函数。</li><li>setup 是所有<strong>Composition API（组合 API）</strong>“ 表演的舞台 ”。</li><li>组件中所用到的：数据、方法等等，均要配置在 setup 中。</li><li>setup 函数的两种返回值：<ol><li>若返回一个对象，则对象中的属性、方法, 在模板中均可以直接使用。（重点关注！）</li><li>若返回一个渲染函数：则可以自定义渲染内容。（了解）</li></ol></li><li>注意点：<ol><li>尽量不要与 Vue2.x 配置混用<ul><li>Vue2.x 配置（data、methods、computed…）中<strong>可以访问到</strong>setup 中的属性、方法。</li><li>但在 setup 中<strong>不能访问到</strong>Vue2.x 配置（data、methods、computed…）。</li><li>如果有重名, setup 优先。</li></ul></li><li>setup 不能是一个 async 函数，因为返回值不再是 return 的对象, 而是 promise, 模板看不到 return 对象中的属性。（后期也可以返回一个 Promise 实例，但需要 Suspense 和异步组件的配合）</li></ol></li></ol><h3 id="2-ref-函数"><a href="#2-ref-函数" class="headerlink" title="2.ref 函数"></a>2.ref 函数</h3><ul><li>作用: 定义一个响应式的数据</li><li>语法: <code>const xxx = ref(initValue)</code><ul><li>创建一个包含响应式数据的<strong>引用对象（reference 对象，简称 ref 对象）</strong>。</li><li>JS 中操作数据： <code>xxx.value</code></li><li>模板中读取数据: 不需要.value，直接：<code>&lt;div&gt;&#123;&#123;xxx&#125;&#125;&lt;/div&gt;</code></li></ul></li><li>备注：<ul><li>接收的数据可以是：基本类型、也可以是对象类型。</li><li>基本类型的数据：响应式依然是靠<code>Object.defineProperty()</code>的<code>get</code>与<code>set</code>完成的。</li><li>对象类型的数据：内部 <em>“ 求助 ”</em> 了 Vue3.0 中的一个新函数—— <code>reactive</code>函数。</li></ul></li></ul><h3 id="3-reactive-函数"><a href="#3-reactive-函数" class="headerlink" title="3.reactive 函数"></a>3.reactive 函数</h3><ul><li>作用: 定义一个<strong>对象类型</strong>的响应式数据（基本类型不要用它，要用<code>ref</code>函数）</li><li>语法：<code>const 代理对象= reactive(源对象)</code>接收一个对象（或数组），返回一个<strong>代理对象（Proxy 的实例对象，简称 proxy 对象）</strong></li><li>reactive 定义的响应式数据是“深层次的”。</li><li>内部基于 ES6 的 Proxy 实现，通过代理对象操作源对象内部数据进行操作。</li></ul><h3 id="4-Vue3-0-中的响应式原理"><a href="#4-Vue3-0-中的响应式原理" class="headerlink" title="4.Vue3.0 中的响应式原理"></a>4.Vue3.0 中的响应式原理</h3><h4 id="vue2-x-的响应式"><a href="#vue2-x-的响应式" class="headerlink" title="vue2.x 的响应式"></a>vue2.x 的响应式</h4><ul><li><p>实现原理：</p><ul><li><p>对象类型：通过<code>Object.defineProperty()</code>对属性的读取、修改进行拦截（数据劫持）。</p></li><li><p>数组类型：通过重写更新数组的一系列方法来实现拦截。（对数组的变更方法进行了包裹）。</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">Object</span>.defineProperty(data, <span class="string">&quot;count&quot;</span>, &#123;</span><br><span class="line">  <span class="function"><span class="title">get</span>(<span class="params"></span>)</span> &#123;&#125;,</span><br><span class="line">  <span class="function"><span class="title">set</span>(<span class="params"></span>)</span> &#123;&#125;,</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure></li></ul></li><li><p>存在问题：</p><ul><li>新增属性、删除属性, 界面不会更新。</li><li>直接通过下标修改数组, 界面不会自动更新。</li></ul></li></ul><h4 id="Vue3-0-的响应式"><a href="#Vue3-0-的响应式" class="headerlink" title="Vue3.0 的响应式"></a>Vue3.0 的响应式</h4><ul><li><p>实现原理:</p><ul><li><p>通过 Proxy（代理）: 拦截对象中任意属性的变化，包括：属性值的读写、属性的添加、属性的删除等。</p></li><li><p>通过 Reflect（反射）: 对源对象的属性进行操作。</p><ul><li><p>MDN 文档中描述的 Proxy 与 Reflect：</p><ul><li>Proxy：<a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Proxy">https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Proxy</a></li><li>Reflect：<a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Reflect">https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Reflect</a></li></ul><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">new</span> <span class="built_in">Proxy</span>(data, &#123;</span><br><span class="line">  <span class="comment">// 拦截读取属性值</span></span><br><span class="line">  <span class="function"><span class="title">get</span>(<span class="params">target, prop</span>)</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="built_in">Reflect</span>.get(target, prop);</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="comment">// 拦截设置属性值或添加新属性</span></span><br><span class="line">  <span class="function"><span class="title">set</span>(<span class="params">target, prop, value</span>)</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="built_in">Reflect</span>.set(target, prop, value);</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="comment">// 拦截删除属性</span></span><br><span class="line">  <span class="function"><span class="title">deleteProperty</span>(<span class="params">target, prop</span>)</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="built_in">Reflect</span>.deleteProperty(target, prop);</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line">proxy.name = <span class="string">&quot;tom&quot;</span>;</span><br></pre></td></tr></table></figure></li></ul></li></ul></li></ul><h3 id="5-reactive-对比-ref"><a href="#5-reactive-对比-ref" class="headerlink" title="5.reactive 对比 ref"></a>5.reactive 对比 ref</h3><ul><li>从定义数据角度对比：<ul><li>ref 用来定义：<strong>基本类型数据</strong>。</li><li>reactive 用来定义：<strong>对象（或数组）类型数据</strong>。</li><li>备注：ref 也可以用来定义<strong>对象（或数组）类型数据</strong>, 它内部会自动通过<code>reactive</code>转为<strong>代理对象</strong>。</li></ul></li><li>从原理角度对比：<ul><li>ref 通过<code>Object.defineProperty()</code>的<code>get</code>与<code>set</code>来实现响应式（数据劫持）。</li><li>reactive 通过使用<strong>Proxy</strong>来实现响应式（数据劫持）, 并通过<strong>Reflect</strong>操作<strong>源对象</strong>内部的数据。</li></ul></li><li>从使用角度对比：<ul><li>ref 定义的数据：操作数据<strong>需要</strong><code>.value</code>，读取数据时模板中直接读取<strong>不需要</strong><code>.value</code>。</li><li>reactive 定义的数据：操作数据与读取数据：<strong>均不需要</strong><code>.value</code>。</li></ul></li></ul><h3 id="6-setup-的两个注意点"><a href="#6-setup-的两个注意点" class="headerlink" title="6.setup 的两个注意点"></a>6.setup 的两个注意点</h3><ul><li>setup 执行的时机<ul><li>在 beforeCreate 之前执行一次，this 是 undefined。</li></ul></li><li>setup 的参数<ul><li>props：值为对象，包含：组件外部传递过来，且组件内部声明接收了的属性。</li><li>context：上下文对象<ul><li>attrs: 值为对象，包含：组件外部传递过来，但没有在 props 配置中声明的属性, 相当于 <code>this.$attrs</code>。</li><li>slots: 收到的插槽内容, 相当于 <code>this.$slots</code>。</li><li>emit: 分发自定义事件的函数, 相当于 <code>this.$emit</code>。</li></ul></li></ul></li></ul><h3 id="7-计算属性与监视"><a href="#7-计算属性与监视" class="headerlink" title="7.计算属性与监视"></a>7.计算属性与监视</h3><h4 id="1-computed-函数"><a href="#1-computed-函数" class="headerlink" title="1.computed 函数"></a>1.computed 函数</h4><ul><li><p>与 Vue2.x 中 computed 配置功能一致</p></li><li><p>写法</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123;computed&#125; <span class="keyword">from</span> <span class="string">&#x27;vue&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="title">setup</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">    ...</span><br><span class="line">    <span class="comment">//计算属性——简写</span></span><br><span class="line">    <span class="keyword">let</span> fullName = computed(<span class="function">()=&gt;</span>&#123;</span><br><span class="line">        <span class="keyword">return</span> person.firstName + <span class="string">&#x27;-&#x27;</span> + person.lastName</span><br><span class="line">    &#125;)</span><br><span class="line">    <span class="comment">//计算属性——完整</span></span><br><span class="line">    <span class="keyword">let</span> fullName = computed(&#123;</span><br><span class="line">        <span class="function"><span class="title">get</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">            <span class="keyword">return</span> person.firstName + <span class="string">&#x27;-&#x27;</span> + person.lastName</span><br><span class="line">        &#125;,</span><br><span class="line">        <span class="function"><span class="title">set</span>(<span class="params">value</span>)</span>&#123;</span><br><span class="line">            <span class="keyword">const</span> nameArr = value.split(<span class="string">&#x27;-&#x27;</span>)</span><br><span class="line">            person.firstName = nameArr[<span class="number">0</span>]</span><br><span class="line">            person.lastName = nameArr[<span class="number">1</span>]</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li></ul><h4 id="2-watch-函数"><a href="#2-watch-函数" class="headerlink" title="2.watch 函数"></a>2.watch 函数</h4><ul><li><p>与 Vue2.x 中 watch 配置功能一致</p></li><li><p>两个小“坑”：</p><ul><li>监视 reactive 定义的响应式数据时：oldValue 无法正确获取、强制开启了深度监视（deep 配置失效）。</li><li>监视 reactive 定义的响应式数据中某个属性时：deep 配置有效。</li></ul><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment">//情况一：监视ref定义的响应式数据</span></span><br><span class="line">watch(</span><br><span class="line">  sum,</span><br><span class="line">  <span class="function">(<span class="params">newValue, oldValue</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&quot;sum变化了&quot;</span>, newValue, oldValue);</span><br><span class="line">  &#125;,</span><br><span class="line">  &#123; <span class="attr">immediate</span>: <span class="literal">true</span> &#125;</span><br><span class="line">);</span><br><span class="line"></span><br><span class="line"><span class="comment">//情况二：监视多个ref定义的响应式数据</span></span><br><span class="line">watch([sum, msg], <span class="function">(<span class="params">newValue, oldValue</span>) =&gt;</span> &#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">&quot;sum或msg变化了&quot;</span>, newValue, oldValue);</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="comment">/* 情况三：监视reactive定义的响应式数据</span></span><br><span class="line"><span class="comment">若watch监视的是reactive定义的响应式数据，则无法正确获得oldValue！！</span></span><br><span class="line"><span class="comment">若watch监视的是reactive定义的响应式数据，则强制开启了深度监视 </span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line">watch(</span><br><span class="line">  person,</span><br><span class="line">  <span class="function">(<span class="params">newValue, oldValue</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&quot;person变化了&quot;</span>, newValue, oldValue);</span><br><span class="line">  &#125;,</span><br><span class="line">  &#123; <span class="attr">immediate</span>: <span class="literal">true</span>, <span class="attr">deep</span>: <span class="literal">false</span> &#125;</span><br><span class="line">); <span class="comment">//此处的deep配置不再奏效</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//情况四：监视reactive定义的响应式数据中的某个属性</span></span><br><span class="line">watch(</span><br><span class="line">  <span class="function">() =&gt;</span> person.job,</span><br><span class="line">  <span class="function">(<span class="params">newValue, oldValue</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&quot;person的job变化了&quot;</span>, newValue, oldValue);</span><br><span class="line">  &#125;,</span><br><span class="line">  &#123; <span class="attr">immediate</span>: <span class="literal">true</span>, <span class="attr">deep</span>: <span class="literal">true</span> &#125;</span><br><span class="line">);</span><br><span class="line"></span><br><span class="line"><span class="comment">//情况五：监视reactive定义的响应式数据中的某些属性</span></span><br><span class="line">watch(</span><br><span class="line">  [<span class="function">() =&gt;</span> person.job, <span class="function">() =&gt;</span> person.name],</span><br><span class="line">  <span class="function">(<span class="params">newValue, oldValue</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&quot;person的job变化了&quot;</span>, newValue, oldValue);</span><br><span class="line">  &#125;,</span><br><span class="line">  &#123; <span class="attr">immediate</span>: <span class="literal">true</span>, <span class="attr">deep</span>: <span class="literal">true</span> &#125;</span><br><span class="line">);</span><br><span class="line"></span><br><span class="line"><span class="comment">//特殊情况</span></span><br><span class="line">watch(</span><br><span class="line">  <span class="function">() =&gt;</span> person.job,</span><br><span class="line">  <span class="function">(<span class="params">newValue, oldValue</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&quot;person的job变化了&quot;</span>, newValue, oldValue);</span><br><span class="line">  &#125;,</span><br><span class="line">  &#123; <span class="attr">deep</span>: <span class="literal">true</span> &#125;</span><br><span class="line">); <span class="comment">//此处由于监视的是reactive素定义的对象中的某个属性，所以deep配置有效</span></span><br></pre></td></tr></table></figure></li></ul><h4 id="3-watchEffect-函数"><a href="#3-watchEffect-函数" class="headerlink" title="3.watchEffect 函数"></a>3.watchEffect 函数</h4><ul><li><p>watch 的套路是：既要指明监视的属性，也要指明监视的回调。</p></li><li><p>watchEffect 的套路是：不用指明监视哪个属性，监视的回调中用到哪个属性，那就监视哪个属性。</p></li><li><p>watchEffect 有点像 computed：</p><ul><li>但 computed 注重的计算出来的值（回调函数的返回值），所以必须要写返回值。</li><li>而 watchEffect 更注重的是过程（回调函数的函数体），所以不用写返回值。</li></ul><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//watchEffect所指定的回调中用到的数据只要发生变化，则直接重新执行回调。</span></span><br><span class="line">watchEffect(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">  <span class="keyword">const</span> x1 = sum.value;</span><br><span class="line">  <span class="keyword">const</span> x2 = person.age;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">&quot;watchEffect配置的回调执行了&quot;</span>);</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure></li></ul><h3 id="8-生命周期"><a href="#8-生命周期" class="headerlink" title="8.生命周期"></a>8.生命周期</h3><p><strong>vue2.x的生命周期</strong></p><p><img src="https://pic.wjnba.top/img/202406/20240617111321.webp" alt=""></p><p><strong>vue3.0的生命周期</strong></p><p><img src="https://pic.wjnba.top/img/202406/20240617111348.webp" alt=""></p><ul><li>Vue3.0 中可以继续使用 Vue2.x 中的生命周期钩子，但有有两个被更名：<ul><li><code>beforeDestroy</code>改名为 <code>beforeUnmount</code></li><li><code>destroyed</code>改名为 <code>unmounted</code></li></ul></li><li>Vue3.0 也提供了 Composition API 形式的生命周期钩子，与 Vue2.x 中钩子对应关系如下：<ul><li><code>beforeCreate</code>===&gt;<code>setup()</code></li><li><code>created</code>=======&gt;<code>setup()</code></li><li><code>beforeMount</code> ===&gt;<code>onBeforeMount</code></li><li><code>mounted</code>=======&gt;<code>onMounted</code></li><li><code>beforeUpdate</code>===&gt;<code>onBeforeUpdate</code></li><li><code>updated</code> =======&gt;<code>onUpdated</code></li><li><code>beforeUnmount</code> ==&gt;<code>onBeforeUnmount</code></li><li><code>unmounted</code> =====&gt;<code>onUnmounted</code></li></ul></li></ul><h3 id="9-自定义-hook-函数"><a href="#9-自定义-hook-函数" class="headerlink" title="9.自定义 hook 函数"></a>9.自定义 hook 函数</h3><ul><li>什么是 hook？—— 本质是一个函数，把 setup 函数中使用的 Composition API 进行了封装。</li><li>类似于 vue2.x 中的 mixin。</li><li>自定义 hook 的优势: 复用代码, 让 setup 中的逻辑更清楚易懂。</li></ul><h3 id="10-toRef"><a href="#10-toRef" class="headerlink" title="10.toRef"></a>10.toRef</h3><ul><li>作用：创建一个 ref 对象，其 value 值指向另一个对象中的某个属性。</li><li>语法：<code>const name = toRef(person,&#39;name&#39;)</code></li><li>应用: 要将响应式对象中的某个属性单独提供给外部使用时。</li><li>扩展：<code>toRefs</code> 与<code>toRef</code>功能一致，但可以批量创建多个 ref 对象，语法：<code>toRefs(person)</code></li></ul><h2 id="三、其它-Composition-API"><a href="#三、其它-Composition-API" class="headerlink" title="三、其它 Composition API"></a>三、其它 Composition API</h2><h3 id="1-shallowReactive-与-shallowRef"><a href="#1-shallowReactive-与-shallowRef" class="headerlink" title="1.shallowReactive 与 shallowRef"></a>1.shallowReactive 与 shallowRef</h3><ul><li>shallowReactive：只处理对象最外层属性的响应式（浅响应式）。</li><li>shallowRef：只处理基本数据类型的响应式, 不进行对象的响应式处理。</li><li>什么时候使用?<ul><li>如果有一个对象数据，结构比较深, 但变化时只是外层属性变化 ===&gt; shallowReactive。</li><li>如果有一个对象数据，后续功能不会修改该对象中的属性，而是生新的对象来替换 ===&gt; shallowRef。</li></ul></li></ul><h3 id="2-readonly-与-shallowReadonly"><a href="#2-readonly-与-shallowReadonly" class="headerlink" title="2.readonly 与 shallowReadonly"></a>2.readonly 与 shallowReadonly</h3><ul><li>readonly: 让一个响应式数据变为只读的（深只读）。</li><li>shallowReadonly：让一个响应式数据变为只读的（浅只读）。</li><li>应用场景: 不希望数据被修改时。</li></ul><h3 id="3-toRaw-与-markRaw"><a href="#3-toRaw-与-markRaw" class="headerlink" title="3.toRaw 与 markRaw"></a>3.toRaw 与 markRaw</h3><ul><li>toRaw：<ul><li>作用：将一个由<code>reactive</code>生成的<strong>响应式对象</strong>转为<strong>普通对象</strong>。</li><li>使用场景：用于读取响应式对象对应的普通对象，对这个普通对象的所有操作，不会引起页面更新。</li></ul></li><li>markRaw：<ul><li>作用：标记一个对象，使其永远不会再成为响应式对象。</li><li>应用场景:<ol><li>有些值不应被设置为响应式的，例如复杂的第三方类库等。</li><li>当渲染具有不可变数据源的大列表时，跳过响应式转换可以提高性能。</li></ol></li></ul></li></ul><h3 id="4-customRef"><a href="#4-customRef" class="headerlink" title="4.customRef"></a>4.customRef</h3><ul><li><p>作用：创建一个自定义的 ref，并对其依赖项跟踪和更新触发进行显式控制。</p></li><li><p>实现防抖效果：</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">template</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;text&quot;</span> <span class="attr">v-model</span>=<span class="string">&quot;keyword&quot;</span> /&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">h3</span>&gt;</span>&#123;&#123; keyword &#125;&#125;<span class="tag">&lt;/<span class="name">h3</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="javascript"></span></span><br><span class="line"><span class="javascript"><span class="keyword">import</span> &#123; ref, customRef &#125; <span class="keyword">from</span> <span class="string">&quot;vue&quot;</span>;</span></span><br><span class="line"><span class="javascript"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span></span><br><span class="line"><span class="javascript">  <span class="attr">name</span>: <span class="string">&quot;Demo&quot;</span>,</span></span><br><span class="line"><span class="javascript">  <span class="function"><span class="title">setup</span>(<span class="params"></span>)</span> &#123;</span></span><br><span class="line"><span class="javascript">    <span class="comment">// let keyword = ref(&#x27;hello&#x27;) //使用Vue准备好的内置ref</span></span></span><br><span class="line"><span class="javascript">    <span class="comment">//自定义一个myRef</span></span></span><br><span class="line"><span class="javascript">    <span class="function"><span class="keyword">function</span> <span class="title">myRef</span>(<span class="params">value, delay</span>) </span>&#123;</span></span><br><span class="line"><span class="javascript">      <span class="keyword">let</span> timer;</span></span><br><span class="line"><span class="javascript">      <span class="comment">//通过customRef去实现自定义</span></span></span><br><span class="line"><span class="javascript">      <span class="keyword">return</span> customRef(<span class="function">(<span class="params">track, trigger</span>) =&gt;</span> &#123;</span></span><br><span class="line"><span class="javascript">        <span class="keyword">return</span> &#123;</span></span><br><span class="line"><span class="javascript">          <span class="function"><span class="title">get</span>(<span class="params"></span>)</span> &#123;</span></span><br><span class="line"><span class="javascript">            track(); <span class="comment">//告诉Vue这个value值是需要被“追踪”的</span></span></span><br><span class="line"><span class="javascript">            <span class="keyword">return</span> value;</span></span><br><span class="line"><span class="javascript">          &#125;,</span></span><br><span class="line"><span class="javascript">          <span class="function"><span class="title">set</span>(<span class="params">newValue</span>)</span> &#123;</span></span><br><span class="line"><span class="javascript">            <span class="built_in">clearTimeout</span>(timer);</span></span><br><span class="line"><span class="javascript">            timer = <span class="built_in">setTimeout</span>(<span class="function">() =&gt;</span> &#123;</span></span><br><span class="line"><span class="javascript">              value = newValue;</span></span><br><span class="line"><span class="javascript">              trigger(); <span class="comment">//告诉Vue去更新界面</span></span></span><br><span class="line"><span class="javascript">            &#125;, delay);</span></span><br><span class="line"><span class="javascript">          &#125;,</span></span><br><span class="line"><span class="javascript">        &#125;;</span></span><br><span class="line"><span class="javascript">      &#125;);</span></span><br><span class="line"><span class="javascript">    &#125;</span></span><br><span class="line"><span class="javascript">    <span class="keyword">let</span> keyword = myRef(<span class="string">&quot;hello&quot;</span>, <span class="number">500</span>); <span class="comment">//使用程序员自定义的ref</span></span></span><br><span class="line"><span class="javascript">    <span class="keyword">return</span> &#123;</span></span><br><span class="line"><span class="javascript">      keyword,</span></span><br><span class="line"><span class="javascript">    &#125;;</span></span><br><span class="line"><span class="javascript">  &#125;,</span></span><br><span class="line"><span class="javascript">&#125;;</span></span><br><span class="line"><span class="javascript"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure></li></ul><h3 id="5-provide-与-inject"><a href="#5-provide-与-inject" class="headerlink" title="5.provide 与 inject"></a>5.provide 与 inject</h3><ul><li><p>作用：实现<strong>祖与后代组件间</strong>通信</p></li><li><p>套路：父组件有一个 <code>provide</code> 选项来提供数据，后代组件有一个 <code>inject</code> 选项来开始使用这些数据</p></li><li><p>具体写法：</p><ol><li><p>祖组件中：</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="title">setup</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">......</span><br><span class="line">    <span class="keyword">let</span> car = reactive(&#123;<span class="attr">name</span>:<span class="string">&#x27;奔驰&#x27;</span>,<span class="attr">price</span>:<span class="string">&#x27;40万&#x27;</span>&#125;)</span><br><span class="line">    provide(<span class="string">&#x27;car&#x27;</span>,car)</span><br><span class="line">    ......</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li><li><p>后代组件中：</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="title">setup</span>(<span class="params">props,context</span>)</span>&#123;</span><br><span class="line">......</span><br><span class="line">    <span class="keyword">const</span> car = inject(<span class="string">&#x27;car&#x27;</span>)</span><br><span class="line">    <span class="keyword">return</span> &#123;car&#125;</span><br><span class="line">......</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li></ol></li></ul><h3 id="6-响应式数据的判断"><a href="#6-响应式数据的判断" class="headerlink" title="6.响应式数据的判断"></a>6.响应式数据的判断</h3><ul><li>isRef: 检查一个值是否为一个 ref 对象</li><li>isReactive: 检查一个对象是否是由 <code>reactive</code> 创建的响应式代理</li><li>isReadonly: 检查一个对象是否是由 <code>readonly</code> 创建的只读代理</li><li>isProxy: 检查一个对象是否是由 <code>reactive</code> 或者 <code>readonly</code> 方法创建的代理</li></ul><h2 id="四、Composition-API-的优势"><a href="#四、Composition-API-的优势" class="headerlink" title="四、Composition API 的优势"></a>四、Composition API 的优势</h2><h3 id="1-Options-API-存在的问题"><a href="#1-Options-API-存在的问题" class="headerlink" title="1.Options API 存在的问题"></a>1.Options API 存在的问题</h3><p>使用传统 OptionsAPI 中，新增或者修改一个需求，就需要分别在 data，methods，computed 里修改 。</p><p><a href="https://fastly.jsdelivr.net/gh/1405720461/blog_img@main/study/33.image"><img src="https://fastly.jsdelivr.net/gh/1405720461/blog_img@main/study/33.image" alt="img"></a></p><p><a href="https://fastly.jsdelivr.net/gh/1405720461/blog_img@main/study/34.image"><img src="https://fastly.jsdelivr.net/gh/1405720461/blog_img@main/study/34.image" alt="img"></a></p><h3 id="2-Composition-API-的优势"><a href="#2-Composition-API-的优势" class="headerlink" title="2.Composition API 的优势"></a>2.Composition API 的优势</h3><p>我们可以更加优雅的组织我们的代码，函数。让相关功能的代码更加有序的组织在一起。</p><p><a href="https://fastly.jsdelivr.net/gh/1405720461/blog_img@main/study/35.image"><img src="https://fastly.jsdelivr.net/gh/1405720461/blog_img@main/study/35.image" alt="img"></a></p><p><a href="https://fastly.jsdelivr.net/gh/1405720461/blog_img@main/study/36.image"><img src="https://fastly.jsdelivr.net/gh/1405720461/blog_img@main/study/36.image" alt="img"></a></p><h2 id="五、新的组件"><a href="#五、新的组件" class="headerlink" title="五、新的组件"></a>五、新的组件</h2><h3 id="1-Fragment"><a href="#1-Fragment" class="headerlink" title="1.Fragment"></a>1.Fragment</h3><ul><li>在 Vue2 中: 组件必须有一个根标签</li><li>在 Vue3 中: 组件可以没有根标签, 内部会将多个标签包含在一个 Fragment 虚拟元素中</li><li>好处: 减少标签层级, 减小内存占用</li></ul><h3 id="2-Teleport"><a href="#2-Teleport" class="headerlink" title="2.Teleport"></a>2.Teleport</h3><ul><li><p>什么是 Teleport？—— <code>Teleport</code> 是一种能够将我们的<strong>组件 html 结构</strong>移动到指定位置的技术。</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">teleport</span> <span class="attr">to</span>=<span class="string">&quot;移动位置&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">v-if</span>=<span class="string">&quot;isShow&quot;</span> <span class="attr">class</span>=<span class="string">&quot;mask&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;dialog&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">h3</span>&gt;</span>我是一个弹窗<span class="tag">&lt;/<span class="name">h3</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">button</span> @<span class="attr">click</span>=<span class="string">&quot;isShow = false&quot;</span>&gt;</span>关闭弹窗<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">teleport</span>&gt;</span></span><br></pre></td></tr></table></figure></li></ul><h3 id="3-Suspense"><a href="#3-Suspense" class="headerlink" title="3.Suspense"></a>3.Suspense</h3><ul><li><p>等待异步组件时渲染一些额外内容，让应用有更好的用户体验</p></li><li><p>使用步骤：</p><ul><li><p>异步引入组件</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; defineAsyncComponent &#125; <span class="keyword">from</span> <span class="string">&quot;vue&quot;</span>;</span><br><span class="line"><span class="keyword">const</span> Child = defineAsyncComponent(<span class="function">() =&gt;</span> <span class="keyword">import</span>(<span class="string">&quot;./components/Child.vue&quot;</span>));</span><br></pre></td></tr></table></figure></li><li><p>使用<code>Suspense</code>包裹组件，并配置好<code>default</code> 与 <code>fallback</code></p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">template</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">h3</span>&gt;</span>我是App组件<span class="tag">&lt;/<span class="name">h3</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">Suspense</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">template</span> <span class="attr">v-slot:default</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">Child</span> /&gt;</span></span><br><span class="line">      <span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">template</span> <span class="attr">v-slot:fallback</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">h3</span>&gt;</span>加载中.....<span class="tag">&lt;/<span class="name">h3</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">Suspense</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br></pre></td></tr></table></figure></li></ul></li></ul><h2 id="六、其他"><a href="#六、其他" class="headerlink" title="六、其他"></a>六、其他</h2><h3 id="1-全局-API-的转移"><a href="#1-全局-API-的转移" class="headerlink" title="1.全局 API 的转移"></a>1.全局 API 的转移</h3><ul><li><p>Vue 2.x 有许多全局 API 和配置。</p><ul><li><p>例如：注册全局组件、注册全局指令等。</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment">//注册全局组件</span></span><br><span class="line">Vue.component(<span class="string">&#x27;MyButton&#x27;</span>, &#123;</span><br><span class="line">  <span class="attr">data</span>: <span class="function">() =&gt;</span> (&#123;</span><br><span class="line">    <span class="attr">count</span>: <span class="number">0</span></span><br><span class="line">  &#125;),</span><br><span class="line">  <span class="attr">template</span>: <span class="string">&#x27;&lt;button @click=&quot;count++&quot;&gt;Clicked &#123;&#123; count &#125;&#125; times.&lt;/button&gt;&#x27;</span></span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line"><span class="comment">//注册全局指令</span></span><br><span class="line">Vue.directive(<span class="string">&#x27;focus&#x27;</span>, &#123;</span><br><span class="line">  <span class="attr">inserted</span>: <span class="function"><span class="params">el</span> =&gt;</span> el.focus()</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li></ul></li><li><p>Vue3.0 中对这些 API 做出了调整：</p><ul><li>将全局的 API，即：<code>Vue.xxx</code>调整到应用实例（<code>app</code>）上</li></ul></li></ul><div class="table-container"><table><thead><tr><th>2.x 全局 API（<code>Vue</code>）</th><th>3.x 实例 API (<code>app</code>)</th></tr></thead><tbody><tr><td>Vue.config.xxxx</td><td>app.config.xxxx</td></tr><tr><td>Vue.config.productionTip</td><td><strong>移除</strong></td></tr><tr><td>Vue.component</td><td>app.component</td></tr><tr><td>Vue.directive</td><td>app.directive</td></tr><tr><td>Vue.mixin</td><td>app.mixin</td></tr><tr><td>Vue.use</td><td>app.use</td></tr><tr><td>Vue.prototype</td><td>app.config.globalProperties</td></tr></tbody></table></div><h3 id="2-其他改变"><a href="#2-其他改变" class="headerlink" title="2.其他改变"></a>2.其他改变</h3><ul><li><p>data 选项应始终被声明为一个函数。</p></li><li><p>过度类名的更改：</p><ul><li><p>Vue2.x 写法</p><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.v-enter</span>,</span><br><span class="line"><span class="selector-class">.v-leave-to</span> &#123;</span><br><span class="line">  <span class="attribute">opacity</span>: <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-class">.v-leave</span>,</span><br><span class="line"><span class="selector-class">.v-enter-to</span> &#123;</span><br><span class="line">  <span class="attribute">opacity</span>: <span class="number">1</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li><li><p>Vue3.x 写法</p><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.v-enter-from</span>,</span><br><span class="line"><span class="selector-class">.v-leave-to</span> &#123;</span><br><span class="line">  <span class="attribute">opacity</span>: <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.v-leave-from</span>,</span><br><span class="line"><span class="selector-class">.v-enter-to</span> &#123;</span><br><span class="line">  <span class="attribute">opacity</span>: <span class="number">1</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li></ul></li><li><p><strong>移除</strong>keyCode 作为 v-on 的修饰符，同时也不再支持<code>config.keyCodes</code></p></li><li><p><strong>移除</strong><code>v-on.native</code>修饰符</p><ul><li><p>父组件中绑定事件</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">my-component</span></span></span><br><span class="line"><span class="tag">  <span class="attr">v-on:close</span>=<span class="string">&quot;handleComponentEvent&quot;</span></span></span><br><span class="line"><span class="tag">  <span class="attr">v-on:click</span>=<span class="string">&quot;handleNativeClickEvent&quot;</span></span></span><br><span class="line"><span class="tag">/&gt;</span></span><br></pre></td></tr></table></figure></li><li><p>子组件中声明自定义事件</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="javascript"></span></span><br><span class="line"><span class="javascript"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span></span><br><span class="line"><span class="javascript">  <span class="attr">emits</span>: [<span class="string">&quot;close&quot;</span>],</span></span><br><span class="line"><span class="javascript">&#125;;</span></span><br><span class="line"><span class="javascript"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure></li></ul></li><li><p><strong>移除</strong>过滤器（filter）</p><blockquote><p>过滤器虽然这看起来很方便，但它需要一个自定义语法，打破大括号内表达式是 “只是 JavaScript” 的假设，这不仅有学习成本，而且有实现成本！建议用方法调用或计算属性去替换过滤器。</p></blockquote></li><li><p>…</p></li></ul>]]></content>
    
    
      
      
    <summary type="html">&lt;h2 id=&quot;Vue3&quot;&gt;&lt;a href=&quot;#Vue3&quot; class=&quot;headerlink&quot; title=&quot;Vue3&quot;&gt;&lt;/a&gt;Vue3&lt;/h2&gt;&lt;p&gt;&lt;img src=&quot;https://pic.wjnba.top/img/202406/20240617110657.webp</summary>
      
    
    
    
    <category term="vue3" scheme="https://www.wjnba.top/categories/vue3/"/>
    
    
    <category term="vue" scheme="https://www.wjnba.top/tags/vue/"/>
    
  </entry>
  
  <entry>
    <title>vue大屏适配方案</title>
    <link href="https://www.wjnba.top/articles/20240612720b6383efbf.html"/>
    <id>https://www.wjnba.top/articles/20240612720b6383efbf.html</id>
    <published>2024-06-12T06:46:53.000Z</published>
    <updated>2025-12-15T03:40:53.439Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://pic.wjnba.top/img/202406/20240612145829.webp" alt=""></p><blockquote><p>在做可视化大屏项目难免会考虑到屏幕适配的难题，如果有一个适配各种屏幕的基础容器组件处理这个事情，我们就可以放心写业务，下面介绍在vue中如何通过锁定宽高比的方式来进行屏幕适配。</p></blockquote><h2 id="组件特点"><a href="#组件特点" class="headerlink" title="组件特点"></a>组件特点</h2><p>1.自动监听浏览器窗口变化,动态计算出高宽比,无视页面放大缩小</p><p>2.适用于各种屏幕,常用作项目最外层基础容器</p><p>3.突破浏览器中 font-size 最小 12px 限制</p><h2 id="组件实现"><a href="#组件实现" class="headerlink" title="组件实现"></a>组件实现</h2><p>新增<code>LargeScreenContainer.vue</code>文件，在文件里面创建一个外层包裹容器，根据屏幕的可视区尺寸与设计稿尺寸得到一个<strong>宽高缩放比例</strong>，根据比例去对外层包裹容器进行缩放，以适应屏幕</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">template</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;well-container&quot;</span> <span class="attr">:ref</span>=<span class="string">&quot;refName&quot;</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">template</span> <span class="attr">v-if</span>=<span class="string">&quot;ready&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">slot</span>&gt;</span><span class="tag">&lt;/<span class="name">slot</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="javascript"></span></span><br><span class="line"><span class="javascript">  <span class="keyword">import</span> &#123; debounce &#125; <span class="keyword">from</span> <span class="string">&#x27;@/utils/util.js&#x27;</span></span></span><br><span class="line"><span class="javascript"></span></span><br><span class="line"><span class="javascript">  <span class="keyword">export</span> <span class="keyword">default</span> &#123;</span></span><br><span class="line"><span class="javascript">    <span class="attr">name</span>: <span class="string">&#x27;largeScreenContainer&#x27;</span>,</span></span><br><span class="line"><span class="javascript">    <span class="attr">props</span>: &#123;</span></span><br><span class="line"><span class="javascript">      <span class="attr">options</span>: <span class="built_in">Object</span></span></span><br><span class="line"><span class="javascript">    &#125;,</span></span><br><span class="line"><span class="javascript">    <span class="function"><span class="title">data</span>(<span class="params"></span>)</span> &#123;</span></span><br><span class="line"><span class="javascript">      <span class="keyword">return</span> &#123;</span></span><br><span class="line"><span class="javascript">        <span class="attr">refName</span>: <span class="string">&#x27;WellContainer&#x27;</span>,</span></span><br><span class="line"><span class="javascript">        <span class="attr">width</span>: <span class="number">0</span>, <span class="comment">// 屏幕宽度</span></span></span><br><span class="line"><span class="javascript">        <span class="attr">height</span>: <span class="number">0</span>, <span class="comment">// 屏幕高度</span></span></span><br><span class="line"><span class="javascript">        <span class="attr">originalWidth</span>: <span class="number">0</span>, <span class="comment">// 原始屏幕宽度</span></span></span><br><span class="line"><span class="javascript">        <span class="attr">originalHeight</span>: <span class="number">0</span>, <span class="comment">// 原始屏幕高度</span></span></span><br><span class="line"><span class="javascript">        <span class="attr">ready</span>: <span class="literal">false</span>, <span class="comment">// 控制显示</span></span></span><br><span class="line"><span class="javascript">        <span class="attr">dom</span>: <span class="literal">null</span>, <span class="comment">// well-container的dom</span></span></span><br><span class="line"><span class="javascript">        <span class="attr">observer</span>: <span class="literal">null</span> <span class="comment">// window.MutationObserver(Bom实例)监听dom改变</span></span></span><br><span class="line"><span class="javascript">      &#125;</span></span><br><span class="line"><span class="javascript">    &#125;,</span></span><br><span class="line"><span class="javascript">    <span class="attr">methods</span>: &#123;</span></span><br><span class="line"><span class="javascript">      <span class="comment">// 设置初始值</span></span></span><br><span class="line"><span class="javascript">      <span class="function"><span class="title">initSize</span>(<span class="params"></span>)</span> &#123;</span></span><br><span class="line"><span class="javascript">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function">(<span class="params">resolve</span>) =&gt;</span> &#123;</span></span><br><span class="line"><span class="javascript">          <span class="built_in">this</span>.$nextTick(<span class="function">() =&gt;</span> &#123;</span></span><br><span class="line"><span class="javascript">            <span class="built_in">this</span>.dom = <span class="built_in">document</span>.getElementById(<span class="string">&#x27;well-container&#x27;</span>)</span></span><br><span class="line"><span class="javascript">            <span class="comment">// 获取大屏的传入尺寸</span></span></span><br><span class="line"><span class="javascript">            <span class="keyword">if</span> (<span class="built_in">this</span>.options &amp;&amp; <span class="built_in">this</span>.options.width &amp;&amp; <span class="built_in">this</span>.options.height) &#123;</span></span><br><span class="line"><span class="javascript">              <span class="comment">// 传入宽高</span></span></span><br><span class="line"><span class="javascript">              <span class="built_in">this</span>.width = <span class="built_in">this</span>.options.width</span></span><br><span class="line"><span class="javascript">              <span class="built_in">this</span>.height = <span class="built_in">this</span>.options.height</span></span><br><span class="line"><span class="javascript">            &#125; <span class="keyword">else</span> &#123;</span></span><br><span class="line"><span class="javascript">              <span class="comment">// 可见宽高</span></span></span><br><span class="line"><span class="javascript">              <span class="built_in">this</span>.width = <span class="built_in">this</span>.dom.clientWidth</span></span><br><span class="line"><span class="javascript">              <span class="built_in">this</span>.height = <span class="built_in">this</span>.dom.clientHeight</span></span><br><span class="line"><span class="javascript">            &#125;</span></span><br><span class="line"><span class="javascript">            <span class="comment">// 获取画布尺寸</span></span></span><br><span class="line"><span class="javascript">            <span class="keyword">if</span> (!<span class="built_in">this</span>.originalWidth || !<span class="built_in">this</span>.originalHeight) &#123;</span></span><br><span class="line"><span class="javascript">              <span class="comment">// 屏幕分辨率宽高</span></span></span><br><span class="line"><span class="javascript">              <span class="built_in">this</span>.originalWidth = <span class="built_in">window</span>.screen.width</span></span><br><span class="line"><span class="javascript">              <span class="built_in">this</span>.originalHeight = <span class="built_in">window</span>.screen.height</span></span><br><span class="line"><span class="javascript">            &#125;</span></span><br><span class="line"><span class="javascript">            resolve()</span></span><br><span class="line"><span class="javascript">          &#125;)</span></span><br><span class="line"><span class="javascript">        &#125;)</span></span><br><span class="line"><span class="javascript">      &#125;,</span></span><br><span class="line"><span class="javascript">      <span class="function"><span class="title">updateSize</span>(<span class="params"></span>)</span> &#123;</span></span><br><span class="line"><span class="javascript">        <span class="keyword">if</span> (<span class="built_in">this</span>.width &amp;&amp; <span class="built_in">this</span>.height) &#123;</span></span><br><span class="line"><span class="javascript">          <span class="built_in">this</span>.dom.style.width = <span class="string">`<span class="subst">$&#123;<span class="built_in">this</span>.width&#125;</span>px`</span></span></span><br><span class="line"><span class="javascript">          <span class="built_in">this</span>.dom.style.height = <span class="string">`<span class="subst">$&#123;<span class="built_in">this</span>.height&#125;</span>px`</span></span></span><br><span class="line"><span class="javascript">        &#125; <span class="keyword">else</span> &#123;</span></span><br><span class="line"><span class="javascript">          <span class="built_in">this</span>.dom.style.width = <span class="string">`<span class="subst">$&#123;<span class="built_in">this</span>.originalWidth&#125;</span>px`</span></span></span><br><span class="line"><span class="javascript">          <span class="built_in">this</span>.dom.style.height = <span class="string">`<span class="subst">$&#123;<span class="built_in">this</span>.originalHeight&#125;</span>px`</span></span></span><br><span class="line"><span class="javascript">        &#125;</span></span><br><span class="line"><span class="javascript">      &#125;,</span></span><br><span class="line"><span class="javascript">      <span class="function"><span class="title">updateScale</span>(<span class="params"></span>)</span> &#123;</span></span><br><span class="line"><span class="javascript">        <span class="comment">// 获取真实的视口尺寸</span></span></span><br><span class="line"><span class="javascript">        <span class="keyword">const</span> currentWidth = <span class="built_in">document</span>.body.clientWidth</span></span><br><span class="line"><span class="javascript">        <span class="keyword">const</span> currentHeight = <span class="built_in">document</span>.body.clientHeight</span></span><br><span class="line"><span class="javascript">        <span class="comment">// 获取大屏最终的宽高</span></span></span><br><span class="line"><span class="javascript">        <span class="keyword">const</span> realWidth = <span class="built_in">this</span>.width || <span class="built_in">this</span>.originalWidth</span></span><br><span class="line"><span class="javascript">        <span class="keyword">const</span> realHeight = <span class="built_in">this</span>.height || <span class="built_in">this</span>.originalHeight</span></span><br><span class="line"><span class="javascript">        <span class="built_in">console</span>.log(currentWidth, currentHeight)</span></span><br><span class="line"><span class="javascript">        <span class="comment">// 缩放比例  = 分辨率宽高 / 传入宽高(可视宽高)</span></span></span><br><span class="line"><span class="javascript">        <span class="keyword">const</span> widthScale = currentWidth / realWidth</span></span><br><span class="line"><span class="javascript">        <span class="keyword">const</span> heightScale = currentHeight / realHeight</span></span><br><span class="line"><span class="javascript">        <span class="comment">// 如果dom存在,就按照比例缩放</span></span></span><br><span class="line"><span class="javascript">        <span class="built_in">this</span>.dom &amp;&amp; (<span class="built_in">this</span>.dom.style.transform = <span class="string">`scale(<span class="subst">$&#123;widthScale&#125;</span>, <span class="subst">$&#123;heightScale&#125;</span>)`</span>)</span></span><br><span class="line"><span class="javascript">      &#125;,</span></span><br><span class="line"><span class="javascript">      <span class="comment">// 重置缩放比例</span></span></span><br><span class="line"><span class="javascript">      <span class="keyword">async</span> <span class="function"><span class="title">onResize</span>(<span class="params"></span>)</span> &#123;</span></span><br><span class="line"><span class="javascript">        <span class="keyword">await</span> <span class="built_in">this</span>.initSize()</span></span><br><span class="line"><span class="javascript">        <span class="built_in">this</span>.updateScale()</span></span><br><span class="line"><span class="javascript">        <span class="built_in">this</span>.$emit(<span class="string">&#x27;resize&#x27;</span>)</span></span><br><span class="line"><span class="javascript">      &#125;,</span></span><br><span class="line"><span class="javascript">      <span class="function"><span class="title">initMutationObserver</span>(<span class="params"></span>)</span> &#123;</span></span><br><span class="line"><span class="javascript">        <span class="comment">// 监听元素属性变化</span></span></span><br><span class="line"><span class="javascript">        <span class="keyword">const</span> MutationObserver = <span class="built_in">window</span>.MutationObserver</span></span><br><span class="line"><span class="javascript">        <span class="comment">// 如果变化,就用onResize重置屏幕所缩放比例</span></span></span><br><span class="line"><span class="javascript">        <span class="built_in">this</span>.observer = <span class="keyword">new</span> MutationObserver(<span class="built_in">this</span>.onResize)</span></span><br><span class="line"><span class="javascript">        <span class="built_in">this</span>.observer.observe(<span class="built_in">this</span>.dom, &#123;</span></span><br><span class="line"><span class="javascript">          <span class="attr">attributes</span>: <span class="literal">true</span>,</span></span><br><span class="line"><span class="javascript">          <span class="attr">attributeFilter</span>: [<span class="string">&#x27;style&#x27;</span>],</span></span><br><span class="line"><span class="javascript">          <span class="attr">attributeOldValue</span>: <span class="literal">true</span></span></span><br><span class="line"><span class="javascript">        &#125;)</span></span><br><span class="line"><span class="javascript">      &#125;,</span></span><br><span class="line"><span class="javascript">      <span class="comment">// 移除监听属性</span></span></span><br><span class="line"><span class="javascript">      <span class="function"><span class="title">removeMutationObserver</span>(<span class="params"></span>)</span> &#123;</span></span><br><span class="line"><span class="javascript">        <span class="keyword">if</span> (<span class="built_in">this</span>.observer) &#123;</span></span><br><span class="line"><span class="javascript">          <span class="built_in">this</span>.observer.disconnect()</span></span><br><span class="line"><span class="javascript">          <span class="built_in">this</span>.observer.takeRecords()</span></span><br><span class="line"><span class="javascript">          <span class="built_in">this</span>.observer = <span class="literal">null</span></span></span><br><span class="line"><span class="javascript">        &#125;</span></span><br><span class="line"><span class="javascript">      &#125;,</span></span><br><span class="line"><span class="javascript">      <span class="function"><span class="title">resize</span>(<span class="params"></span>)</span> &#123;</span></span><br><span class="line"><span class="javascript">        debounce(<span class="built_in">this</span>.onResize, <span class="number">100</span>)</span></span><br><span class="line"><span class="javascript">      &#125;</span></span><br><span class="line"><span class="javascript">    &#125;,</span></span><br><span class="line"><span class="javascript">    <span class="keyword">async</span> <span class="function"><span class="title">mounted</span>(<span class="params"></span>)</span> &#123;</span></span><br><span class="line"><span class="javascript">      <span class="keyword">await</span> <span class="built_in">this</span>.initSize()</span></span><br><span class="line"><span class="javascript">      <span class="built_in">this</span>.updateSize()</span></span><br><span class="line"><span class="javascript">      <span class="built_in">this</span>.updateScale()</span></span><br><span class="line"><span class="javascript">      <span class="built_in">window</span>.addEventListener(<span class="string">&#x27;resize&#x27;</span>, <span class="built_in">this</span>.resize)</span></span><br><span class="line"><span class="javascript">      <span class="built_in">this</span>.initMutationObserver()</span></span><br><span class="line"><span class="javascript">      <span class="built_in">this</span>.ready = <span class="literal">true</span></span></span><br><span class="line"><span class="javascript">    &#125;,</span></span><br><span class="line"><span class="javascript">    <span class="function"><span class="title">beforeDestroy</span>(<span class="params"></span>)</span> &#123;</span></span><br><span class="line"><span class="javascript">      <span class="built_in">window</span>.removeEventListener(<span class="string">&#x27;resize&#x27;</span>, <span class="built_in">this</span>.resize)</span></span><br><span class="line"><span class="javascript">      <span class="built_in">this</span>.removeMutationObserver()</span></span><br><span class="line"><span class="javascript">    &#125;</span></span><br><span class="line"><span class="javascript">  &#125;</span></span><br><span class="line"><span class="javascript"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">style</span> <span class="attr">lang</span>=<span class="string">&quot;scss&quot;</span> <span class="attr">scoped</span>&gt;</span><span class="css"></span></span><br><span class="line"><span class="css"></span></span><br><span class="line"><span class="css"><span class="selector-id">#well-container</span> &#123;</span></span><br><span class="line"><span class="css">  <span class="attribute">position</span>: fixed;</span></span><br><span class="line"><span class="css">  <span class="attribute">top</span>: <span class="number">0</span>;</span></span><br><span class="line"><span class="css">  <span class="attribute">left</span>: <span class="number">0</span>;</span></span><br><span class="line"><span class="css">  <span class="attribute">overflow</span>: hidden;</span></span><br><span class="line"><span class="css">  <span class="attribute">transform-origin</span>: left top;</span></span><br><span class="line"><span class="css">  <span class="attribute">z-index</span>: <span class="number">999</span>;</span></span><br><span class="line"><span class="css">&#125;</span></span><br><span class="line"><span class="css"></span><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br></pre></td></tr></table></figure><p>依赖文件 util.js，参考如下：</p><div class="tag link"><a class="link-card" title="节流与防抖" href="https://www.wjnba.top/articles/20220523205e2283eab8.html"><div class="left"><img src="https://pic.wjnba.top/img/blog-cover-3.png"/></div><div class="right"><p class="text">节流与防抖</p><p class="url">https://www.wjnba.top/articles/20220523205e2283eab8.html</p></div></a></div><h2 id="组件的使用"><a href="#组件的使用" class="headerlink" title="组件的使用"></a>组件的使用</h2><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">large-screen-container</span></span></span><br><span class="line"><span class="tag">  <span class="attr">:options</span>=<span class="string">&quot;&#123;width:1920,height:1080&#125;&quot;</span></span></span><br><span class="line"><span class="tag">&gt;</span></span><br><span class="line">  <span class="comment">&lt;!-- 子元素会根据缩放比例自动适配 --&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">large-screen-container</span>&gt;</span></span><br></pre></td></tr></table></figure><h2 id="核心原理"><a href="#核心原理" class="headerlink" title="核心原理"></a>核心原理</h2><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 缩放比例  = 分辨率宽高 / 传入宽高(可视宽高)</span></span><br><span class="line"><span class="keyword">const</span> widthScale = currentWidth / realWidth</span><br><span class="line"><span class="keyword">const</span> heightScale = currentHeight / realHeight</span><br><span class="line"><span class="comment">// 如果dom存在,就按照比例缩放</span></span><br><span class="line"><span class="built_in">this</span>.dom &amp;&amp; (<span class="built_in">this</span>.dom.style.transform = <span class="string">`scale(<span class="subst">$&#123;widthScale&#125;</span>, <span class="subst">$&#123;heightScale&#125;</span>)`</span>)</span><br></pre></td></tr></table></figure><p>1.宽度度缩放比例(widthScale)= 分辨率宽高/props 传入宽高(可视宽高)</p><p>2.高度缩放比例(heightScale) = 分辨率高度/props 传入高度(可视高度)</p><p>3.通过 transform 的属性缩放容器的大</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;&lt;img src=&quot;https://pic.wjnba.top/img/202406/20240612145829.webp&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;在做可视化大屏项目难免会考虑到屏幕适配的难题，如果有一个适配各种屏幕的基础容器组件处理这个</summary>
      
    
    
    
    <category term="vue组件" scheme="https://www.wjnba.top/categories/vue%E7%BB%84%E4%BB%B6/"/>
    
    
    <category term="vue" scheme="https://www.wjnba.top/tags/vue/"/>
    
    <category term="前端适配" scheme="https://www.wjnba.top/tags/%E5%89%8D%E7%AB%AF%E9%80%82%E9%85%8D/"/>
    
  </entry>
  
  <entry>
    <title>vue中使用vue-lazyload实现图片的懒加载</title>
    <link href="https://www.wjnba.top/articles/20240416e2cba8f4e7fb.html"/>
    <id>https://www.wjnba.top/articles/20240416e2cba8f4e7fb.html</id>
    <published>2024-04-16T09:24:17.000Z</published>
    <updated>2025-12-15T03:40:53.439Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://pic.wjnba.top/img/202404/20240418153949.webp" alt=""></p><blockquote><p>前面在<a href="https://www.wjnba.top/articles/20220530043ea0d0d7dd.html">图片懒加载</a>一文中讲到什么是图片懒加载和用<code>js</code>怎么实现懒加载，本文记录一下图片懒加载插件 <code>vue-lazyload</code>的使用。</p></blockquote><h2 id="一、安装依赖包"><a href="#一、安装依赖包" class="headerlink" title="一、安装依赖包"></a>一、安装依赖包</h2><h4 id="npm"><a href="#npm" class="headerlink" title="npm"></a>npm</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm i vue-lazyload -S</span><br></pre></td></tr></table></figure><h4 id="yarn"><a href="#yarn" class="headerlink" title="yarn"></a>yarn</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">yarn add vue-lazyload</span><br></pre></td></tr></table></figure><h2 id="二、全局注册插件"><a href="#二、全局注册插件" class="headerlink" title="二、全局注册插件"></a>二、全局注册插件</h2><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 引入插件</span></span><br><span class="line"><span class="keyword">import</span> VueLazyload <span class="keyword">from</span> <span class="string">&#x27;vue-lazyload&#x27;</span></span><br><span class="line"><span class="comment">// 注册插件</span></span><br><span class="line"><span class="keyword">const</span> loadimage = <span class="built_in">require</span>(<span class="string">&#x27;./assets/loading.gif&#x27;</span>)</span><br><span class="line"><span class="keyword">const</span> errorimage = <span class="built_in">require</span>(<span class="string">&#x27;./assets/error.gif&#x27;</span>)</span><br><span class="line">Vue.use(VueLazyload, &#123;</span><br><span class="line">  <span class="attr">preLoad</span>: <span class="number">1.3</span>,</span><br><span class="line">  <span class="attr">error</span>: errorimage,</span><br><span class="line">  <span class="attr">loading</span>: loadimage,</span><br><span class="line">  <span class="attr">attempt</span>: <span class="number">1</span></span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure><p>配置项参数说明：</p><div class="table-container"><table><thead><tr><th style="text-align:center"><strong>键</strong></th><th><strong>描述</strong></th><th><strong>默认值</strong></th><th style="text-align:center"><strong>选项</strong></th></tr></thead><tbody><tr><td style="text-align:center">preLoad</td><td>表示lazyload的元素,<br />距离页面底部距离的百分比.<br/>计算值为(preload - 1)</td><td>1.3</td><td style="text-align:center">Number</td></tr><tr><td style="text-align:center">error</td><td>加载失败后图片地址</td><td>‘data-src’</td><td style="text-align:center">String</td></tr><tr><td style="text-align:center">loading</td><td>加载时图片地址</td><td>‘data-src’</td><td style="text-align:center">String</td></tr><tr><td style="text-align:center">attempt</td><td>图片加载失败后的重试次数</td><td>3</td><td style="text-align:center">Number</td></tr><tr><td style="text-align:center">listenEvents</td><td>触发懒加载的事件</td><td>[<br />‘scroll’,<br /> ‘wheel’,<br /> ‘mousewheel’,<br /> ‘resize’, <br />‘animationend’, <br />‘transitionend’,<br /> ‘touchmove’<br />]</td><td style="text-align:center">无</td></tr><tr><td style="text-align:center">adapter</td><td>注册img 的loading,loaded,error<br/>三个状态的回调函数,<br/>参数会暴露懒加载的img元素,<br/>可以对其进行操作.</td><td>{ }</td><td style="text-align:center">无</td></tr><tr><td style="text-align:center">filter</td><td>img未加载之前,<br/>解析到src 的时候注册的回调函数.<br/>可以在加载图片之前,对src进行修改.<br/>注册在filter下的所有的函数都会执行</td><td>{ }</td><td style="text-align:center">无</td></tr><tr><td style="text-align:center">lazyComponent</td><td>是否启用懒加载组件.<br/><lazy-component>组件中的内容<br/>只有在出现在preload的<br/>位置中才会加载组件.<br/>这个lazyloadComponent<br/>组件有个缺点<br/>就是,组件在加载前<br/>是什么都不渲染的,<br/>这样子的话,有可能会影响布局,<br/>以及加载前到加载后的切换不好,<br/>有点突兀和生硬.</td><td>false</td><td style="text-align:center">无</td></tr><tr><td style="text-align:center">dispatchEvent</td><td>触发dom事件</td><td>false</td><td style="text-align:center">Boolean</td></tr><tr><td style="text-align:center">throttleWait</td><td>等待时长</td><td>200</td><td style="text-align:center">Number</td></tr><tr><td style="text-align:center">observer</td><td>是否启用IntersectionObserver, 这个api有<a href="https://links.jianshu.com/go?to=https%3A%2F%2Fcaniuse.com%2F%23search%3DIntersectionobserver">兼容问题</a></td><td>false</td><td style="text-align:center">Boolean</td></tr><tr><td style="text-align:center">observerOptions</td><td>IntersectionObserver选项</td><td>{ rootMargin: ‘0px’, threshold: 0.1 }</td><td style="text-align:center">无</td></tr><tr><td style="text-align:center">silent</td><td>不打印调试信息</td><td>true</td><td style="text-align:center">Boolean</td></tr></tbody></table></div><h2 id="三、在需要的组件中使用"><a href="#三、在需要的组件中使用" class="headerlink" title="三、在需要的组件中使用"></a>三、在需要的组件中使用</h2><h4 id="1、v-lazy"><a href="#1、v-lazy" class="headerlink" title="1、v-lazy"></a>1、v-lazy</h4><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">ul</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">li</span> <span class="attr">v-for</span>=<span class="string">&quot;img in list&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">img</span> <span class="attr">v-lazy</span>=<span class="string">&quot;img.src&quot;</span> &gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">ul</span>&gt;</span></span><br></pre></td></tr></table></figure><h4 id="2、v-lazy-container"><a href="#2、v-lazy-container" class="headerlink" title="2、v-lazy-container"></a>2、v-lazy-container</h4><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">v-lazy-container</span>=<span class="string">&quot;&#123; selector: &#x27;img&#x27;, error: &#x27;xxx.jpg&#x27;, loading: &#x27;xxx.jpg&#x27; &#125;&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">img</span> <span class="attr">data-src</span>=<span class="string">&quot;//domain.com/img1.jpg&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">img</span> <span class="attr">data-src</span>=<span class="string">&quot;//domain.com/img2.jpg&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">img</span> <span class="attr">data-src</span>=<span class="string">&quot;//domain.com/img3.jpg&quot;</span>&gt;</span>  </span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure><h2 id="四、实现富文本里面图片的懒加载"><a href="#四、实现富文本里面图片的懒加载" class="headerlink" title="四、实现富文本里面图片的懒加载"></a>四、实现富文本里面图片的懒加载</h2><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span>  </span></span><br><span class="line"><span class="tag">     <span class="attr">v-lazy-container</span>=<span class="string">&quot;lazyConfig&quot;</span> </span></span><br><span class="line"><span class="tag">     <span class="attr">class</span>=<span class="string">&quot;content&quot;</span> </span></span><br><span class="line"><span class="tag">     <span class="attr">v-html</span>=<span class="string">&quot;htmlStr&quot;</span> </span></span><br><span class="line"><span class="tag">     <span class="attr">ref</span>=<span class="string">&quot;content&quot;</span> </span></span><br><span class="line"><span class="tag">     <span class="attr">id</span>=<span class="string">&quot;htmlContent&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span><br><span class="line">    ......</span><br><span class="line">    <span class="function"><span class="title">data</span>(<span class="params"></span>)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> &#123;</span><br><span class="line">            <span class="attr">content</span>: <span class="string">&#x27;&#x27;</span>,</span><br><span class="line">            <span class="attr">lazyConfig</span>: &#123;</span><br><span class="line">                <span class="attr">selector</span>: <span class="string">&#x27;img&#x27;</span>,</span><br><span class="line">                <span class="attr">error</span>: <span class="string">&#x27;https://www.wjnba.top/img/loading.gif&#x27;</span>,</span><br><span class="line">                <span class="attr">loading</span>: <span class="string">&#x27;https://www.wjnba.top/img/loading.gif&#x27;</span></span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;，</span><br><span class="line">    <span class="attr">computed</span>: &#123;</span><br><span class="line">        <span class="comment">// 把副本中图片src替换为 data-src</span></span><br><span class="line">        <span class="function"><span class="title">htmlStr</span>(<span class="params"></span>)</span> &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="built_in">this</span>.content?.replace(<span class="regexp">/(&lt;img )([^&gt;]*)(src=&quot;)([^&quot;]*&quot;)([^&gt;]*)(&gt;)/g</span>, <span class="function">(<span class="params">match, p1, p2, p3, p4, p5, p6</span>) =&gt;</span> &#123;</span><br><span class="line">                <span class="keyword">return</span> <span class="string">`<span class="subst">$&#123;p1 + p2&#125;</span>data-src=&quot;<span class="subst">$&#123;p4&#125;</span><span class="subst">$&#123;p5&#125;</span><span class="subst">$&#123;p6&#125;</span>`</span></span><br><span class="line">            &#125;)</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;,</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;&lt;img src=&quot;https://pic.wjnba.top/img/202404/20240418153949.webp&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;前面在&lt;a href=&quot;https://www.wjnba.top/articles/20</summary>
      
    
    
    
    <category term="vue插件" scheme="https://www.wjnba.top/categories/vue%E6%8F%92%E4%BB%B6/"/>
    
    
    <category term="vue" scheme="https://www.wjnba.top/tags/vue/"/>
    
    <category term="性能优化" scheme="https://www.wjnba.top/tags/%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96/"/>
    
  </entry>
  
  <entry>
    <title>JS命名规范</title>
    <link href="https://www.wjnba.top/articles/202404033e401561b4c9.html"/>
    <id>https://www.wjnba.top/articles/202404033e401561b4c9.html</id>
    <published>2024-04-03T03:21:51.000Z</published>
    <updated>2025-12-15T03:40:53.441Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://pic.wjnba.top/img/202404/20240403125232.png" alt=""></p><blockquote><p>js命名应遵循 <strong>简洁、语义化</strong> 的原则</p></blockquote><h2 id="一、变量"><a href="#一、变量" class="headerlink" title="一、变量"></a>一、变量</h2><p>命名方法: 小驼峰式命名法<br>命名规范：前缀为形容词 （函数前缀为动词, 以此来区分函数和变量）</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//好的命名方式</span></span><br><span class="line"><span class="keyword">let</span> maxCount = <span class="number">10</span>;</span><br><span class="line"><span class="keyword">let</span> tableTitle = <span class="string">&#x27;啦啦啦&#x27;</span>;</span><br><span class="line"><span class="comment">//不好的命名方式</span></span><br><span class="line"><span class="keyword">let</span> setConut = <span class="number">10</span>;</span><br><span class="line"><span class="keyword">let</span> getTitle = <span class="string">&#x27;啦啦啦&#x27;</span>;</span><br></pre></td></tr></table></figure><h3 id="临时变量"><a href="#临时变量" class="headerlink" title="临时变量"></a>临时变量</h3><p>1：作用域不大临时变量可以简写，比如：<code>str</code>，<code>num</code>，<code>bol</code>，<code>obj</code>，<code>fun</code>，<code>arr</code>。<br>2：循环变量可以简写，比如：<code>i</code>，<code>j</code>，<code>k</code>等。</p><ul><li><code>s</code>：表示字符串。例如：sName，sHtml；</li><li><code>n</code>：表示数字。例如：nPage，nTotal；</li><li><code>b</code>：表示逻辑。例如：bChecked，bHasLogin；</li><li><code>a</code>：表示数组。例如：aList，aGroup；</li><li><code>r</code>：表示正则表达式。例如：rDomain，rEmail；</li><li><code>f</code>：表示函数。例如：fGetHtml，fInit；</li><li><code>o</code>：表示以上未涉及到的其他对象，例如：oButton，oDate；</li><li><code>g</code>：表示全局变量，例如：gUserName，gLoginTime；</li></ul><h2 id="二、常量"><a href="#二、常量" class="headerlink" title="二、常量"></a>二、常量</h2><blockquote><p> 某些作为不允许修改值的变量认为是常量，常量可以存在于函数中，也可以存在于全局。</p></blockquote><p><strong>命名方法：</strong>名词全部大写<br><strong>命名规范：</strong>使用大写字母和下划线来组合命名，下划线用来分割单词。</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> MAX_COUNT = <span class="number">10</span>;</span><br><span class="line"><span class="keyword">const</span> URL = <span class="string">&#x27;//www.huifenqi.com&#x27;</span>;</span><br></pre></td></tr></table></figure><h2 id="三、函数-amp-方法"><a href="#三、函数-amp-方法" class="headerlink" title="三、函数 &amp; 方法"></a>三、函数 &amp; 方法</h2><p><strong>命名方法：</strong> 小驼峰式命名法<br><strong>命名规范：</strong> 前缀应该为动词<br><strong>命名建议：</strong>常用动词约定</p><ul><li><p><code>get</code> 获取/<code>set</code> 设置/<code>add</code> 增加/<code>remove</code> 删除/<code>create</code> 创建/<code>destory</code> 移除</p></li><li><p><code>start</code> 启动/<code>stop</code> 停止/<code>open</code> 打开/<code>close</code> 关闭/<code>read</code> 读取/<code>write</code> 写入</p></li><li><p><code>load</code> 载入/<code>save</code> 保存/<code>create</code> 创建/<code>destroy</code> 销毁</p></li><li><p><code>begin</code> 开始/<code>end</code> 结束/<code>backup</code> 备份/<code>restore</code> 恢复/<code>detach</code> 脱离</p></li><li><p><code>import</code> 导入/<code>export</code> 导出/<code>split</code> 分割/<code>merge</code> 合并/<code>inject</code> 注入/<code>extract</code> 提取</p></li><li><p><code>attach</code> 附着/<code>bind</code> 绑定/<code>separate</code> 分离/ <code>view</code> 查看/<code>browse</code> 浏览</p></li><li><p><code>edit</code> 编辑/<code>modify</code> 修改/<code>select</code> 选取/<code>mark</code> 标记/<code>copy</code> 复制/<code>paste</code> 粘贴/<code>undo</code> 撤销</p></li><li><p><code>redo</code> 重做/<code>insert</code> 插入/<code>delete</code> 移除/<code>add</code> 加入/<code>append</code> 添加</p></li><li><p><code>clean</code> 清理/<code>clear</code> 清除/<code>index</code> 索引/<code>sort</code> 排序/<code>find</code> 查找/<code>search</code> 搜索/</p></li><li><p><code>increase</code> 增加/<code>decrease</code> 减少/<code>play</code> 播放/<code>pause</code> 暂停/</p></li><li><p><code>launch</code> 启动/<code>run</code> 运行/<code>pack</code> 打包/<code>unpack</code> 解包/<code>parse</code> 解析/<code>emit</code> 生成</p></li><li><p><code>compile</code> 编译/<code>execute</code> 执行/<code>debug</code> 调试/<code>trace</code> 跟踪</p></li><li><p><code>observe</code> 观察/<code>listen</code> 监听/<code>build</code> 构建/<code>publish</code> 发布/<code>push</code> 推/<code>pull</code> 拉</p></li><li><p><code>input</code> 输入/<code>output</code> 输出/<code>encode</code> 编码/<code>decode</code> 解码</p></li><li><p><code>expand</code> 展开/<code>collapse</code> 折叠/<code>encrypt</code> 加密/<code>decrypt</code> 解密</p></li><li><p><code>compress</code> 压缩/<code>decompress</code> 解压缩</p></li><li><p><code>connect</code> 连接/<code>disconnect</code> 断开/<code>send</code> 发送/<code>receive</code> 接收</p></li><li><p><code>download</code> 下载/<code>upload</code> 上传/<code>refresh</code> 刷新/<code>synchronize</code> 同步</p></li><li><p><code>update</code> 更新/<code>revert</code> 复原/<code>lock</code> 锁定/<code>unlock</code> 解锁</p></li><li><p><code>check out</code> 签出/<code>check in</code> 签入/<code>submit</code> 提交/<code>commit</code> 交付</p></li><li><p><code>begin</code> 起始/<code>end</code> 结束/<code>start</code> 开始/<code>finish</code> 完成/<code>enter</code> 进入/<code>exit</code> 退出</p></li><li><p><code>abort</code> 放弃/<code>quit</code> 离开/<code>obsolete</code> 废弃/<code>depreciate</code> 废旧</p></li><li><p><code>collect</code> 收集/<code>aggregate</code> 聚集</p></li><li><p><code>can</code> 判断是否可执行某个动作</p></li><li><p><code>has</code> 判断是否含义某个值</p></li><li><p><code>is</code> 判断是否为某个值</p></li></ul><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 是否可阅读</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">canRead</span>(<span class="params"></span>) </span>&#123;&#125;</span><br><span class="line"><span class="comment">// 获取名称</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">getName</span>(<span class="params"></span>) </span>&#123;&#125;</span><br></pre></td></tr></table></figure><h2 id="四、类-amp-构造函数"><a href="#四、类-amp-构造函数" class="headerlink" title="四、类 &amp; 构造函数"></a>四、类 &amp; 构造函数</h2><p><strong>命名方法：</strong>大写驼峰式命名法，首字母大写。<br><strong>命名规范：</strong>前缀为名称。</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Persion</span> </span>&#123;</span><br><span class="line">  <span class="function"><span class="title">constructor</span>(<span class="params">name</span>)</span> &#123;</span><br><span class="line">   ...</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> person = <span class="keyword">new</span> Person(<span class="string">&#x27;啦啦啦&#x27;</span>);</span><br></pre></td></tr></table></figure><h2 id="五、类的成员"><a href="#五、类的成员" class="headerlink" title="五、类的成员"></a>五、类的成员</h2><p>类的成员包括：</p><p><strong>公共属性和方法：</strong> 跟变量和函数命名一样。<br><strong>私有属性和方法：</strong>前缀为下划线_, 后面跟公共属性和方法一样的命名方式。</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Person</span> </span>&#123;</span><br><span class="line">  <span class="comment">// 私有属性 </span></span><br><span class="line">  <span class="attr">_name</span>: string;</span><br><span class="line">  <span class="function"><span class="title">constructor</span>(<span class="params"></span>)</span> &#123; &#125;</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 公共方法</span></span><br><span class="line">  <span class="function"><span class="title">getName</span>(<span class="params"></span>)</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="built_in">this</span>._name;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="comment">// 公共方法</span></span><br><span class="line">  <span class="function"><span class="title">setName</span>(<span class="params">name</span>)</span> &#123;</span><br><span class="line">    <span class="built_in">this</span>._name = name;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;&lt;img src=&quot;https://pic.wjnba.top/img/202404/20240403125232.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;js命名应遵循 &lt;strong&gt;简洁、语义化&lt;/strong&gt; 的原则&lt;/p&gt;
&lt;/bloc</summary>
      
    
    
    
    <category term="代码规范" scheme="https://www.wjnba.top/categories/%E4%BB%A3%E7%A0%81%E8%A7%84%E8%8C%83/"/>
    
    
    <category term="代码规范" scheme="https://www.wjnba.top/tags/%E4%BB%A3%E7%A0%81%E8%A7%84%E8%8C%83/"/>
    
    <category term="javascript" scheme="https://www.wjnba.top/tags/javascript/"/>
    
  </entry>
  
  <entry>
    <title>CSS媒体查询</title>
    <link href="https://www.wjnba.top/articles/20240402d6b5aa8c7fec.html"/>
    <id>https://www.wjnba.top/articles/20240402d6b5aa8c7fec.html</id>
    <published>2024-04-02T02:18:25.000Z</published>
    <updated>2025-12-15T03:40:53.435Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://pic.wjnba.top/img/202404/20240403125837.png" alt=""></p><h2 id="媒体查询（Media-Queries）"><a href="#媒体查询（Media-Queries）" class="headerlink" title="媒体查询（Media Queries）"></a>媒体查询（Media Queries）</h2><blockquote><p><strong>媒体查询（Media Queries）</strong>是 CSS3 中的一个特性，它允许你根据设备的特性（如宽度、高度、颜色等）来应用不同的 CSS 样式。这使得开发者能够为不同的设备（如桌面电脑、平板电脑、手机等）或同一设备的不同状态（如横屏或竖屏）创建特定的布局和样式。</p></blockquote><p><strong>媒体查询由两部分组成</strong>：<strong>媒体类型（Media Type）</strong>和<strong>媒体特性（Media Features）</strong>。</p><p><strong>媒体类型</strong>：描述了设备的一般类别，如 all（所有设备）、screen（电脑屏幕、平板电脑、智能手机等）、print（打印机和打印预览）等。</p><p><strong>媒体特性</strong>：描述了设备的具体特性，如 width（视口宽度）、height（视口高度）、color（设备颜色位数）等。</p><p>媒体查询的基本语法如下：</p><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">css</span><br><span class="line"><span class="keyword">@media</span> mediaType <span class="keyword">and</span> (mediaFeature1: value1) <span class="keyword">and</span> (mediaFeature2: value2) &#123;  </span><br><span class="line">    <span class="comment">/* CSS 规则 */</span>  </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>例如，如果你想为宽度小于 768px 的设备设置特定的样式，你可以这样写：</p><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">css</span><br><span class="line"><span class="keyword">@media</span> screen <span class="keyword">and</span> (<span class="attribute">max-width</span>: <span class="number">767px</span>) &#123;  </span><br><span class="line">    <span class="selector-tag">body</span> &#123;  </span><br><span class="line">        <span class="attribute">background-color</span>: lightblue;  </span><br><span class="line">    &#125;  </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>在这个例子中，媒体类型是 screen，媒体特性是 max-width: 767px。这意味着当屏幕宽度小于或等于 767px 时，body 的背景色将变为浅蓝色。</p><p>媒体查询是响应式设计的核心，它允许开发者创建一个灵活且适应各种设备的网站。</p><p><strong>媒体查询中的分辨率</strong>设置主要依赖于具体的设备特性，并没有固定的分辨率列表。但是，你可以根据常见的设备和屏幕尺寸来设置媒体查询。<br> 以下是一些常见的屏幕分辨率和对应的CSS媒体查询：</p><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">1024</span>x768 (常用于<span class="number">10.4</span>、<span class="number">12.1</span>、<span class="number">14.1</span>、<span class="number">15</span>寸电脑)：</span><br><span class="line"></span><br><span class="line">css</span><br><span class="line"><span class="keyword">@media</span> screen <span class="keyword">and</span> (<span class="attribute">min-width</span>: <span class="number">1024px</span>) <span class="keyword">and</span> (<span class="attribute">max-width</span>: <span class="number">1279px</span>) &#123;  </span><br><span class="line">    <span class="comment">/* 样式 */</span>  </span><br><span class="line">&#125;</span><br><span class="line"><span class="number">1280</span>x1024 (常用于<span class="number">14.1</span>、<span class="number">15</span>寸电脑)：</span><br><span class="line"></span><br><span class="line">css</span><br><span class="line"><span class="keyword">@media</span> screen <span class="keyword">and</span> (<span class="attribute">min-width</span>: <span class="number">1280px</span>) <span class="keyword">and</span> (<span class="attribute">max-width</span>: <span class="number">1629px</span>) &#123;  </span><br><span class="line">    <span class="comment">/* 样式 */</span>  </span><br><span class="line">&#125;</span><br><span class="line"><span class="number">1280</span>x800 (常用于<span class="number">15.4</span>寸电脑)：</span><br><span class="line"></span><br><span class="line">css</span><br><span class="line"><span class="keyword">@media</span> screen <span class="keyword">and</span> (<span class="attribute">min-width</span>: <span class="number">1280px</span>) <span class="keyword">and</span> (<span class="attribute">max-width</span>: <span class="number">1599px</span>) &#123;  </span><br><span class="line">    <span class="comment">/* 样式 */</span>  </span><br><span class="line">&#125;</span><br><span class="line"><span class="number">1366</span>x768 (常用于<span class="number">15.2</span>寸电脑)：</span><br><span class="line"></span><br><span class="line">css</span><br><span class="line"><span class="keyword">@media</span> screen <span class="keyword">and</span> (<span class="attribute">min-width</span>: <span class="number">1366px</span>) <span class="keyword">and</span> (<span class="attribute">max-width</span>: <span class="number">1629px</span>) &#123;  </span><br><span class="line">    <span class="comment">/* 样式 */</span>  </span><br><span class="line">&#125;</span><br><span class="line"><span class="number">1440</span>x900 (常用于<span class="number">15.6</span>、<span class="number">17</span>寸电脑)：</span><br><span class="line"></span><br><span class="line">css</span><br><span class="line"><span class="keyword">@media</span> screen <span class="keyword">and</span> (<span class="attribute">min-width</span>: <span class="number">1440px</span>) <span class="keyword">and</span> (<span class="attribute">max-width</span>: <span class="number">1799px</span>) &#123;  </span><br><span class="line">    <span class="comment">/* 样式 */</span>  </span><br><span class="line">&#125;</span><br><span class="line"><span class="number">1600</span>x900 (常用于<span class="number">15.4</span>、<span class="number">20</span>寸电脑)：</span><br><span class="line"></span><br><span class="line">css</span><br><span class="line"><span class="keyword">@media</span> screen <span class="keyword">and</span> (<span class="attribute">min-width</span>: <span class="number">1600px</span>) <span class="keyword">and</span> (<span class="attribute">max-width</span>: <span class="number">1899px</span>) &#123;  </span><br><span class="line">    <span class="comment">/* 样式 */</span>  </span><br><span class="line">&#125;</span><br><span class="line"><span class="number">1920</span>x1080 (常用于主流<span class="number">23</span>、<span class="number">24</span>、<span class="number">27</span>寸电脑)：</span><br><span class="line"></span><br><span class="line">css</span><br><span class="line"><span class="keyword">@media</span> screen <span class="keyword">and</span> (<span class="attribute">min-width</span>: <span class="number">1920px</span>) &#123;  </span><br><span class="line">    <span class="comment">/* 样式 */</span>  </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;&lt;img src=&quot;https://pic.wjnba.top/img/202404/20240403125837.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;媒体查询（Media-Queries）&quot;&gt;&lt;a href=&quot;#媒体查询（Media-Queries）&quot; cl</summary>
      
    
    
    
    <category term="深入浅出css" scheme="https://www.wjnba.top/categories/%E6%B7%B1%E5%85%A5%E6%B5%85%E5%87%BAcss/"/>
    
    
    <category term="css" scheme="https://www.wjnba.top/tags/css/"/>
    
    <category term="响应式布局" scheme="https://www.wjnba.top/tags/%E5%93%8D%E5%BA%94%E5%BC%8F%E5%B8%83%E5%B1%80/"/>
    
  </entry>
  
  <entry>
    <title>uniapp安卓手机无线真机调试</title>
    <link href="https://www.wjnba.top/articles/2023083076b3a1d0ac73.html"/>
    <id>https://www.wjnba.top/articles/2023083076b3a1d0ac73.html</id>
    <published>2023-08-30T02:12:00.000Z</published>
    <updated>2025-12-15T03:40:53.438Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://pic.wjnba.top/img/202308301602929.png" alt="202308301432378"></p><p>从 <code>Android 11</code> 开始USB调试新增了无线调试功能，需要搭配 <code>adb 30.0.0</code> 及以上版本使用，请确认你的系统和<code>adb</code>是否符合要求。</p><h2 id="一、下载adb"><a href="#一、下载adb" class="headerlink" title="一、下载adb"></a>一、下载<code>adb</code></h2><p><code>adb</code>下载地址： <a href="https://developer.android.google.cn/studio/releases/platform-tools">SDK Platform Tools版本说明</a></p><p>选择对应的系统版本，我是windows系统，所以选择如下：</p><p><img src="https://pic.wjnba.top/img/202308301457052.png" alt="image-20230830145726373"></p><p>下载解压完之后放到<code>HBuilderX</code>的<code>adbs</code>文件夹里 重命名为<code>34.0.0</code> </p><p><img src="https://pic.wjnba.top/img/202308301503762.png" alt="image-20230830150354324"></p><h2 id="二、在手机上打开无线调试"><a href="#二、在手机上打开无线调试" class="headerlink" title="二、在手机上打开无线调试"></a>二、在手机上打开无线调试</h2><p>手机连上<code>wifi</code>，保证手机和电脑在同一局域网，进入开发者选项开启无线调试</p><p><img src="https://pic.wjnba.top/img/202308301513412.png" alt="image-20230830151126101" style="zoom:50%;" /></p><p><img src="https://pic.wjnba.top/img/202308301541876.png" alt="image-20230830151243039" style="zoom:50%;" /></p><h2 id="三、使用配对码配对"><a href="#三、使用配对码配对" class="headerlink" title="三、使用配对码配对"></a>三、使用配对码配对</h2><h3 id="1、手机上点击使用配对码配对设备，查看配对码和ip地址："><a href="#1、手机上点击使用配对码配对设备，查看配对码和ip地址：" class="headerlink" title="1、手机上点击使用配对码配对设备，查看配对码和ip地址："></a>1、手机上点击使用配对码配对设备，查看配对码和ip地址：</h3><p><img src="https://pic.wjnba.top/img/202308301540471.png" alt="image-20230830152317568" style="zoom:50%;" /></p><h3 id="2、进入34-0-0-文件夹，并打开cmd窗口："><a href="#2、进入34-0-0-文件夹，并打开cmd窗口：" class="headerlink" title="2、进入34.0.0 文件夹，并打开cmd窗口："></a>2、进入<code>34.0.0</code> 文件夹，并打开<code>cmd</code>窗口：</h3><ul><li><p>使用adb pair命令和手机配对</p><p><img src="https://pic.wjnba.top/img/202308301540608.png" alt="image-20230830153230621"></p></li></ul><ul><li><p>继续使用adb connect命令连接设备</p><p><img src="https://pic.wjnba.top/img/202308301540436.png" alt="image-20230830153742605"></p></li></ul><h2 id="四、验证"><a href="#四、验证" class="headerlink" title="四、验证"></a>四、验证</h2><p><img src="https://pic.wjnba.top/img/202308301540175.png" alt="image-20230830154040142"></p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;&lt;img src=&quot;https://pic.wjnba.top/img/202308301602929.png&quot; alt=&quot;202308301432378&quot;&gt;&lt;/p&gt;
&lt;p&gt;从 &lt;code&gt;Android 11&lt;/code&gt; 开始USB调试新增了无线调试功能，需要搭配 &lt;c</summary>
      
    
    
    
    <category term="uniapp" scheme="https://www.wjnba.top/categories/uniapp/"/>
    
    
    <category term="uniapp" scheme="https://www.wjnba.top/tags/uniapp/"/>
    
  </entry>
  
  <entry>
    <title>hexo博客butterfly主题cdn加载失败？那就换</title>
    <link href="https://www.wjnba.top/articles/202305238604b7796c2d.html"/>
    <id>https://www.wjnba.top/articles/202305238604b7796c2d.html</id>
    <published>2023-05-23T09:11:51.000Z</published>
    <updated>2025-12-15T03:40:53.438Z</updated>
    
    <content type="html"><![CDATA[<blockquote><p>前段时间因为jsdelivr挂掉，无法访问第三方文件，导致我的博客长时间出现资源加载问题，后面更换了cdn，但有时候还是会无法加载，未从根本上解决问题。</p></blockquote><p><img src="https://pic.wjnba.top/img/202305231724882.png" alt="image-20230523172407947"></p><p>于是今天决定，把第三方文件放在本地加载，查看<a href="https://butterfly.js.org/posts/ceeb73f/?highlight=hexo+butterfly+extjs#CDN">butterfly</a>官网，看到了两种方案可供选择。</p><h2 id="1、修改third-party-provider"><a href="#1、修改third-party-provider" class="headerlink" title="1、修改third_party_provider"></a>1、修改third_party_provider</h2><p>①.找到<code>/butterfly/_comfig.yml</code>文件，找到下面部分，把标注的部分改为<code>local</code></p><p><img src="https://pic.wjnba.top/img/202305231736947.png" alt="image-20230523173623522"></p><p>②.安装<code>hexo-butterfly-extjs</code>依赖，执行</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">npm</span> <span class="string">install</span> <span class="string">hexo-butterfly-extjs@1.3.4</span></span><br></pre></td></tr></table></figure><p>*注意：<code>hexo-butterfly-extjs</code>的版本要和<code>butterfly</code>对应，如果版本不对应的话，可能会导致这个主题需要的第三方依赖无法完全下载到<code>node_modules</code>，导致后面出错。当然也可以直接执行<code>npm i  依赖@版本号</code>，第三方依赖和版本号在<code>/butterfly/plugins.yml</code>。</p><p><img src="https://pic.wjnba.top/img/202305231749290.png" alt="image-20230523174943933"></p><h2 id="2、下载第三方文件到本地，修改option文件地址，覆盖原有的配置"><a href="#2、下载第三方文件到本地，修改option文件地址，覆盖原有的配置" class="headerlink" title="2、下载第三方文件到本地，修改option文件地址，覆盖原有的配置"></a>2、下载第三方文件到本地，修改option文件地址，覆盖原有的配置</h2><p><img src="https://pic.wjnba.top/img/202305231743345.png" alt="image-20230523174345684"></p><div class="table-container"><table><thead><tr><th>参数</th><th>解释</th></tr></thead><tbody><tr><td>internal_provider</td><td>主题内部文件可选<br /> local/jsdelivr/unpkg/cdnjs/custom<br/>lcoal 为本地加载，custom 为自定义格式，需配置 custom_format<br/>注意: 如果使用的是 Dev 版，只能设置为 local</td></tr><tr><td>third_party_provider</td><td>第三方文件<br/>可选 local/jsdelivr/unpkg/cdnjs/custom<br/>lcoal 为本地加载，custom 为自定义格式，需配置 custom_format<br/>注意: 如果你选择 local 需要安装 hexo-butterfly-extjs插件</td></tr><tr><td>version</td><td>true/false 为 cdn 加上指定版本号</td></tr><tr><td>custom_format</td><td>自定义格式</td></tr><tr><td>option</td><td>你可以在这里更换部分文件,会覆盖原有的配置</td></tr></tbody></table></div>]]></content>
    
    
      
      
    <summary type="html">&lt;blockquote&gt;
&lt;p&gt;前段时间因为jsdelivr挂掉，无法访问第三方文件，导致我的博客长时间出现资源加载问题，后面更换了cdn，但有时候还是会无法加载，未从根本上解决问题。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img src=&quot;https://pic.wjnb</summary>
      
    
    
    
    <category term="Hexo+Gitee" scheme="https://www.wjnba.top/categories/Hexo-Gitee/"/>
    
    
    <category term="个人博客" scheme="https://www.wjnba.top/tags/%E4%B8%AA%E4%BA%BA%E5%8D%9A%E5%AE%A2/"/>
    
    <category term="Hexo" scheme="https://www.wjnba.top/tags/Hexo/"/>
    
    <category term="butterfly" scheme="https://www.wjnba.top/tags/butterfly/"/>
    
  </entry>
  
  <entry>
    <title>实现五种CSS经典布局</title>
    <link href="https://www.wjnba.top/articles/20230523844402ea9656.html"/>
    <id>https://www.wjnba.top/articles/20230523844402ea9656.html</id>
    <published>2023-05-23T03:30:32.000Z</published>
    <updated>2025-12-15T03:40:53.442Z</updated>
    
    <content type="html"><![CDATA[<p>页面布局是样式开发的第一步，也是 CSS 最重要的功能之一。</p><p><img src="https://pic.wjnba.top/img/202305231513264.jpg" alt="img"></p><p>常用的页面布局，其实就那么几个。下面我会介绍5个经典布局，只要掌握了它们，就能应对绝大多数常规页面。</p><h2 id="一、空间居中布局"><a href="#一、空间居中布局" class="headerlink" title="一、空间居中布局"></a>一、空间居中布局</h2><p>空间居中布局指的是，不管容器的大小，项目总是占据中心点。</p><p><img src="https://pic.wjnba.top/img/202305231515153.jpg" alt="img"></p><p>CSS 代码如下。</p><blockquote><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.container</span> &#123;</span><br><span class="line">    <span class="attribute">display</span>: grid;</span><br><span class="line">    place-items: center;</span><br><span class="line">&#125; </span><br></pre></td></tr></table></figure></blockquote><p>上面代码需要写在容器上，指定为 Grid 布局。核心代码是<code>place-items</code>属性那一行，它是一个简写形式。</p><blockquote><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">place-items: &lt;align-items&gt; &lt;justify-items&gt;;</span><br></pre></td></tr></table></figure></blockquote><p><code>align-items</code>属性控制垂直位置，<code>justify-items</code>属性控制水平位置。这两个属性的值一致时，就可以合并写成一个值。所以，<code>place-items: center;</code>等同于<code>place-items: center center;</code>。</p><p>同理，左上角布局可以写成下面这样。</p><blockquote><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">place-items: start;</span><br></pre></td></tr></table></figure></blockquote><p><img src="https://pic.wjnba.top/img/202305231513286.jpg" alt="img"></p><p>右下角布局。</p><blockquote><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">place-items: end;</span><br></pre></td></tr></table></figure></blockquote><p><img src="https://pic.wjnba.top/img/202305231513339.jpg" alt="img"></p><h2 id="二、并列式布局"><a href="#二、并列式布局" class="headerlink" title="二、并列式布局"></a>二、并列式布局</h2><p>并列式布局就是多个项目并列。</p><p><img src="https://pic.wjnba.top/img/202305231513737.jpg" alt="img"></p><p>如果宽度不够，放不下的项目就自动折行。</p><p><img src="https://pic.wjnba.top/img/202305231513563.jpg" alt="img"></p><p><img src="https://pic.wjnba.top/img/202305231515110.jpg" alt="img"></p><p>它的实现也很简单。首先，容器设置成 Flex 布局，内容居中（<code>justify-content</code>）可换行（<code>flex-wrap</code>）。</p><blockquote><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.container</span> &#123;</span><br><span class="line">    <span class="attribute">display</span>: flex;</span><br><span class="line">    <span class="attribute">flex-wrap</span>: wrap;</span><br><span class="line">    <span class="attribute">justify-content</span>: center;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></blockquote><p>然后，项目上面只用一行<code>flex</code>属性就够了。</p><blockquote><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.item</span>&#123;</span><br><span class="line">   <span class="attribute">flex</span>: <span class="number">0</span> <span class="number">1</span> <span class="number">150px</span>;</span><br><span class="line">   <span class="attribute">margin</span>: <span class="number">5px</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></blockquote><p><code>flex</code>属性是<code>flex-grow</code>、<code>flex-shrink</code>、<code>flex-basis</code>这三个属性的简写形式。</p><blockquote><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="attribute">flex</span>: &lt;flex-grow&gt; &lt;flex-shrink&gt; &lt;flex-basis&gt;;</span><br></pre></td></tr></table></figure></blockquote><ul><li><code>flex-basis</code>：项目的初始宽度。</li><li><code>flex-grow</code>：指定如果有多余宽度，项目是否可以扩大。</li><li><code>flex-shrink</code>：指定如果宽度不足，项目是否可以缩小。</li></ul><p><code>flex: 0 1 150px;</code>的意思就是，项目的初始宽度是150px，且不可以扩大，但是当容器宽度不足150px时，项目可以缩小。</p><p>如果写成<code>flex: 1 1 150px;</code>，就表示项目始终会占满所有宽度。</p><p><img src="https://pic.wjnba.top/img/202305231513042.jpg" alt="img"></p><p><img src="https://pic.wjnba.top/img/202305231515740.jpg" alt="img"></p><p><img src="https://pic.wjnba.top/img/202305231513940.jpg" alt="img"></p><h2 id="三、两栏式布局"><a href="#三、两栏式布局" class="headerlink" title="三、两栏式布局"></a>三、两栏式布局</h2><p>两栏式布局就是一个边栏，一个主栏。</p><p><img src="https://pic.wjnba.top/img/202305231513525.jpg" alt="img"></p><p>下面的实现是，边栏始终存在，主栏根据设备宽度，变宽或者变窄。如果希望主栏自动换到下一行，可以参考上面的”并列式布局”。</p><p><img src="https://pic.wjnba.top/img/202305231514216.jpg" alt="img"></p><p>使用 Grid，实现很容易。</p><blockquote><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.container</span> &#123;</span><br><span class="line">    <span class="attribute">display</span>: grid;</span><br><span class="line">    grid-template-<span class="attribute">columns</span>: <span class="built_in">minmax</span>(<span class="number">150px</span>, <span class="number">25%</span>) <span class="number">1</span>fr;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></blockquote><p>上面代码中，<code>grid-template-columns</code>指定页面分成两列。第一列的宽度是<code>minmax(150px, 25%)</code>，即最小宽度为<code>150px</code>，最大宽度为总宽度的25%；第二列为<code>1fr</code>，即所有剩余宽度。</p><h2 id="四、三明治布局"><a href="#四、三明治布局" class="headerlink" title="四、三明治布局"></a>四、三明治布局</h2><p>三明治布局指的是，页面在垂直方向上，分成三部分：页眉、内容区、页脚。</p><p><img src="https://pic.wjnba.top/img/202305231514618.jpg" alt="img"></p><p>这个布局会根据设备宽度，自动适应，并且不管内容区有多少内容，页脚始终在容器底部（粘性页脚）。也就是说，这个布局总是会占满整个页面高度。</p><p><img src="https://pic.wjnba.top/img/202305231514404.jpg" alt="img"></p><p>CSS 代码如下。</p><blockquote><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.container</span> &#123;</span><br><span class="line">    <span class="attribute">display</span>: grid;</span><br><span class="line">    grid-template-rows: auto <span class="number">1</span>fr auto;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></blockquote><p>上面代码写在容器上面，指定采用 Grid 布局。核心代码是<code>grid-template-rows</code>那一行，指定垂直高度怎么划分，这里是从上到下分成三部分。第一部分（页眉）和第三部分（页脚）的高度都为<code>auto</code>，即本来的内容高度；第二部分（内容区）的高度为<code>1fr</code>，即剩余的所有高度，这可以保证页脚始终在容器的底部。</p><h2 id="五、圣杯布局"><a href="#五、圣杯布局" class="headerlink" title="五、圣杯布局"></a>五、圣杯布局</h2><p>圣杯布局是最常用的布局，所以被比喻为圣杯。它将页面分成五个部分，除了页眉和页脚，内容区分成左边栏、主栏、右边栏。</p><p><img src="https://pic.wjnba.top/img/202305231514073.jpg" alt="img"></p><p>这里的实现是，不管页面宽度，内容区始终分成三栏。如果宽度太窄，主栏和右边栏会看不到。如果想将这三栏改成小屏幕自动堆叠，可以参考并列式布局。</p><p><img src="https://pic.wjnba.top/img/202305231514857.jpg" alt="img"></p><p>HTML 代码如下。</p><blockquote><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;container&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">header</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">main</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">footer</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure></blockquote><p>CSS 代码如下。</p><blockquote><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.container</span> &#123;</span><br><span class="line">    <span class="attribute">display</span>: grid;</span><br><span class="line">    grid-template: auto <span class="number">1</span>fr auto / auto <span class="number">1</span>fr auto;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></blockquote><p>上面代码要写在容器上面，指定采用 Grid 布局。核心代码是<code>grid-template</code>属性那一行，它是两个属性<code>grid-template-rows</code>（垂直方向）和<code>grid-template-columns</code>（水平方向）的简写形式。</p><blockquote><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">grid-template: &lt;grid-template-rows&gt; / &lt;grid-template-columns&gt;</span><br></pre></td></tr></table></figure></blockquote><p><code>grid-template-rows</code>和<code>grid-template-columns</code>都是<code>auto 1fr auto</code>，就表示页面在垂直方向和水平方向上，都分成三个部分。第一部分（页眉和左边栏）和第三部分（页脚和右边栏）都是本来的内容高度（或宽度），第二部分（内容区和主栏）占满剩余的高度（或宽度）。</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;页面布局是样式开发的第一步，也是 CSS 最重要的功能之一。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://pic.wjnba.top/img/202305231513264.jpg&quot; alt=&quot;img&quot;&gt;&lt;/p&gt;
&lt;p&gt;常用的页面布局，其实就那么几个。下面我会介绍5个</summary>
      
    
    
    
    <category term="深入浅出 css" scheme="https://www.wjnba.top/categories/%E6%B7%B1%E5%85%A5%E6%B5%85%E5%87%BA-css/"/>
    
    
    <category term="css" scheme="https://www.wjnba.top/tags/css/"/>
    
  </entry>
  
  <entry>
    <title>谷歌浏览器书签同步到码云</title>
    <link href="https://www.wjnba.top/articles/2022120111ffaf80a31b.html"/>
    <id>https://www.wjnba.top/articles/2022120111ffaf80a31b.html</id>
    <published>2022-12-01T06:29:30.000Z</published>
    <updated>2025-12-15T03:40:53.442Z</updated>
    
    <content type="html"><![CDATA[<p>在我们更换电脑、或者重新安装谷歌浏览器的情况下，如果书签没有备份，原来收藏的网页就找不到了，我们需要一种手段来保存、同步书签，这时我们可以通过浏览器扩展程序配合码云来实现这个功能。</p><span id="more"></span><h2 id="准备"><a href="#准备" class="headerlink" title="准备"></a>准备</h2><h4 id="一、在码云上创建一个仓库，用来保存书签。"><a href="#一、在码云上创建一个仓库，用来保存书签。" class="headerlink" title="一、在码云上创建一个仓库，用来保存书签。"></a>一、在<a href="https://gitee.com/">码云</a>上创建一个仓库，用来保存书签。</h4><p><img src="https://pic.wjnba.top/img/202212011446255.png" alt=""></p><h4 id="二、在仓库里新建一个名为bookmarks-html的空文件。"><a href="#二、在仓库里新建一个名为bookmarks-html的空文件。" class="headerlink" title="二、在仓库里新建一个名为bookmarks.html的空文件。"></a>二、在仓库里新建一个名为<code>bookmarks.html</code>的空文件。</h4><blockquote><p>必须要创建<code>bookmarks.html</code>文件，不然推送到仓库的时候会失败。</p></blockquote><p><img src="https://pic.wjnba.top/img/202212011448166.png" alt="image-20221201144854987"></p><h4 id="三、创建私人令牌，用来推送书签文件到仓库。"><a href="#三、创建私人令牌，用来推送书签文件到仓库。" class="headerlink" title="三、创建私人令牌，用来推送书签文件到仓库。"></a>三、创建私人令牌，用来推送书签文件到仓库。</h4><p><img src="https://pic.wjnba.top/img/202212011457379.png" alt="image-20221201145712863"></p><h4 id="四、下载使用扩展程序。"><a href="#四、下载使用扩展程序。" class="headerlink" title="四、下载使用扩展程序。"></a>四、下载使用扩展程序。</h4><div class="btns rounded grid5">            <a class="button" href='https://pic.wjnba.top/file/%E8%B0%B7%E6%AD%8C%E5%90%8C%E6%AD%A5%E4%B9%A6%E7%AD%BE.zip' title='下载扩展程序'><i class='fas fa-download'></i>下载扩展程序</a>          </div><p>下载扩展程序后解压，导入到谷歌浏览器扩展程序里。</p><p><img src="https://pic.wjnba.top/img/202212011506216.png" alt="image-20221201150556766"></p><p>点击程序，向下依次填入私人令牌、用户名、仓库名、文件路径（<code>bookmarks.html</code>）、分支（<code>master</code>）,如下图所示：</p><p><img src="https://pic.wjnba.top/img/202212011509374.png" alt="image-20221201150923847"></p><p>填完后，我们就可以通过点击Upload按钮把书签同步到码云上，当更换电脑、重新安装浏览器后可通过点击Download按钮同步书签到本地了。</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;在我们更换电脑、或者重新安装谷歌浏览器的情况下，如果书签没有备份，原来收藏的网页就找不到了，我们需要一种手段来保存、同步书签，这时我们可以通过浏览器扩展程序配合码云来实现这个功能。&lt;/p&gt;</summary>
    
    
    
    <category term="浏览器" scheme="https://www.wjnba.top/categories/%E6%B5%8F%E8%A7%88%E5%99%A8/"/>
    
    
    <category term="谷歌浏览器" scheme="https://www.wjnba.top/tags/%E8%B0%B7%E6%AD%8C%E6%B5%8F%E8%A7%88%E5%99%A8/"/>
    
  </entry>
  
  <entry>
    <title>patch-package的使用</title>
    <link href="https://www.wjnba.top/articles/202210170ca19cae2d60.html"/>
    <id>https://www.wjnba.top/articles/202210170ca19cae2d60.html</id>
    <published>2022-10-17T09:10:03.000Z</published>
    <updated>2025-12-15T03:40:53.438Z</updated>
    
    <content type="html"><![CDATA[<h2 id="patch-package的使用"><a href="#patch-package的使用" class="headerlink" title="patch-package的使用"></a>patch-package的使用</h2><p>在<code>vue</code>实际项目中,有时候会涉及到修改<code>node_modules</code>里面的代码，但是如果直接在本地修改<code>node_modules</code>里面的代码，会带来很大的麻烦，比如更换电脑拉取项目后，执行<code>npm install</code>安装项目依赖，会恢复到没改之前的代码，这时我们可以使用<code>patch-package</code>这个库来解决这类问题。</p><span id="more"></span><h4 id="1、安装patch-package"><a href="#1、安装patch-package" class="headerlink" title="1、安装patch-package"></a>1、安装<code>patch-package</code></h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm i patch-package --save-dev</span><br></pre></td></tr></table></figure><h4 id="2、修改完依赖后，运行patch-package创建patch文件"><a href="#2、修改完依赖后，运行patch-package创建patch文件" class="headerlink" title="2、修改完依赖后，运行patch-package创建patch文件"></a>2、修改完依赖后，运行<code>patch-package</code>创建<code>patch</code>文件</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">npx patch-package 依赖名称</span><br><span class="line">例子： npx patch-package wangeditor</span><br></pre></td></tr></table></figure><p><img src="https://pic.wjnba.top/img/202210171736007.png" alt="image-20221017173642445"></p><h4 id="3、修改package-json的内容，在scripts中加入-quot-postinstall-quot-quot-patch-package-quot-，这个是为了npm-install的时候自动为依赖包打上我们改过的依赖"><a href="#3、修改package-json的内容，在scripts中加入-quot-postinstall-quot-quot-patch-package-quot-，这个是为了npm-install的时候自动为依赖包打上我们改过的依赖" class="headerlink" title="3、修改package.json的内容，在scripts中加入&quot;postinstall&quot;: &quot;patch-package&quot;，这个是为了npm install的时候自动为依赖包打上我们改过的依赖"></a>3、修改<code>package.json</code>的内容，在<code>scripts</code>中加入<code>&quot;postinstall&quot;: &quot;patch-package&quot;</code>，这个是为了<code>npm install</code>的时候自动为依赖包打上我们改过的依赖</h4><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&quot;scripts&quot;</span>: &#123;</span><br><span class="line">　　...</span><br><span class="line">　　<span class="attr">&quot;postinstall&quot;</span>: <span class="string">&quot;patch-package&quot;</span></span><br><span class="line">　　&#125;</span><br></pre></td></tr></table></figure><blockquote><p><code>npm install</code>命令发起后，根据工程定义决定是否执行<code>preinstall</code>，<code>install</code>、<code>postinstall</code> 是 <code>npm install</code>命令必然会执行的阶段</p></blockquote>]]></content>
    
    
    <summary type="html">&lt;h2 id=&quot;patch-package的使用&quot;&gt;&lt;a href=&quot;#patch-package的使用&quot; class=&quot;headerlink&quot; title=&quot;patch-package的使用&quot;&gt;&lt;/a&gt;patch-package的使用&lt;/h2&gt;&lt;p&gt;在&lt;code&gt;vue&lt;/code&gt;实际项目中,有时候会涉及到修改&lt;code&gt;node_modules&lt;/code&gt;里面的代码，但是如果直接在本地修改&lt;code&gt;node_modules&lt;/code&gt;里面的代码，会带来很大的麻烦，比如更换电脑拉取项目后，执行&lt;code&gt;npm install&lt;/code&gt;安装项目依赖，会恢复到没改之前的代码，这时我们可以使用&lt;code&gt;patch-package&lt;/code&gt;这个库来解决这类问题。&lt;/p&gt;</summary>
    
    
    
    <category term="vue插件" scheme="https://www.wjnba.top/categories/vue%E6%8F%92%E4%BB%B6/"/>
    
    
    <category term="vue" scheme="https://www.wjnba.top/tags/vue/"/>
    
  </entry>
  
  <entry>
    <title>Butterfly之主题页面</title>
    <link href="https://www.wjnba.top/articles/202209231b74b40eef30.html"/>
    <id>https://www.wjnba.top/articles/202209231b74b40eef30.html</id>
    <published>2022-09-23T07:54:07.000Z</published>
    <updated>2025-12-15T03:40:53.435Z</updated>
    
    <content type="html"><![CDATA[<h2 id="Front-matter"><a href="#Front-matter" class="headerlink" title="Front-matter"></a>Front-matter</h2><p><code>Front-matter</code> 是 <code>markdown</code> 文件最上方以 <strong>—-</strong> 分隔的区域，用于指定个别档案的变数。</p><p><code>Page Front-matter</code> 用于<strong>页面</strong>配置<br><code>Post Front-matter</code> 用于<strong>文章页</strong>配置</p><span id="more"></span><blockquote><p>如果标注可选的参数，可根据自己需要添加，不用全部都写在markdown里</p></blockquote><h3 id="Page-Front-matter"><a href="#Page-Front-matter" class="headerlink" title="Page Front-matter"></a>Page Front-matter</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">---</span><br><span class="line">title:</span><br><span class="line">date:</span><br><span class="line">updated:</span><br><span class="line"><span class="built_in">type</span>:</span><br><span class="line">comments:</span><br><span class="line">description:</span><br><span class="line">keywords:</span><br><span class="line">top_img:</span><br><span class="line">mathjax:</span><br><span class="line">katex:</span><br><span class="line">aside:</span><br><span class="line">aplayer:</span><br><span class="line">highlight_shrink:</span><br><span class="line">---</span><br></pre></td></tr></table></figure><div class="table-container"><table><thead><tr><th>写法</th><th>解释</th></tr></thead><tbody><tr><td>title</td><td>【必需】页面标题</td></tr><tr><td>date</td><td>【必需】页面创建日期</td></tr><tr><td>type</td><td>【必需】标籤、分类和友情链接三个页面需要配置</td></tr><tr><td>updated</td><td>【可选】页面更新日期</td></tr><tr><td>description</td><td>【可选】页面描述</td></tr><tr><td>keywords</td><td>【可选】页面关键字</td></tr><tr><td>comments</td><td>【可选】显示页面评论模块(默认 true)</td></tr><tr><td>top_img</td><td>【可选】页面顶部图片</td></tr><tr><td>mathjax</td><td>【可选】显示mathjax(当设置mathjax的per_page: false时，才需要配置，默认 false)</td></tr><tr><td>katex</td><td>【可选】显示katex(当设置katex的per_page: false时，才需要配置，默认 false)</td></tr><tr><td>aside</td><td>【可选】显示侧边栏 (默认 true)</td></tr><tr><td>aplayer</td><td>【可选】在需要的页面加载aplayer的js和css,请参考文章下面的音乐 配置</td></tr><tr><td>highlight_shrink</td><td>【可选】配置代码框是否展开(true/false)(默认为设置中highlight_shrink的配置)</td></tr></tbody></table></div><h3 id="Post-Front-matter"><a href="#Post-Front-matter" class="headerlink" title="Post Front-matter"></a>Post Front-matter</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">---</span><br><span class="line">title:</span><br><span class="line">date:</span><br><span class="line">updated:</span><br><span class="line">tags:</span><br><span class="line">categories:</span><br><span class="line">keywords:</span><br><span class="line">description:</span><br><span class="line">top_img:</span><br><span class="line">comments:</span><br><span class="line">cover:</span><br><span class="line">toc:</span><br><span class="line">toc_number:</span><br><span class="line">toc_style_simple:</span><br><span class="line">copyright:</span><br><span class="line">copyright_author:</span><br><span class="line">copyright_author_href:</span><br><span class="line">copyright_url:</span><br><span class="line">copyright_info:</span><br><span class="line">mathjax:</span><br><span class="line">katex:</span><br><span class="line">aplayer:</span><br><span class="line">highlight_shrink:</span><br><span class="line">aside:</span><br><span class="line">---</span><br></pre></td></tr></table></figure><div class="table-container"><table><thead><tr><th>写法</th><th>解释</th></tr></thead><tbody><tr><td>title</td><td>【必需】文章标题</td></tr><tr><td>date</td><td>【必需】文章创建日期</td></tr><tr><td>updated</td><td>【可选】文章更新日期</td></tr><tr><td>tags</td><td>【可选】文章标籤</td></tr><tr><td>categories</td><td>【可选】文章分类</td></tr><tr><td>keywords</td><td>【可选】文章关键字</td></tr><tr><td>description</td><td>【可选】文章描述</td></tr><tr><td>top_img</td><td>【可选】文章顶部图片</td></tr><tr><td>cover</td><td>【可选】文章缩略图(如果没有设置top_img,文章页顶部将显示缩略图，可设为false/图片地址/留空)</td></tr><tr><td>comments</td><td>【可选】显示文章评论模块(默认 true)</td></tr><tr><td>toc</td><td>【可选】显示文章TOC(默认为设置中toc的enable配置)</td></tr><tr><td>toc_number</td><td>【可选】显示toc_number(默认为设置中toc的number配置)</td></tr><tr><td>toc_style_simple</td><td>【可选】显示 toc 简洁模式</td></tr><tr><td>copyright</td><td>【可选】显示文章版权模块(默认为设置中post_copyright的enable配置)</td></tr><tr><td>copyright_author</td><td>【可选】文章版权模块的文章作者</td></tr><tr><td>copyright_author_href</td><td>【可选】文章版权模块的文章作者链接</td></tr><tr><td>copyright_url</td><td>【可选】文章版权模块的文章连结链接</td></tr><tr><td>copyright_info</td><td>【【可选】文章版权模块的版权声明文字</td></tr><tr><td>mathjax</td><td>【可选】显示mathjax(当设置mathjax的per_page: false时，才需要配置，默认 false)</td></tr><tr><td>katex</td><td>【可选】显示katex(当设置katex的per_page: false时，才需要配置，默认 false)</td></tr><tr><td>aplayer</td><td>【可选】在需要的页面加载aplayer的js和css,请参考文章下面的音乐 配置</td></tr><tr><td>highlight_shrink</td><td>【可选】配置代码框是否展开(true/false)(默认为设置中highlight_shrink的配置)</td></tr><tr><td>aside</td><td>【可选】显示侧边栏 (默认 true)</td></tr></tbody></table></div>]]></content>
    
    
    <summary type="html">&lt;h2 id=&quot;Front-matter&quot;&gt;&lt;a href=&quot;#Front-matter&quot; class=&quot;headerlink&quot; title=&quot;Front-matter&quot;&gt;&lt;/a&gt;Front-matter&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Front-matter&lt;/code&gt; 是 &lt;code&gt;markdown&lt;/code&gt; 文件最上方以 &lt;strong&gt;—-&lt;/strong&gt; 分隔的区域，用于指定个别档案的变数。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Page Front-matter&lt;/code&gt; 用于&lt;strong&gt;页面&lt;/strong&gt;配置&lt;br&gt;&lt;code&gt;Post Front-matter&lt;/code&gt; 用于&lt;strong&gt;文章页&lt;/strong&gt;配置&lt;/p&gt;</summary>
    
    
    
    <category term="Hexo+Gitee" scheme="https://www.wjnba.top/categories/Hexo-Gitee/"/>
    
    
    <category term="个人博客" scheme="https://www.wjnba.top/tags/%E4%B8%AA%E4%BA%BA%E5%8D%9A%E5%AE%A2/"/>
    
    <category term="Hexo" scheme="https://www.wjnba.top/tags/Hexo/"/>
    
    <category term="Gitee Pages" scheme="https://www.wjnba.top/tags/Gitee-Pages/"/>
    
  </entry>
  
  <entry>
    <title>键盘按键键码值（keyCode）对照表</title>
    <link href="https://www.wjnba.top/articles/20220829cc1271ddc11d.html"/>
    <id>https://www.wjnba.top/articles/20220829cc1271ddc11d.html</id>
    <published>2022-08-29T07:42:40.000Z</published>
    <updated>2025-12-15T03:40:53.443Z</updated>
    
    <content type="html"><![CDATA[<blockquote><p>键盘事件包含onkeypress onkeydown和onkeyup事件，其中onkeypress事件是在键盘上的某个键被按下并且释放时触发此事件的处理程序，一般用于 键盘上的单键操作。onkeydown事件是在键盘上的某个键被按下时触发此事件的处理程序，一般用于快捷键的操作。onkeyup事件是在键盘上的某个键被按下后松开时触发此事件的处理程序，一般用于快捷键的操作。</p></blockquote><span id="more"></span><h2 id="字母和数字键的键码值-keyCode"><a href="#字母和数字键的键码值-keyCode" class="headerlink" title="字母和数字键的键码值(keyCode)"></a>字母和数字键的键码值(keyCode)</h2><div class="table-container"><table><thead><tr><th style="text-align:center">按键</th><th style="text-align:center">键码</th><th style="text-align:center">按键</th><th style="text-align:center">键码</th><th style="text-align:center">按键</th><th style="text-align:center">键码</th><th style="text-align:center">按键</th><th style="text-align:center">键码</th></tr></thead><tbody><tr><td style="text-align:center">A</td><td style="text-align:center">65</td><td style="text-align:center">J</td><td style="text-align:center">74</td><td style="text-align:center">S</td><td style="text-align:center">83</td><td style="text-align:center">1</td><td style="text-align:center">49</td></tr><tr><td style="text-align:center">B</td><td style="text-align:center">66</td><td style="text-align:center">K</td><td style="text-align:center">75</td><td style="text-align:center">T</td><td style="text-align:center">84</td><td style="text-align:center">2</td><td style="text-align:center">50</td></tr><tr><td style="text-align:center">C</td><td style="text-align:center">67</td><td style="text-align:center">L</td><td style="text-align:center">76</td><td style="text-align:center">U</td><td style="text-align:center">85</td><td style="text-align:center">3</td><td style="text-align:center">51</td></tr><tr><td style="text-align:center">D</td><td style="text-align:center">68</td><td style="text-align:center">M</td><td style="text-align:center">77</td><td style="text-align:center">V</td><td style="text-align:center">86</td><td style="text-align:center">4</td><td style="text-align:center">52</td></tr><tr><td style="text-align:center">E</td><td style="text-align:center">69</td><td style="text-align:center">N</td><td style="text-align:center">78</td><td style="text-align:center">W</td><td style="text-align:center">87</td><td style="text-align:center">5</td><td style="text-align:center">53</td></tr><tr><td style="text-align:center">F</td><td style="text-align:center">70</td><td style="text-align:center">O</td><td style="text-align:center">79</td><td style="text-align:center">X</td><td style="text-align:center">88</td><td style="text-align:center">6</td><td style="text-align:center">54</td></tr><tr><td style="text-align:center">G</td><td style="text-align:center">71</td><td style="text-align:center">P</td><td style="text-align:center">80</td><td style="text-align:center">Y</td><td style="text-align:center">89</td><td style="text-align:center">7</td><td style="text-align:center">55</td></tr><tr><td style="text-align:center">H</td><td style="text-align:center">72</td><td style="text-align:center">Q</td><td style="text-align:center">81</td><td style="text-align:center">Z</td><td style="text-align:center">90</td><td style="text-align:center">8</td><td style="text-align:center">56</td></tr><tr><td style="text-align:center">I</td><td style="text-align:center">73</td><td style="text-align:center">R</td><td style="text-align:center">82</td><td style="text-align:center">0</td><td style="text-align:center">48</td><td style="text-align:center">9</td><td style="text-align:center">57</td></tr></tbody></table></div><h2 id="数字键盘上的键的键码值-keyCode"><a href="#数字键盘上的键的键码值-keyCode" class="headerlink" title="数字键盘上的键的键码值(keyCode)"></a>数字键盘上的键的键码值(keyCode)</h2><div class="table-container"><table><thead><tr><th style="text-align:center">按键</th><th style="text-align:center">键码</th><th style="text-align:center">按键</th><th style="text-align:center">键码</th></tr></thead><tbody><tr><td style="text-align:center">0</td><td style="text-align:center">96</td><td style="text-align:center">8</td><td style="text-align:center">104</td></tr><tr><td style="text-align:center">1</td><td style="text-align:center">97</td><td style="text-align:center">9</td><td style="text-align:center">105</td></tr><tr><td style="text-align:center">2</td><td style="text-align:center">98</td><td style="text-align:center">*</td><td style="text-align:center">106</td></tr><tr><td style="text-align:center">3</td><td style="text-align:center">99</td><td style="text-align:center">+</td><td style="text-align:center">107</td></tr><tr><td style="text-align:center">4</td><td style="text-align:center">100</td><td style="text-align:center">Enter</td><td style="text-align:center">108</td></tr><tr><td style="text-align:center">5</td><td style="text-align:center">101</td><td style="text-align:center">–</td><td style="text-align:center">109</td></tr><tr><td style="text-align:center">6</td><td style="text-align:center">102</td><td style="text-align:center">.</td><td style="text-align:center">110</td></tr><tr><td style="text-align:center">7</td><td style="text-align:center">103</td><td style="text-align:center">/</td><td style="text-align:center">111</td></tr></tbody></table></div><h2 id="功能键键码值-keyCode"><a href="#功能键键码值-keyCode" class="headerlink" title="功能键键码值(keyCode)"></a>功能键键码值(keyCode)</h2><div class="table-container"><table><thead><tr><th style="text-align:center">按键</th><th style="text-align:center">键码</th><th style="text-align:center">按键</th><th style="text-align:center">键码</th></tr></thead><tbody><tr><td style="text-align:center">F1</td><td style="text-align:center">112</td><td style="text-align:center">F7</td><td style="text-align:center">118</td></tr><tr><td style="text-align:center">F2</td><td style="text-align:center">113</td><td style="text-align:center">F8</td><td style="text-align:center">119</td></tr><tr><td style="text-align:center">F3</td><td style="text-align:center">114</td><td style="text-align:center">F9</td><td style="text-align:center">120</td></tr><tr><td style="text-align:center">F4</td><td style="text-align:center">115</td><td style="text-align:center">F10</td><td style="text-align:center">121</td></tr><tr><td style="text-align:center">F5</td><td style="text-align:center">116</td><td style="text-align:center">F11</td><td style="text-align:center">122</td></tr><tr><td style="text-align:center">F6</td><td style="text-align:center">117</td><td style="text-align:center">F12</td><td style="text-align:center">123</td></tr></tbody></table></div><h2 id="控制键键码值-keyCode"><a href="#控制键键码值-keyCode" class="headerlink" title="控制键键码值(keyCode)"></a>控制键键码值(keyCode)</h2><div class="table-container"><table><thead><tr><th style="text-align:center">按键</th><th style="text-align:center">键码</th><th style="text-align:center">按键</th><th style="text-align:center">键码</th><th style="text-align:center">按键</th><th style="text-align:center">键码</th><th style="text-align:center">按键</th><th style="text-align:center">键码</th></tr></thead><tbody><tr><td style="text-align:center">BackSpace</td><td style="text-align:center">8</td><td style="text-align:center">Esc</td><td style="text-align:center">27</td><td style="text-align:center">Right Arrow</td><td style="text-align:center">39</td><td style="text-align:center">-_</td><td style="text-align:center">189</td></tr><tr><td style="text-align:center">Tab</td><td style="text-align:center">9</td><td style="text-align:center">Spacebar</td><td style="text-align:center">32</td><td style="text-align:center">Dw Arrow</td><td style="text-align:center">40</td><td style="text-align:center">.&gt;</td><td style="text-align:center">190</td></tr><tr><td style="text-align:center">Clear</td><td style="text-align:center">12</td><td style="text-align:center">Page Up</td><td style="text-align:center">33</td><td style="text-align:center">Insert</td><td style="text-align:center">45</td><td style="text-align:center">/?</td><td style="text-align:center">191</td></tr><tr><td style="text-align:center">Enter</td><td style="text-align:center">13</td><td style="text-align:center">Page Down</td><td style="text-align:center">34</td><td style="text-align:center">Delete</td><td style="text-align:center">46</td><td style="text-align:center">`~</td><td style="text-align:center">192</td></tr><tr><td style="text-align:center">Shift</td><td style="text-align:center">16</td><td style="text-align:center">End</td><td style="text-align:center">35</td><td style="text-align:center">Num Lock</td><td style="text-align:center">144</td><td style="text-align:center">[{</td><td style="text-align:center">219</td></tr><tr><td style="text-align:center">Control</td><td style="text-align:center">17</td><td style="text-align:center">Home</td><td style="text-align:center">36</td><td style="text-align:center">;:</td><td style="text-align:center">186</td><td style="text-align:center"></td><td style="text-align:center">220</td></tr><tr><td style="text-align:center">Alt</td><td style="text-align:center">18</td><td style="text-align:center">Left Arrow</td><td style="text-align:center">37</td><td style="text-align:center">=+</td><td style="text-align:center">187</td><td style="text-align:center">]}</td><td style="text-align:center">221</td></tr><tr><td style="text-align:center">Cape Lock</td><td style="text-align:center">20</td><td style="text-align:center">Up Arrow</td><td style="text-align:center">38</td><td style="text-align:center">,&lt;</td><td style="text-align:center">188</td><td style="text-align:center">‘“</td><td style="text-align:center">222</td></tr></tbody></table></div>]]></content>
    
    
    <summary type="html">&lt;blockquote&gt;
&lt;p&gt;键盘事件包含onkeypress onkeydown和onkeyup事件，其中onkeypress事件是在键盘上的某个键被按下并且释放时触发此事件的处理程序，一般用于 键盘上的单键操作。onkeydown事件是在键盘上的某个键被按下时触发此事件的处理程序，一般用于快捷键的操作。onkeyup事件是在键盘上的某个键被按下后松开时触发此事件的处理程序，一般用于快捷键的操作。&lt;/p&gt;
&lt;/blockquote&gt;</summary>
    
    
    
    <category term="深入浅出js" scheme="https://www.wjnba.top/categories/%E6%B7%B1%E5%85%A5%E6%B5%85%E5%87%BAjs/"/>
    
    
    <category term="javascript" scheme="https://www.wjnba.top/tags/javascript/"/>
    
  </entry>
  
  <entry>
    <title>Typescript基础之泛型</title>
    <link href="https://www.wjnba.top/articles/202208247dee70e2a1ef.html"/>
    <id>https://www.wjnba.top/articles/202208247dee70e2a1ef.html</id>
    <published>2022-08-24T01:25:17.000Z</published>
    <updated>2025-12-15T03:40:53.436Z</updated>
    
    <content type="html"><![CDATA[<h1 id="TypeSprict-—-泛型"><a href="#TypeSprict-—-泛型" class="headerlink" title="TypeSprict — 泛型"></a>TypeSprict — 泛型</h1><h2 id="TS-—-泛型"><a href="#TS-—-泛型" class="headerlink" title="TS — 泛型"></a><code>TS</code> — 泛型</h2><h3 id="什么是泛型"><a href="#什么是泛型" class="headerlink" title="什么是泛型"></a>什么是泛型</h3><blockquote><p>1.泛型（Generics）是指在定义函数、接口或类的时候，不预先指定具体的类型，而在使用的时候再指定类型的一种特性。</p><p>2.我们不仅要创建一致的定义良好的API，同时也要考虑可重用性。组件不仅能够支持当前的数据类型，同时也能支持未来的数据类型，这在创建大型系统时为你提供了十分灵活的功能。  在像c#和java这样的语言中，可以使用泛型来创建可重用的组件，一个组件可以支持多种类型的数据。这样用户就可以以自己的数据类型来使用组件。  </p></blockquote><span id="more"></span><h3 id="ts函数定义"><a href="#ts函数定义" class="headerlink" title="ts函数定义"></a><code>ts</code>函数定义</h3><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 首先看一下ts函数的定义</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">getData</span>(<span class="params">value: <span class="built_in">string</span></span>): <span class="title">string</span> </span>&#123; <span class="comment">// 传入值和返回值都限制了string类型</span></span><br><span class="line">    <span class="keyword">return</span> <span class="string">&#x27;str&#x27;</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>当需要同时支持多个数类型的时候 这时怎么解决呢？</p><ul><li>用<code>any</code>类型</li></ul><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">getData</span> (<span class="params">value: <span class="built_in">any</span></span>):<span class="title">any</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> value</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 用了any就代表着放弃了类型的检查，一般我们都提倡严格限制类型，这时我们可以利用泛型来解决</span></span><br></pre></td></tr></table></figure><h3 id="泛型的写法"><a href="#泛型的写法" class="headerlink" title="泛型的写法"></a>泛型的写法</h3><blockquote><p>1.我们在函数名后添加了 <T>，其中 T 用来指代任意输入的类型，在后面的输入 value: T 和输出 Array<T> 中即可使用了。<br>2.T表示泛型（也可以取其他名字），具体什么类型是调用这个方法的时候决定的</p></blockquote><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 例子</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">createArray</span>&lt;<span class="title">T</span>&gt;(<span class="params">length: <span class="built_in">number</span>, value: T</span>): <span class="title">Array</span>&lt;<span class="title">T</span>&gt; </span>&#123; </span><br><span class="line">    <span class="keyword">let</span> result: T[] = [];</span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>; i &lt; length; i++) &#123;</span><br><span class="line">        result[i] = value;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> result;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">createArray&lt;<span class="built_in">string</span>&gt;(<span class="number">3</span>, <span class="string">&#x27;x&#x27;</span>); <span class="comment">// [&#x27;x&#x27;, &#x27;x&#x27;, &#x27;x&#x27;]</span></span><br></pre></td></tr></table></figure><h3 id="多个类型参数"><a href="#多个类型参数" class="headerlink" title="多个类型参数"></a>多个类型参数</h3><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">泛型可以定义多个不同类型参数</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">swap</span>&lt;<span class="title">T</span>, <span class="title">U</span>&gt;(<span class="params">tuple: [T, U]</span>): [<span class="title">U</span>, <span class="title">T</span>] </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> [tuple[<span class="number">1</span>], tuple[<span class="number">0</span>]];</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">swap&lt;<span class="built_in">number</span>, <span class="built_in">string</span>&gt;([<span class="number">7</span>, <span class="string">&#x27;seven&#x27;</span>]); <span class="comment">// [&#x27;seven&#x27;, 7]</span></span><br></pre></td></tr></table></figure><h3 id="函数表达式-函数别名-接口-—配合泛型写法"><a href="#函数表达式-函数别名-接口-—配合泛型写法" class="headerlink" title="函数表达式/函数别名/接口 —配合泛型写法"></a>函数表达式/函数别名/接口 —配合泛型写法</h3><ul><li>函数表达式的定义方式</li></ul><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> getArray: &lt;T&gt;<span class="function">(<span class="params">arg: T, times: <span class="built_in">number</span></span>) =&gt;</span> T[]</span><br><span class="line">getArray = <span class="function">(<span class="params">arg: <span class="built_in">any</span>, times: <span class="built_in">number</span></span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> <span class="built_in">Array</span>(times).fill(arg)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ul><li>接口类型</li></ul><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">interface</span> GetArray&lt;T&gt; &#123;</span><br><span class="line">    (arg: T, <span class="attr">times</span>: <span class="built_in">number</span>): T[],</span><br><span class="line">    <span class="attr">array</span>: T[]</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="泛型类"><a href="#泛型类" class="headerlink" title="泛型类"></a>泛型类</h3><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 与泛型接口类型，泛型也可以定义在类的类型定义中</span></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">GenericNumber</span>&lt;<span class="title">T</span>&gt; </span>&#123;</span><br><span class="line">    <span class="attr">zeroValue</span>: T;</span><br><span class="line">    add: <span class="function">(<span class="params">x: T, y: T</span>) =&gt;</span> T;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> myGenericNumber = <span class="keyword">new</span> GenericNumber&lt;<span class="built_in">number</span>&gt;();</span><br><span class="line">myGenericNumber.zeroValue = <span class="number">0</span>;</span><br><span class="line">myGenericNumber.add = <span class="function"><span class="keyword">function</span>(<span class="params">x, y</span>) </span>&#123; <span class="keyword">return</span> x + y; &#125;;</span><br></pre></td></tr></table></figure><blockquote><p> 需要注意的是：类有两部分： 静态部分和实例部分。泛型类值的是实例部分的类型，所以类的静态属性不能使用这个泛型类型</p></blockquote><p>案例：比如有最小堆算法，需要同时支持返回数字和字符串两种类型。通过类的泛型来实现</p><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">myClass</span>&lt;<span class="title">T</span>&gt; </span>&#123;</span><br><span class="line">    <span class="keyword">public</span> list:T[] = [];</span><br><span class="line">    add (value: T): <span class="built_in">void</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.list.push(value)</span><br><span class="line">    &#125;</span><br><span class="line">    min () : <span class="built_in">number</span> &#123;</span><br><span class="line">        <span class="keyword">var</span> min=arr[<span class="number">0</span>];</span><br><span class="line">        list.forEach(<span class="function">(<span class="params">value</span>)=&gt;</span>&#123;</span><br><span class="line">            <span class="keyword">if</span>(value&lt;min)&#123;</span><br><span class="line">                min=value</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;)</span><br><span class="line">        <span class="keyword">return</span> min</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> m = <span class="keyword">new</span> myClass&lt;<span class="built_in">number</span>&gt;() <span class="comment">//实例化，并且指定了泛型T的类型为number</span></span><br><span class="line">m.add(<span class="number">2</span>);</span><br><span class="line">m.add(<span class="number">3</span>);</span><br><span class="line">m.add(<span class="number">5</span>);</span><br><span class="line">m.add(<span class="number">5</span>);</span><br><span class="line">m.add(<span class="number">7</span>);</span><br><span class="line">m.add(<span class="number">8</span>);</span><br><span class="line">alert(m.min()) <span class="comment">//输出了最大值</span></span><br></pre></td></tr></table></figure><h3 id="泛型约束"><a href="#泛型约束" class="headerlink" title="泛型约束"></a>泛型约束</h3><blockquote><p>1.有时候我们想对泛型传入的参数加以约束，这时候使用泛型约束<br>2.思路就是让泛型类型去继承接口或者一些类，让在编译过程去检测传入的泛型是具有当前指定的属性</p></blockquote><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">interface</span> Lengthwise &#123;</span><br><span class="line">    <span class="attr">length</span>: <span class="built_in">number</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">loggingIdentity</span>&lt;<span class="title">T</span> <span class="title">extends</span> <span class="title">Lengthwise</span>&gt;(<span class="params">arg: T</span>): <span class="title">T</span> </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(arg.length);</span><br><span class="line">    <span class="keyword">return</span> arg;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">loggingIdentity(<span class="number">7</span>);<span class="comment">// 传入数字会报错 arg不包含length</span></span><br></pre></td></tr></table></figure><h3 id="泛型参数的默认类型"><a href="#泛型参数的默认类型" class="headerlink" title="泛型参数的默认类型"></a>泛型参数的默认类型</h3><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">createArray</span>&lt;<span class="title">T</span> = <span class="title">string</span>&gt;(<span class="params">length: <span class="built_in">number</span>, value: T</span>): <span class="title">Array</span>&lt;<span class="title">T</span>&gt; </span>&#123;</span><br><span class="line">    <span class="keyword">let</span> result: T[] = [];</span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>; i &lt; length; i++) &#123;</span><br><span class="line">        result[i] = value;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> result;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    
    <summary type="html">&lt;h1 id=&quot;TypeSprict-—-泛型&quot;&gt;&lt;a href=&quot;#TypeSprict-—-泛型&quot; class=&quot;headerlink&quot; title=&quot;TypeSprict — 泛型&quot;&gt;&lt;/a&gt;TypeSprict — 泛型&lt;/h1&gt;&lt;h2 id=&quot;TS-—-泛型&quot;&gt;&lt;a href=&quot;#TS-—-泛型&quot; class=&quot;headerlink&quot; title=&quot;TS — 泛型&quot;&gt;&lt;/a&gt;&lt;code&gt;TS&lt;/code&gt; — 泛型&lt;/h2&gt;&lt;h3 id=&quot;什么是泛型&quot;&gt;&lt;a href=&quot;#什么是泛型&quot; class=&quot;headerlink&quot; title=&quot;什么是泛型&quot;&gt;&lt;/a&gt;什么是泛型&lt;/h3&gt;&lt;blockquote&gt;
&lt;p&gt;1.泛型（Generics）是指在定义函数、接口或类的时候，不预先指定具体的类型，而在使用的时候再指定类型的一种特性。&lt;/p&gt;
&lt;p&gt;2.我们不仅要创建一致的定义良好的API，同时也要考虑可重用性。组件不仅能够支持当前的数据类型，同时也能支持未来的数据类型，这在创建大型系统时为你提供了十分灵活的功能。  在像c#和java这样的语言中，可以使用泛型来创建可重用的组件，一个组件可以支持多种类型的数据。这样用户就可以以自己的数据类型来使用组件。  &lt;/p&gt;
&lt;/blockquote&gt;</summary>
    
    
    
    <category term="Typescript基础" scheme="https://www.wjnba.top/categories/Typescript%E5%9F%BA%E7%A1%80/"/>
    
    
    <category term="Typescript" scheme="https://www.wjnba.top/tags/Typescript/"/>
    
  </entry>
  
  <entry>
    <title>Typescript基础之函数</title>
    <link href="https://www.wjnba.top/articles/20220824ce2fc93679c8.html"/>
    <id>https://www.wjnba.top/articles/20220824ce2fc93679c8.html</id>
    <published>2022-08-24T01:25:05.000Z</published>
    <updated>2025-12-15T03:40:53.436Z</updated>
    
    <content type="html"><![CDATA[<h1 id="TypeSprict-—-函数"><a href="#TypeSprict-—-函数" class="headerlink" title="TypeSprict — 函数"></a>TypeSprict — 函数</h1><h2 id="JS-—-函数的两种表现形式"><a href="#JS-—-函数的两种表现形式" class="headerlink" title="JS — 函数的两种表现形式"></a><code>JS</code> — 函数的两种表现形式</h2><blockquote><p>我们熟知<code>js</code>有两种函数表现形式’函数声明’和’函数表达式’</p></blockquote><h3 id="函数声明"><a href="#函数声明" class="headerlink" title="函数声明"></a>函数声明</h3><span id="more"></span><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 函数声明（Function Declaration）</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">sum</span>(<span class="params">x, y</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> x + y;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="函数的表达式"><a href="#函数的表达式" class="headerlink" title="函数的表达式"></a>函数的表达式</h3><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 函数表达式（Function Expression）</span></span><br><span class="line"><span class="keyword">let</span> mySum = <span class="function"><span class="keyword">function</span> (<span class="params">x, y</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> x + y;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><h3 id="es6-箭头函数"><a href="#es6-箭头函数" class="headerlink" title="es6 箭头函数"></a><code>es6</code> 箭头函数</h3><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> esExample = <span class="function">(<span class="params">name</span>)=&gt;</span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(name)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="TS-—-定义一个函数"><a href="#TS-—-定义一个函数" class="headerlink" title="TS — 定义一个函数"></a><code>TS</code> — 定义一个函数</h2><blockquote><p>将上面的三种写法依次推导成’<code>ts</code>‘的写法</p></blockquote><h3 id="TS-—-函数声明"><a href="#TS-—-函数声明" class="headerlink" title="TS — 函数声明"></a><code>TS</code> — 函数声明</h3><blockquote><p>1.<code>TS</code>以函数的声明的形式，需要定义函数参数中的类型，以及返回类型。 ‘<code>function</code> 函数名(参数:类型):函数返回的类型{}’<br>2.如果函数没有返回类型就是 <code>void</code></p></blockquote><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 返回number类型的值</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">add</span>(<span class="params">arg1:<span class="built_in">number</span>, arg2:<span class="built_in">number</span></span>): <span class="title">number</span></span>&#123;</span><br><span class="line">    <span class="keyword">return</span> arg1 + arg2</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 没有返回值</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">sub</span>(<span class="params">arg1: <span class="built_in">number</span></span>): <span class="title">void</span></span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(arg1）</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><code>TS</code> — 函数函数的表达式/ 箭头函数（定义）</p><blockquote><p>下面两种写法最后编译成’<code>js</code>‘的结果不同，但是却在’<code>TS</code>‘ 表现形式略有区别</p><ul><li>第一个案例只对等号右侧的匿名函数进行了类型定义，在把这个重新被定义的类型函数赋值给了’<code>add</code>‘。</li><li>第二个案例就比较遵循’<code>ts</code>‘ 规则，先定义了一个函数类型，这个类型参数指定的类型，以及函数返回的类型，然后使用的时候在按照定义规范去用</li></ul></blockquote><ul><li>第一种写法</li></ul><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> add = <span class="function">(<span class="params">arg1:<span class="built_in">number</span>,arg2:<span class="built_in">number</span></span>) =&gt;</span> arg1 + arg2</span><br><span class="line">add(<span class="number">1</span>,<span class="number">2</span>) <span class="comment">// 3</span></span><br></pre></td></tr></table></figure><ul><li>第二种写法</li></ul><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 声明一个函数类型包括参数类型和返回类型， ts 箭头函数左面是函数参数，右面是函数返回类型</span></span><br><span class="line"><span class="keyword">let</span> add:<span class="function">(<span class="params">x:<span class="built_in">number</span>,y:<span class="built_in">number</span></span>) =&gt;</span> <span class="built_in">number</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 使用的时候具体函数使用</span></span><br><span class="line">add = <span class="function">(<span class="params">arg1:<span class="built_in">number</span>,arg2:<span class="built_in">number</span></span>) =&gt;</span>&#123; <span class="keyword">return</span> arg1+arg2&#125;</span><br><span class="line">add(<span class="number">1</span>,<span class="number">2</span>) <span class="comment">// 3</span></span><br></pre></td></tr></table></figure><h3 id="使用接口-定义"><a href="#使用接口-定义" class="headerlink" title="使用接口(定义)"></a>使用接口(定义)</h3><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">interface</span> Add &#123;</span><br><span class="line">    (x:<span class="built_in">number</span>,<span class="attr">y</span>:<span class="built_in">number</span>):<span class="built_in">number</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 按照接口格式 规范实现我们的myAdd方法</span></span><br><span class="line"><span class="keyword">let</span> myAdd: Add</span><br><span class="line">myAdd = <span class="function">(<span class="params">x:<span class="built_in">number</span>,y:<span class="built_in">number</span></span>)=&gt;</span>&#123;</span><br><span class="line">    <span class="keyword">return</span> x+y</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 使用</span></span><br><span class="line"><span class="built_in">console</span>.log(myAdd(<span class="number">1</span>,<span class="number">2</span>)) <span class="comment">//3</span></span><br></pre></td></tr></table></figure><h3 id="ts-定义参数可选参数写法-—-‘-’的使用"><a href="#ts-定义参数可选参数写法-—-‘-’的使用" class="headerlink" title="ts 定义参数可选参数写法 — ‘?’的使用"></a><code>ts</code> 定义参数可选参数写法 — ‘?’的使用</h3><blockquote><p>1.<code>JavaScript</code>里，每个参数都是可选的，可传可不传。但’TS’不同每个函数参数都是必须的，可以理解定义则必须使用</p><p>2.但是有时候不想将每一个定义的参数都传值使用，这时候就可以用’?’ 的形式来将参数变成可选的和接口中使用的方式相似</p><p>3.需要注意的是，可选参数必须接在必需参数最后面。</p></blockquote><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> AddFun: <span class="function">(<span class="params">x:<span class="built_in">number</span>,y:<span class="built_in">number</span>,z?:<span class="built_in">any</span></span>) =&gt;</span> <span class="built_in">number</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> add:AddFun</span><br><span class="line">add = <span class="function">(<span class="params">x:<span class="built_in">number</span>,y:<span class="built_in">number</span></span>)=&gt;</span>&#123;</span><br><span class="line">    <span class="keyword">return</span> x+y</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 增加了一个z参数</span></span><br><span class="line">add = <span class="function">(<span class="params">x:<span class="built_in">number</span>,y:<span class="built_in">number</span>,z:<span class="built_in">number</span></span>)=&gt;</span>&#123;</span><br><span class="line">    <span class="keyword">return</span> x+y+z</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ul><li>官方给的案例</li></ul><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">buildName</span>(<span class="params">firstName: <span class="built_in">string</span>, lastName?: <span class="built_in">string</span></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (lastName)</span><br><span class="line">        <span class="keyword">return</span> firstName + <span class="string">&quot; &quot;</span> + lastName;</span><br><span class="line">    <span class="keyword">else</span></span><br><span class="line">        <span class="keyword">return</span> firstName;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> result1 = buildName(<span class="string">&quot;Bob&quot;</span>);  <span class="comment">// works correctly now</span></span><br><span class="line"><span class="keyword">let</span> result2 = buildName(<span class="string">&quot;Bob&quot;</span>, <span class="string">&quot;Adams&quot;</span>, <span class="string">&quot;Sr.&quot;</span>);  <span class="comment">// error, too many parameters</span></span><br><span class="line"><span class="keyword">let</span> result3 = buildName(<span class="string">&quot;Bob&quot;</span>, <span class="string">&quot;Adams&quot;</span>);  <span class="comment">// ah, just right</span></span><br></pre></td></tr></table></figure><p><code>TS</code>函数 — 设置函数参数默认值</p><blockquote><p>1.和<code>es6</code> 一样直接在参数中给要增加的参数赋值默认参数即可<br>2.当有默认参数的时候，默认参数会自动变成一个可选参数,不填就用默认参数，填就用填写参数，但是’?’形式的可选参数依然必须在末尾</p></blockquote><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">buildName</span>(<span class="params">firstName: <span class="built_in">string</span>, lastName: <span class="built_in">string</span> = <span class="string">&#x27;Cat&#x27;</span></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> firstName + <span class="string">&#x27; &#x27;</span> + lastName;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">let</span> tomcat = buildName(<span class="string">&#x27;Tom&#x27;</span>, <span class="string">&#x27;Cat&#x27;</span>);</span><br><span class="line"><span class="keyword">let</span> tom = buildName(<span class="string">&#x27;Tom&#x27;</span>);</span><br></pre></td></tr></table></figure><ul><li>案例二</li></ul><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">buildName</span>(<span class="params">firstName = <span class="string">&quot;Will&quot;</span>, lastName: <span class="built_in">string</span></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> firstName + <span class="string">&quot; &quot;</span> + lastName;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> result1 = buildName(<span class="string">&quot;Bob&quot;</span>);                  <span class="comment">// 错误，少了个参数</span></span><br><span class="line"><span class="keyword">let</span> result2 = buildName(<span class="string">&quot;Bob&quot;</span>, <span class="string">&quot;Adams&quot;</span>, <span class="string">&quot;Sr.&quot;</span>);  <span class="comment">// 错误，多了个参数</span></span><br><span class="line"><span class="keyword">let</span> result3 = buildName(<span class="string">&quot;Bob&quot;</span>, <span class="string">&quot;Adams&quot;</span>);         <span class="comment">//  Bob Adams</span></span><br><span class="line"><span class="keyword">let</span> result4 = buildName(<span class="literal">undefined</span>, <span class="string">&quot;Adams&quot;</span>);     <span class="comment">// Will Adams</span></span><br></pre></td></tr></table></figure><h3 id="TS函数-—-设置剩余参数"><a href="#TS函数-—-设置剩余参数" class="headerlink" title="TS函数 — 设置剩余参数"></a><code>TS</code>函数 — 设置剩余参数</h3><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">1.</span> 使用的场景：同时操作多个参数，或者在不确定有多少个参数的时候</span><br><span class="line"><span class="number">2.</span> 对es6中的<span class="string">&#x27;...&#x27;</span> 简单讲解:</span><br><span class="line">    <span class="keyword">var</span> a = [<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>]</span><br><span class="line">    <span class="keyword">var</span> b = [...a]</span><br><span class="line">    <span class="built_in">console</span>.log(b) <span class="comment">//  [1, 2, 3] </span></span><br><span class="line">    <span class="comment">// 对象解构</span></span><br><span class="line">    <span class="keyword">var</span> aObj = &#123;<span class="string">&#x27;a&#x27;</span>:<span class="number">1</span>&#125;</span><br><span class="line">    <span class="keyword">var</span> bObj2 = &#123;...aObj,<span class="string">&quot;b&quot;</span>:<span class="number">2</span>&#125;</span><br><span class="line">    <span class="built_in">console</span>.log(bObj2 ) <span class="comment">// &#123;a: 1, b: 2&#125;</span></span><br><span class="line"><span class="number">4.</span> 在<span class="string">&#x27;ts&#x27;</span> 中也是<span class="string">&#x27;...&#x27;</span>但需要定义数组类型参数<span class="string">&#x27; ...args: number[]&#x27;</span></span><br><span class="line"><span class="number">5.</span> 需要注意的是，剩余参数必须接在必需参数最后面。</span><br></pre></td></tr></table></figure><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> handleData = <span class="function">(<span class="params">arg1: <span class="built_in">number</span>, ...args: <span class="built_in">number</span>[]</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(arg1, arg2)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="函数重载"><a href="#函数重载" class="headerlink" title="函数重载"></a>函数重载</h3><blockquote><p>1.有时候函数会因为传递的参数不同，导致函数参数返回的时候类型值不同一种解决办法就是利用’联合类型’</p><p> 但是有个缺点，就是不能够精确的表达输入为数字的时候，输出也应该为数字 输入为字符串的时候，输出也应该为字符串另一种解决办法就是利用’重载’<br>2.官方文档的标准解释：重载允许一个函数接受不同数量或类型的参数时，作出不同的处理。</p></blockquote><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">reverse</span>(<span class="params">x: <span class="built_in">number</span> | <span class="built_in">string</span></span>): <span class="title">number</span> | <span class="title">string</span> </span>&#123;</span><br><span class="line">     <span class="keyword">if</span> (<span class="keyword">typeof</span> x === <span class="string">&#x27;number&#x27;</span>) &#123;</span><br><span class="line">         <span class="keyword">return</span> <span class="built_in">Number</span>(x.toString().split(<span class="string">&#x27;&#x27;</span>).reverse().join(<span class="string">&#x27;&#x27;</span>));</span><br><span class="line">     &#125; <span class="keyword">else</span> <span class="keyword">if</span> (<span class="keyword">typeof</span> x === <span class="string">&#x27;string&#x27;</span>) &#123;</span><br><span class="line">         <span class="keyword">return</span> x.split(<span class="string">&#x27;&#x27;</span>).reverse().join(<span class="string">&#x27;&#x27;</span>);</span><br><span class="line">     &#125;</span><br><span class="line"> &#125;</span><br></pre></td></tr></table></figure><ul><li>用重载定义多个 <code>reverse</code> 的函数类型</li></ul><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">reverse</span>(<span class="params">x: <span class="built_in">number</span></span>): <span class="title">number</span></span>;</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">reverse</span>(<span class="params">x: <span class="built_in">string</span></span>): <span class="title">string</span></span>;</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">reverse</span>(<span class="params">x: <span class="built_in">number</span> | <span class="built_in">string</span></span>): <span class="title">number</span> | <span class="title">string</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (<span class="keyword">typeof</span> x === <span class="string">&#x27;number&#x27;</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="built_in">Number</span>(x.toString().split(<span class="string">&#x27;&#x27;</span>).reverse().join(<span class="string">&#x27;&#x27;</span>));</span><br><span class="line">    &#125; <span class="keyword">else</span> <span class="keyword">if</span> (<span class="keyword">typeof</span> x === <span class="string">&#x27;string&#x27;</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> x.split(<span class="string">&#x27;&#x27;</span>).reverse().join(<span class="string">&#x27;&#x27;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><blockquote><p>注意，<code>TypeScript</code> 会优先从最前面的函数定义开始匹配，所以多个函数定义如果有包含关系，需要优先把精确的定义写在前面。</p></blockquote>]]></content>
    
    
    <summary type="html">&lt;h1 id=&quot;TypeSprict-—-函数&quot;&gt;&lt;a href=&quot;#TypeSprict-—-函数&quot; class=&quot;headerlink&quot; title=&quot;TypeSprict — 函数&quot;&gt;&lt;/a&gt;TypeSprict — 函数&lt;/h1&gt;&lt;h2 id=&quot;JS-—-函数的两种表现形式&quot;&gt;&lt;a href=&quot;#JS-—-函数的两种表现形式&quot; class=&quot;headerlink&quot; title=&quot;JS — 函数的两种表现形式&quot;&gt;&lt;/a&gt;&lt;code&gt;JS&lt;/code&gt; — 函数的两种表现形式&lt;/h2&gt;&lt;blockquote&gt;
&lt;p&gt;我们熟知&lt;code&gt;js&lt;/code&gt;有两种函数表现形式’函数声明’和’函数表达式’&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;函数声明&quot;&gt;&lt;a href=&quot;#函数声明&quot; class=&quot;headerlink&quot; title=&quot;函数声明&quot;&gt;&lt;/a&gt;函数声明&lt;/h3&gt;</summary>
    
    
    
    <category term="Typescript基础" scheme="https://www.wjnba.top/categories/Typescript%E5%9F%BA%E7%A1%80/"/>
    
    
    <category term="Typescript" scheme="https://www.wjnba.top/tags/Typescript/"/>
    
  </entry>
  
  <entry>
    <title>Typescript基础之类</title>
    <link href="https://www.wjnba.top/articles/2022082491102b34e243.html"/>
    <id>https://www.wjnba.top/articles/2022082491102b34e243.html</id>
    <published>2022-08-24T01:24:46.000Z</published>
    <updated>2025-12-15T03:40:53.437Z</updated>
    
    <content type="html"><![CDATA[<h2 id="TypeSprict-—-类"><a href="#TypeSprict-—-类" class="headerlink" title="TypeSprict — 类"></a>TypeSprict — 类</h2><blockquote><p><code>JavaScript</code> 通过构造函数实现类的概念，通过原型链实现继承。而在 <code>ES6</code> 中，我们终于迎来了 <code>class</code>。<br><code>TypeScript</code> 除了实现了所有 <code>ES6</code> 中的类的功能以外，还添加了一些新的用法。</p></blockquote><span id="more"></span><h3 id="TS-—-类的概念"><a href="#TS-—-类的概念" class="headerlink" title="TS — 类的概念"></a><code>TS</code> — 类的概念</h3><blockquote><ol><li>类(<code>Class</code>)：定义了一件事物的抽象特点，包含它的属性和方法</li><li>对象（<code>Object</code>）：类的实例，通过 <code>new</code> 生成</li><li><p>面向对象（<code>OOP</code>）的三大特性：封装、继承、多态</p><ul><li>封装（<code>Encapsulation</code>）：将对数据的操作细节隐藏起来，只暴露对外的接口。</li><li>继承（<code>Inheritance</code>）：子类继承父类，子类除了拥有父类的所有特性外，还有一些更具体的特性。</li><li>多态（<code>Polymorphism</code>）：由继承而产生了相关的不同的类，对同一个方法可以有不同的响应。</li></ul></li><li><p>存取器（<code>getter</code> &amp; <code>setter</code>）：用以改变属性的读取和赋值行为</p></li><li>修饰符（<code>Modifiers</code>）：修饰符是一些关键字，用于限定成员或类型的性质。比如 public 表示公有属性或方法</li><li>抽象类（<code>Abstract Class</code>）：抽象类是供其他类继承的基类，抽象类不允许被实例化。<br>抽象类中的抽象方法必须在子类中被实现</li><li>接口（<code>Interfaces</code>）：不同类之间公有的属性或方法，可以抽象成一个接口。<br>接口可以被类实现（<code>implements</code>）。一个类只能继承自另一个类，但是可以实现多个接口</li></ol></blockquote><h4 id="创建一个简单的-ts-类"><a href="#创建一个简单的-ts-类" class="headerlink" title="创建一个简单的 ts 类"></a>创建一个简单的 ts 类</h4><blockquote><p><code>class</code> 定义类，使用 <code>constructor</code> 定义构造函数。通过 <code>new</code> 生成新实例的时候，会自动调用构造函数。</p></blockquote><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Animal</span> </span>&#123;</span><br><span class="line">  <span class="function"><span class="title">constructor</span>(<span class="params">name</span>)</span> &#123;</span><br><span class="line">    <span class="built_in">this</span>.name = name;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="function"><span class="title">sayHi</span>(<span class="params"></span>)</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="string">`My name is <span class="subst">$&#123;<span class="built_in">this</span>.name&#125;</span>`</span>;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> a = <span class="keyword">new</span> Animal(<span class="string">&quot;Jack&quot;</span>);</span><br><span class="line"><span class="built_in">console</span>.log(a.sayHi()); <span class="comment">// My name is Jack</span></span><br></pre></td></tr></table></figure><h5 id="继承"><a href="#继承" class="headerlink" title="继承"></a>继承</h5><blockquote><p>使用 <code>extends</code> 关键字实现继承，子类中使用 <code>super</code> 关键字来调用父类的构造函数和方法。</p></blockquote><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Animal</span> </span>&#123;</span><br><span class="line">  <span class="keyword">public</span> name: <span class="built_in">string</span>;</span><br><span class="line">  <span class="function"><span class="title">constructor</span>(<span class="params">name</span>)</span> &#123;</span><br><span class="line">    <span class="built_in">this</span>.name = name;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="function"><span class="title">sayHi</span>(<span class="params"></span>)</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="string">`My name is <span class="subst">$&#123;<span class="built_in">this</span>.name&#125;</span>`</span>;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Cat</span> <span class="keyword">extends</span> <span class="title">Animal</span> </span>&#123;</span><br><span class="line">  <span class="function"><span class="title">constructor</span>(<span class="params">name: <span class="built_in">string</span></span>)</span> &#123;</span><br><span class="line">    <span class="built_in">super</span>(name); <span class="comment">// 调用父类的 constructor(name)</span></span><br><span class="line">  &#125;</span><br><span class="line">  <span class="function"><span class="title">sayHi</span>(<span class="params"></span>)</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="string">&quot;Meow, &quot;</span> + <span class="built_in">super</span>.sayHi(); <span class="comment">// 调用父类的 sayHi()</span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="public-private-protected—-公共-私有-受保护的"><a href="#public-private-protected—-公共-私有-受保护的" class="headerlink" title="public / private / protected— 公共/私有/受保护的"></a><code>public</code> / <code>private</code> / <code>protected</code>— 公共/私有/受保护的</h3><h4 id="public-—-公共"><a href="#public-—-公共" class="headerlink" title="public — 公共"></a><code>public</code> — 公共</h4><blockquote><p>‘<code>public</code>‘修饰的属性或方法是公有的，可以在任何地方被访问到，默认所有的属性和方法都是 ‘<code>public</code>‘的</p></blockquote><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Animal</span> </span>&#123;</span><br><span class="line">  <span class="keyword">public</span> name;</span><br><span class="line">  <span class="keyword">public</span> <span class="function"><span class="title">constructor</span>(<span class="params">name</span>)</span> &#123;</span><br><span class="line">    <span class="built_in">this</span>.name = name;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> a = <span class="keyword">new</span> Animal(<span class="string">&quot;Jack&quot;</span>);</span><br><span class="line"><span class="built_in">console</span>.log(a.name); <span class="comment">// Jack</span></span><br><span class="line">a.name = <span class="string">&quot;Tom&quot;</span>;</span><br><span class="line"><span class="built_in">console</span>.log(a.name); <span class="comment">// Tom</span></span><br></pre></td></tr></table></figure><h4 id="private-—-私有的"><a href="#private-—-私有的" class="headerlink" title="private — 私有的"></a><code>private</code> — 私有的</h4><blockquote><p>当成员被标记成<code>private</code>时，它就不能在声明它的类的外部访问，简单的说，只有自己的<code>class</code>内部可以访问，即使是自己的’实例’，’继承的子类’ 都无法访问被’<code>private</code>‘修饰的内容</p></blockquote><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Animal</span> </span>&#123;</span><br><span class="line">  <span class="keyword">private</span> name: <span class="built_in">string</span>;</span><br><span class="line">  <span class="function"><span class="title">constructor</span>(<span class="params">name: <span class="built_in">string</span></span>)</span> &#123;</span><br><span class="line">    <span class="built_in">this</span>.name = name; <span class="comment">// 能调用private修饰的</span></span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">public</span> <span class="function"><span class="title">getName</span>(<span class="params"></span>)</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="string">`我的名字<span class="subst">$&#123;<span class="built_in">this</span>.name&#125;</span>`</span>; <span class="comment">// 能调用private修饰的</span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Cat</span> <span class="keyword">extends</span> <span class="title">Animal</span> </span>&#123;</span><br><span class="line">  <span class="function"><span class="title">constructor</span>(<span class="params">name: <span class="built_in">string</span></span>)</span> &#123;</span><br><span class="line">    <span class="built_in">super</span>(name);</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="function"><span class="title">getTest</span>(<span class="params"></span>)</span> &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="built_in">this</span>.name); <span class="comment">// 错误提示：属性“name”为私有属性，只能在类“Animal ”中访问。</span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> dog = <span class="keyword">new</span> Animal(<span class="string">&quot;dog&quot;</span>);</span><br><span class="line"><span class="comment">// dog.name = &quot;Anne&quot; // 提示错误：属性“name”为私有属性，只能在类“Animal”中访问。</span></span><br><span class="line"><span class="built_in">console</span>.log(dog.getName()); <span class="comment">// 可以访问，打印结果：我的名字Anne</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> cat = <span class="keyword">new</span> Cat(<span class="string">&quot;cat&quot;</span>);</span><br><span class="line"><span class="comment">// cat.getTest() // 这里是错误的 因为Cat 类也无法使用继承父类的私有属性或者方法</span></span><br></pre></td></tr></table></figure><h4 id="protected-—-受保护的"><a href="#protected-—-受保护的" class="headerlink" title="protected — 受保护的"></a><code>protected</code> — 受保护的</h4><blockquote><p>1.修饰的属性或方法是受保护的，它和 <code>private</code> 类似，区别是它在子类中也是允许被访问的，简单的 说’子类是可以访问 <code>protected</code> 修饰的’ 实例是不可以的</p><p> 2.修饰的是’<code>constructor</code>‘ 则当前类不能创建实例</p></blockquote><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Animal</span> </span>&#123;</span><br><span class="line">  <span class="keyword">protected</span> name: <span class="built_in">string</span>;</span><br><span class="line">  <span class="keyword">protected</span> <span class="function"><span class="title">constructor</span>(<span class="params">name: <span class="built_in">string</span></span>)</span> &#123;</span><br><span class="line">    <span class="built_in">this</span>.name = name;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">protected</span> <span class="function"><span class="title">getName</span>(<span class="params"></span>)</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="built_in">this</span>.name;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//protected 修饰constructor不能创建实例 报错提示：类“Animal”的构造函数是受保护的，仅可在类声明中访问。</span></span><br><span class="line"><span class="comment">// const cat = new Animal (18)</span></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Dog</span> <span class="keyword">extends</span> <span class="title">Animal</span> </span>&#123;</span><br><span class="line">  <span class="function"><span class="title">constructor</span>(<span class="params">name: <span class="built_in">string</span></span>)</span> &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="built_in">super</span>.getName()); <span class="comment">// 可以访问父类中的protected方法</span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">const</span> dog = <span class="keyword">new</span> Dog(<span class="string">&quot;Laura&quot;</span>);</span><br></pre></td></tr></table></figure><h3 id="其他特性"><a href="#其他特性" class="headerlink" title="其他特性"></a>其他特性</h3><h4 id="readonly-—-只读属性"><a href="#readonly-—-只读属性" class="headerlink" title="readonly — 只读属性"></a><code>readonly</code> — 只读属性</h4><blockquote><p>可以使用 <code>readonly</code> 关键字将属性设置为只读的。</p></blockquote><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Animal</span> </span>&#123;</span><br><span class="line">  <span class="keyword">readonly</span> name;</span><br><span class="line">  <span class="keyword">public</span> <span class="function"><span class="title">constructor</span>(<span class="params">name</span>)</span> &#123;</span><br><span class="line">    <span class="built_in">this</span>.name = name;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> a = <span class="keyword">new</span> Animal(<span class="string">&quot;Jack&quot;</span>);</span><br><span class="line"><span class="built_in">console</span>.log(a.name); <span class="comment">// Jack</span></span><br><span class="line">a.name = <span class="string">&quot;Tom&quot;</span>; <span class="comment">// 错误 name是只读的</span></span><br></pre></td></tr></table></figure><h4 id="静态属性-—-static-修饰"><a href="#静态属性-—-static-修饰" class="headerlink" title="静态属性 — static 修饰"></a>静态属性 — <code>static</code> 修饰</h4><blockquote><p>1.’<code>ts</code>‘ 提供了 静态属性，属性和方法都是’<code>static</code>‘ 修饰 </p><p>2.静态方法没法直接调用类里面的属性，当想要调用类里面的属性的时候需要声明静态的属性</p></blockquote><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Animal</span> </span>&#123;</span><br><span class="line">  <span class="keyword">public</span> <span class="keyword">static</span> <span class="function"><span class="title">getName</span>(<span class="params"></span>)</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> Animal.name;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">private</span> <span class="keyword">static</span> name: <span class="built_in">string</span> = <span class="number">18</span>;</span><br><span class="line">  <span class="function"><span class="title">constructor</span>(<span class="params"></span>)</span> &#123;&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">const</span> p = <span class="keyword">new</span> Animal();</span><br><span class="line"><span class="comment">// console.log(p.age) // age 是静态的属性 所以实例是不能访问的</span></span><br><span class="line"><span class="comment">// console.log(Animal.age) // 虽然有了类但是也是不能访问的，因为用了private修饰用public可以访问</span></span><br></pre></td></tr></table></figure><h4 id="ts-的-getter-setter"><a href="#ts-的-getter-setter" class="headerlink" title="ts 的 getter /setter"></a><code>ts</code> 的 <code>getter</code> /<code>setter</code></h4><blockquote><p>使用 <code>getter</code> 和 <code>setter</code> 来改变属性的赋值和读取行为</p></blockquote><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Animal</span> </span>&#123;</span><br><span class="line">  <span class="function"><span class="title">constructor</span>(<span class="params">name</span>)</span> &#123;</span><br><span class="line">    <span class="built_in">this</span>.name = name;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">get</span> <span class="title">name</span>() &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="string">&quot;Jack&quot;</span>;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">set</span> <span class="title">name</span>(<span class="params">value</span>) &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&quot;setter: &quot;</span> + value);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> a = <span class="keyword">new</span> Animal(<span class="string">&quot;Kitty&quot;</span>); <span class="comment">// setter: Kitty</span></span><br><span class="line">a.name = <span class="string">&quot;Tom&quot;</span>; <span class="comment">// setter: Tom</span></span><br><span class="line"><span class="built_in">console</span>.log(a.name); <span class="comment">// Jack</span></span><br></pre></td></tr></table></figure><h4 id="抽象类-abstract"><a href="#抽象类-abstract" class="headerlink" title="抽象类 abstract"></a>抽象类 <code>abstract</code></h4><blockquote><ol><li>抽象类是不允许被实例化的</li><li>继承抽象类的类必须去实现实例中的抽象类中的’抽象方法’和’抽象属性’</li></ol></blockquote><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">abstract</span> <span class="class"><span class="keyword">class</span> <span class="title">Animal</span> </span>&#123;</span><br><span class="line">  <span class="keyword">public</span> name;</span><br><span class="line">  <span class="keyword">public</span> <span class="function"><span class="title">constructor</span>(<span class="params">name</span>)</span> &#123;</span><br><span class="line">    <span class="built_in">this</span>.name = name;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">public</span> <span class="keyword">abstract</span> sayHi();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Cat</span> <span class="keyword">extends</span> <span class="title">Animal</span> </span>&#123;</span><br><span class="line">  <span class="keyword">public</span> <span class="function"><span class="title">sayHi</span>(<span class="params"></span>)</span> &#123;</span><br><span class="line">    <span class="comment">// 实现抽象类的抽象方法</span></span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">`Meow, My name is <span class="subst">$&#123;<span class="built_in">this</span>.name&#125;</span>`</span>);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">let</span> cat = <span class="keyword">new</span> Cat(<span class="string">&quot;Tom&quot;</span>);</span><br></pre></td></tr></table></figure>]]></content>
    
    
    <summary type="html">&lt;h2 id=&quot;TypeSprict-—-类&quot;&gt;&lt;a href=&quot;#TypeSprict-—-类&quot; class=&quot;headerlink&quot; title=&quot;TypeSprict — 类&quot;&gt;&lt;/a&gt;TypeSprict — 类&lt;/h2&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;JavaScript&lt;/code&gt; 通过构造函数实现类的概念，通过原型链实现继承。而在 &lt;code&gt;ES6&lt;/code&gt; 中，我们终于迎来了 &lt;code&gt;class&lt;/code&gt;。&lt;br&gt;&lt;code&gt;TypeScript&lt;/code&gt; 除了实现了所有 &lt;code&gt;ES6&lt;/code&gt; 中的类的功能以外，还添加了一些新的用法。&lt;/p&gt;
&lt;/blockquote&gt;</summary>
    
    
    
    <category term="Typescript基础" scheme="https://www.wjnba.top/categories/Typescript%E5%9F%BA%E7%A1%80/"/>
    
    
    <category term="Typescript" scheme="https://www.wjnba.top/tags/Typescript/"/>
    
  </entry>
  
</feed>
