<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Vue.js on Last Stand</title><link>https://amatsuzero.github.io/LastStand/posts/frontend/vue/</link><description>Recent content in Vue.js on Last Stand</description><generator>Hugo</generator><language>zh-cn</language><lastBuildDate>Wed, 25 Dec 2024 00:00:00 +0800</lastBuildDate><atom:link href="https://amatsuzero.github.io/LastStand/posts/frontend/vue/index.xml" rel="self" type="application/rss+xml"/><item><title>Vue实例挂载</title><link>https://amatsuzero.github.io/LastStand/posts/frontend/vue/vue-001/</link><pubDate>Fri, 04 Oct 2024 00:00:00 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/frontend/vue/vue-001/</guid><description>&lt;h3 id="一思考"&gt;&lt;strong&gt;一、思考&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;我们都听过知其然知其所以然这句话&lt;/p&gt;
&lt;p&gt;那么不知道大家是否思考过&lt;code&gt;new Vue()&lt;/code&gt;这个过程中究竟做了些什么？&lt;/p&gt;
&lt;p&gt;过程中是如何完成数据的绑定，又是如何将数据渲染到视图的等等&lt;/p&gt;
&lt;h3 id="一分析"&gt;&lt;strong&gt;一、分析&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;首先找到&lt;code&gt;vue&lt;/code&gt;的构造函数&lt;/p&gt;
&lt;p&gt;源码位置：src\core\instance\index.js&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Vue&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;options&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;process&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;env&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;NODE_ENV&lt;/span&gt; &lt;span style="color:#f92672"&gt;!==&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;production&amp;#39;&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;!&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;this&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;instanceof&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Vue&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;warn&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;Vue is a constructor and should be called with the `new` keyword&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;_init&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;options&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;options&lt;/code&gt;是用户传递过来的配置项，如&lt;code&gt;data、methods&lt;/code&gt;等常用的方法&lt;/p&gt;
&lt;p&gt;&lt;code&gt;vue&lt;/code&gt;构建函数调用&lt;code&gt;_init&lt;/code&gt;方法，但我们发现本文件中并没有此方法，但仔细可以看到文件下方定定义了很多初始化方法&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;initMixin&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;Vue&lt;/span&gt;); &lt;span style="color:#75715e"&gt;// 定义 _init
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;stateMixin&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;Vue&lt;/span&gt;); &lt;span style="color:#75715e"&gt;// 定义 $set $get $delete $watch 等
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;eventsMixin&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;Vue&lt;/span&gt;); &lt;span style="color:#75715e"&gt;// 定义事件 $on $once $off $emit
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;lifecycleMixin&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;Vue&lt;/span&gt;);&lt;span style="color:#75715e"&gt;// 定义 _update $forceUpdate $destroy
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;renderMixin&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;Vue&lt;/span&gt;); &lt;span style="color:#75715e"&gt;// 定义 _render 返回虚拟dom
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;首先可以看&lt;code&gt;initMixin&lt;/code&gt;方法，发现该方法在&lt;code&gt;Vue&lt;/code&gt;原型上定义了&lt;code&gt;_init&lt;/code&gt;方法&lt;/p&gt;
&lt;p&gt;源码位置：src\core\instance\init.js&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;Vue&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;prototype&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;_init&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;options&lt;/span&gt;&lt;span style="color:#f92672"&gt;?:&lt;/span&gt; Object) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;vm&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Component&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// a uid
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;vm&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;_uid&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;uid&lt;/span&gt;&lt;span style="color:#f92672"&gt;++&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;startTag&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;endTag&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;/* istanbul ignore if */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;process&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;env&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;NODE_ENV&lt;/span&gt; &lt;span style="color:#f92672"&gt;!==&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;production&amp;#39;&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;config&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;performance&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;mark&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;startTag&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;`vue-perf-start:&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;vm&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;_uid&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;endTag&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;`vue-perf-end:&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;vm&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;_uid&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;mark&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;startTag&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// a flag to avoid this being observed
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;vm&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;_isVue&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// merge options
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 合并属性，判断初始化的是否是组件，这里合并主要是 mixins 或 extends 的方法
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;options&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;options&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;_isComponent&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// optimize internal component instantiation
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// since dynamic options merging is pretty slow, and none of the
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// internal component options needs special treatment.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;initInternalComponent&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;vm&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;options&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; } &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; { &lt;span style="color:#75715e"&gt;// 合并vue属性
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;vm&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;$options&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;mergeOptions&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;resolveConstructorOptions&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;vm&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;constructor&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;options&lt;/span&gt; &lt;span style="color:#f92672"&gt;||&lt;/span&gt; {},
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;vm&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; )
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;/* istanbul ignore else */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;process&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;env&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;NODE_ENV&lt;/span&gt; &lt;span style="color:#f92672"&gt;!==&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;production&amp;#39;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 初始化proxy拦截器
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;initProxy&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;vm&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; } &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;vm&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;_renderProxy&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;vm&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// expose real self
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;vm&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;_self&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;vm&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 初始化组件生命周期标志位
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;initLifecycle&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;vm&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 初始化组件事件侦听
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;initEvents&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;vm&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 初始化渲染方法
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;initRender&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;vm&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;callHook&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;vm&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;beforeCreate&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 初始化依赖注入内容，在初始化data、props之前
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;initInjections&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;vm&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// resolve injections before data/props
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 初始化props/data/method/watch/methods
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;initState&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;vm&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;initProvide&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;vm&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// resolve provide after data/props
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;callHook&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;vm&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;created&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;/* istanbul ignore if */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;process&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;env&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;NODE_ENV&lt;/span&gt; &lt;span style="color:#f92672"&gt;!==&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;production&amp;#39;&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;config&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;performance&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;mark&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;vm&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;_name&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;formatComponentName&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;vm&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;mark&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;endTag&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;measure&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;`vue &lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;vm&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;_name&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt; init`&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;startTag&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;endTag&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 挂载元素
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;vm&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;$options&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;el&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;vm&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;$mount&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;vm&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;$options&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;el&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;仔细阅读上面的代码，我们得到以下结论：&lt;/p&gt;</description></item><item><title>数据绑定</title><link>https://amatsuzero.github.io/LastStand/posts/frontend/vue/vue-002/</link><pubDate>Fri, 04 Oct 2024 00:00:00 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/frontend/vue/vue-002/</guid><description>&lt;h3 id="1-定义"&gt;1. 定义&lt;/h3&gt;
&lt;h4 id="11-双向绑定--单向绑定"&gt;&lt;strong&gt;1.1 双向绑定 &amp;amp; 单向绑定&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;vue的双向绑定，即数据与视图的&lt;code&gt;响应式&lt;/code&gt;设计。具体表现为：&lt;code&gt;View&lt;/code&gt;的改变能实时让&lt;code&gt;Model&lt;/code&gt;发生变化，而&lt;code&gt;Model&lt;/code&gt;的变化也能实时更新&lt;code&gt;View&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;什么情况下用户可以更新View呢？如：&lt;code&gt;填写表单&lt;/code&gt;。当用户填写表单时，View的状态就被更新了，如果此时MVVM框架可以自动更新Model的状态，那就相当于把Model和View做了双向绑定。&lt;/p&gt;
&lt;p&gt;注意区别：&lt;code&gt;单向数据绑定&lt;/code&gt;，所有数据只有一份，一旦数据变化，就去更新页面(只有data&amp;ndash;&amp;gt;DOM，没有DOM&amp;ndash;&amp;gt;data)。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;用户在页面作出更新，需要用户手动收集(双向绑定是自动收集)，在合并到原有的数据中。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Vue.js中的v-model主要用在表单的input输入框，完成视图和数据的双向绑定：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;html&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;head&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style="color:#f92672"&gt;head&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;body&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;div&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;id&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;app&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;input&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;type&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;text&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;v-model&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;message&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;p&lt;/span&gt;&amp;gt;{{message}}&amp;lt;/&lt;span style="color:#f92672"&gt;p&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;app&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Vue&lt;/span&gt;({
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;el&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;#app&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;message&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; });
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;body&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;html&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="12-v-model来添加双向绑定"&gt;&lt;strong&gt;1.2 v-model来添加双向绑定&lt;/strong&gt;&lt;/h4&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;input&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;v-model&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;xxx&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;&amp;lt;!-- 上面的代码等价于 --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;input&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;:value&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;xxx&amp;#34;&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;@&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;input&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;xxx = $event.target.value&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;&amp;lt;!-- 双向绑定 = 单向绑定 + UI事件监听 --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="13-双向绑定单向绑定的优缺点"&gt;&lt;strong&gt;1.3 双向绑定、单向绑定的优缺点&lt;/strong&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;单向绑定&lt;/strong&gt;：数据流也是单向的，对于复杂应用来说是实施统一状态管理（如redux）的前提。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;双向绑定&lt;/strong&gt;：在一些需要&lt;code&gt;实时&lt;/code&gt;反应用户输入的场合会非常方便（如多级联动菜单）。但常认为复杂应用中这种便利比不上引入状态管理带来的优势。因为不知道状态什么时候发生改变，是谁造成的改变，数据变更也不会通知。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;响应式的思路：&lt;code&gt;mvvm&lt;/code&gt; &lt;strong&gt;Model，View，View-Model&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="2-原理概述"&gt;2. 原理概述&lt;/h3&gt;
&lt;p&gt;Vue 数据双向绑定原理是通过 &lt;code&gt;数据劫持&lt;/code&gt; + &lt;code&gt;发布者-订阅者模式&lt;/code&gt; 的方式来实现的，首先是通过 &lt;code&gt;ES5&lt;/code&gt; 提供的 &lt;code&gt;Object.defineProperty()&lt;/code&gt; 方法来劫持（监听）各属性的 &lt;strong&gt;getter、setter&lt;/strong&gt;，并在当监听的属性发生变动时通知订阅者，是否需要更新，若更新就会执行对应的更新函数。详见 &lt;a href="https://github.com/vuejs/vue"&gt;vue源码&lt;/a&gt;。&lt;/p&gt;</description></item><item><title>vue指令</title><link>https://amatsuzero.github.io/LastStand/posts/frontend/vue/vue-003/</link><pubDate>Fri, 04 Oct 2024 00:00:00 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/frontend/vue/vue-003/</guid><description>&lt;h4 id="11-钩子函数"&gt;1.1 钩子函数&lt;/h4&gt;
&lt;p&gt;一个指令定义对象可以提供如下几个钩子函数 (均为可选)：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;bind 只调用一次，指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。&lt;/li&gt;
&lt;li&gt;inserted 被绑定元素插入父节点时调用 (仅保证父节点存在，但不一定已被插入文档中)。&lt;/li&gt;
&lt;li&gt;update 所在组件的 VNode 更新时调用，但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变，也可能没有。&lt;/li&gt;
&lt;li&gt;componentUpdated 指令所在组件的 VNode 及其子 VNode 全部更新后调用。&lt;/li&gt;
&lt;li&gt;unbind 只调用一次，指令与元素解绑时调用。&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;Vue&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;directive&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;gqs&amp;#39;&lt;/span&gt;,{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;bind&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 当指令绑定到 HTML 元素上时触发.**只调用一次**
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;bind triggerd&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;inserted&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 当绑定了指令的这个HTML元素插入到父元素上时触发(在这里父元素是 `div#app`)**.但不保证,父元素已经插入了 DOM 文档.**
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;inserted triggerd&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;updated&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 所在组件的`VNode`更新时调用.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;updated triggerd&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;componentUpdated&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 指令所在组件的 VNode 及其子 VNode 全部更新后调用。
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;componentUpdated triggerd&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;unbind&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 只调用一次，指令与元素解绑时调用.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;unbind triggerd&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; })
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="12-钩子函数参数"&gt;1.2 钩子函数参数&lt;/h4&gt;
&lt;p&gt;指令钩子函数会被传入以下参数：&lt;/p&gt;</description></item><item><title>计算属性</title><link>https://amatsuzero.github.io/LastStand/posts/frontend/vue/vue-004/</link><pubDate>Fri, 04 Oct 2024 00:00:00 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/frontend/vue/vue-004/</guid><description>&lt;h2 id="前言"&gt;前言&lt;/h2&gt;
&lt;p&gt;Vue 的计算属性（&lt;code&gt;computed&lt;/code&gt;）是 Vue.js 中非常重要的一个概念。它允许你在 Vue 组件中定义一些计算逻辑，这些逻辑会依赖于 Vue 的响应式数据，并且具有缓存机制，只有在依赖数据发生改变时才会重新计算，从而提高了性能。&lt;/p&gt;
&lt;p&gt;计算属性的主要作用包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;数据转换&lt;/li&gt;
&lt;li&gt;数据过滤&lt;/li&gt;
&lt;li&gt;响应式依赖&lt;/li&gt;
&lt;li&gt;缓存机制&lt;/li&gt;
&lt;li&gt;简化模板&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;在本篇文章中，我们将详细探寻如何利用计算属性优化 Vue 组件的数据处理和渲染逻辑，深入了解 Vue 计算属性的精髓。&lt;/p&gt;
&lt;h2 id="一-认识计算属性"&gt;一. 认识计算属性&lt;/h2&gt;
&lt;h3 id="1-什么是计算属性"&gt;1. 什么是计算属性&lt;/h3&gt;
&lt;p&gt;Vue.js 中的计算属性（&lt;code&gt;computed properties&lt;/code&gt;）是 Vue 实例中非常重要的一个特性。它们用于对 Vue 实例的数据进行动态计算，且具有缓存机制，只有在相关依赖发生改变时才会重新计算。这种特性使得计算属性非常适合用于处理模板中的逻辑。&lt;/p&gt;
&lt;h3 id="2-计算属性的定义"&gt;2. 计算属性的定义&lt;/h3&gt;
&lt;p&gt;计算属性是在 Vue 实例的&lt;code&gt;computed&lt;/code&gt;选项中定义的，可以是一个函数或具有&lt;code&gt;get&lt;/code&gt;和&lt;code&gt;set&lt;/code&gt;方法的对象。函数形式的计算属性会在调用时被执行，而对象形式的计算属性则可以提供自定义的&lt;code&gt;get&lt;/code&gt;和&lt;code&gt;set&lt;/code&gt;方法。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;computed&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 函数形式的计算属性
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;reversedMessage&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; () {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;message&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;split&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;&amp;#39;&lt;/span&gt;).&lt;span style="color:#a6e22e"&gt;reverse&lt;/span&gt;().&lt;span style="color:#a6e22e"&gt;join&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 对象形式的计算属性
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fullName&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;get&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; () {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;firstName&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39; &amp;#39;&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;lastName&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;set&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;newValue&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;names&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;newValue&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;split&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39; &amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;firstName&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;names&lt;/span&gt;[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;lastName&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;names&lt;/span&gt;[&lt;span style="color:#a6e22e"&gt;names&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;length&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="3-计算属性的依赖"&gt;3. 计算属性的依赖&lt;/h3&gt;
&lt;p&gt;计算属性可以依赖于 Vue 实例的响应式数据。当依赖数据发生改变时，相关的计算属性会重新计算。&lt;/p&gt;</description></item><item><title>侦听器watch</title><link>https://amatsuzero.github.io/LastStand/posts/frontend/vue/vue-005/</link><pubDate>Fri, 04 Oct 2024 00:00:00 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/frontend/vue/vue-005/</guid><description>&lt;h2 id="一-watch-api"&gt;一、 watch API&lt;/h2&gt;
&lt;p&gt;我们先看看 watch的使用例子,watch 有多种用法，可以接收多种类型参数:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;reactive&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;watch&lt;/span&gt; } &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;vue&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 1. 传入getter函数
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;state&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;reactive&lt;/span&gt;({ &lt;span style="color:#a6e22e"&gt;count&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; })
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;watch&lt;/span&gt;(() =&amp;gt; &lt;span style="color:#a6e22e"&gt;state&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;count&lt;/span&gt;, (&lt;span style="color:#a6e22e"&gt;count&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;prevCount&lt;/span&gt;) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 当 state.count 更新，会触发此回调函数
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 2. 传入reactive对象
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;watch&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;state&lt;/span&gt;, (&lt;span style="color:#a6e22e"&gt;count&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;prevCount&lt;/span&gt;) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 当 state.count 更新，会触发此回调函数
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 3. 传入ref对象
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;stateRef&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ref&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;watch&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;stateRef&lt;/span&gt;, (&lt;span style="color:#a6e22e"&gt;count&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;prevCount&lt;/span&gt;) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 当 stateRef.value 更新，会触发此回调函数
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 4.监听多个数据源，回调函数接受两个数组，分别对应来源数组中的新值和旧值：
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;watch&lt;/span&gt;([&lt;span style="color:#a6e22e"&gt;fooRef&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;barRef&lt;/span&gt;], ([&lt;span style="color:#a6e22e"&gt;foo&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;bar&lt;/span&gt;], [&lt;span style="color:#a6e22e"&gt;prevFoo&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;prevBar&lt;/span&gt;]) =&amp;gt; { &lt;span style="color:#75715e"&gt;/* ... */&lt;/span&gt; })
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;从上面的例子可以看到，对于 watch，它能接收的第一个参数类型非常多。&lt;/p&gt;
&lt;p&gt;你可以传入一个ref对象、一个响应式对象、一个 getter 函数、甚至是一个数组。&lt;/p&gt;
&lt;p&gt;我们在上一篇中知道了&lt;code&gt;computed对象&lt;/code&gt;其内部是借助了 &lt;code&gt;effect函数&lt;/code&gt; 创建了一个 &lt;code&gt;reactiveEffect函数&lt;/code&gt;，在访问&lt;code&gt;computed对象&lt;/code&gt;的值时，执行其 &lt;code&gt;runner函数&lt;/code&gt; 求值。&lt;/p&gt;</description></item><item><title>methods</title><link>https://amatsuzero.github.io/LastStand/posts/frontend/vue/methods/</link><pubDate>Fri, 04 Oct 2024 00:00:00 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/frontend/vue/methods/</guid><description>&lt;h2 id="methods-的初始化"&gt;Methods 的初始化&lt;/h2&gt;
&lt;p&gt;在 Vue.js 中，每个组件实例（&lt;code&gt;vm&lt;/code&gt;）都会有一个 &lt;code&gt;methods&lt;/code&gt; 属性，这个属性包含了组件中定义的所有方法。这些方法需要被初始化到实例上，以便可以在模板和生命周期钩子中被调用。初始化过程如下：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;initMethods&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;vm&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;methods&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;key&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;methods&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;vm&lt;/span&gt;[&lt;span style="color:#a6e22e"&gt;key&lt;/span&gt;] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;methods&lt;/span&gt;[&lt;span style="color:#a6e22e"&gt;key&lt;/span&gt;] &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt; &lt;span style="color:#f92672"&gt;?&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;noop&lt;/span&gt; &lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;bind&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;methods&lt;/span&gt;[&lt;span style="color:#a6e22e"&gt;key&lt;/span&gt;], &lt;span style="color:#a6e22e"&gt;vm&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这段代码遍历 &lt;code&gt;methods&lt;/code&gt; 对象中的每个属性，并将其复制到 Vue 实例（&lt;code&gt;vm&lt;/code&gt;）上。如果方法不存在（&lt;code&gt;methods[key] == null&lt;/code&gt;），则赋值为一个空函数（&lt;code&gt;noop&lt;/code&gt;），以避免对 &lt;code&gt;undefined&lt;/code&gt; 的调用。否则，使用 &lt;code&gt;bind&lt;/code&gt; 方法将每个方法的 &lt;code&gt;this&lt;/code&gt; 绑定到 Vue 实例上。&lt;/p&gt;
&lt;h2 id="methods-作用域的固定"&gt;Methods 作用域的固定&lt;/h2&gt;
&lt;p&gt;在 JavaScript 中，函数的 &lt;code&gt;this&lt;/code&gt; 值是在函数被调用时确定的，而不是在定义时。这可能导致在 Vue 实例的方法中 &lt;code&gt;this&lt;/code&gt; 并不指向实例本身，尤其是在方法被传递给其他函数或作为回调函数时。Vue 使用 &lt;code&gt;bind&lt;/code&gt; 来解决这个问题，确保 &lt;code&gt;this&lt;/code&gt; 总是指向 Vue 实例。&lt;/p&gt;
&lt;h3 id="原生和兼容性-bind-实现"&gt;原生和兼容性 bind 实现&lt;/h3&gt;
&lt;p&gt;Vue.js 提供了两种 &lt;code&gt;bind&lt;/code&gt; 的实现：原生的和兼容性的。兼容性实现是为了兼容那些不支持 &lt;code&gt;Function.prototype.bind&lt;/code&gt; 的旧浏览器。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;polyfillBind&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;fn&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;ctx&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;boundFn&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;a&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;l&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;arguments&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;length&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;l&lt;/span&gt; &lt;span style="color:#f92672"&gt;?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; (&lt;span style="color:#a6e22e"&gt;l&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;?&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;fn&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;apply&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;ctx&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;arguments&lt;/span&gt;) &lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;fn&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;call&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;ctx&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;a&lt;/span&gt;)) &lt;span style="color:#f92672"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fn&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;call&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;ctx&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;boundFn&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;_length&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;fn&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;length&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;boundFn&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;nativeBind&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;fn&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;ctx&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;fn&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;bind&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;ctx&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;bind&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Function.&lt;span style="color:#a6e22e"&gt;prototype&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;bind&lt;/span&gt; &lt;span style="color:#f92672"&gt;?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;nativeBind&lt;/span&gt; &lt;span style="color:#f92672"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;polyfillBind&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;polyfillBind&lt;/code&gt; 函数创建了一个新的函数 &lt;code&gt;boundFn&lt;/code&gt;，它在调用时使用 &lt;code&gt;call&lt;/code&gt; 或 &lt;code&gt;apply&lt;/code&gt; 将 &lt;code&gt;fn&lt;/code&gt; 的 &lt;code&gt;this&lt;/code&gt; 绑定到 &lt;code&gt;ctx&lt;/code&gt; 上。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;nativeBind&lt;/code&gt; 函数直接使用原生的 &lt;code&gt;bind&lt;/code&gt; 方法。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;bind&lt;/code&gt; 变量根据浏览器是否支持原生 &lt;code&gt;bind&lt;/code&gt; 来选择使用哪种实现。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="使用-bind-的好处"&gt;使用 bind 的好处&lt;/h3&gt;
&lt;p&gt;使用 &lt;code&gt;bind&lt;/code&gt; 后，我们可以在组件的方法中直接使用 &lt;code&gt;this&lt;/code&gt; 来访问实例的属性和方法，而不用担心 &lt;code&gt;this&lt;/code&gt; 的指向问题。这使得代码更加简洁和安全。&lt;/p&gt;</description></item><item><title>生命周期</title><link>https://amatsuzero.github.io/LastStand/posts/frontend/vue/lifecycle/</link><pubDate>Fri, 04 Oct 2024 00:00:00 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/frontend/vue/lifecycle/</guid><description>&lt;h2 id="vue3生命周期"&gt;vue3生命周期&lt;/h2&gt;
&lt;p&gt;在Vue中，生命周期指的是Vue实例从创建到销毁的过程。在这个过程中，Vue实例会经历一系列的阶段，包括数据观测、模板编译、挂载DOM、更新DOM、卸载等等。在这些阶段，Vue提供了一些生命周期钩子函数，让我们可以在特定的时机执行某些代码。&lt;/p&gt;
&lt;h2 id="为什么需要生命周期"&gt;为什么需要生命周期&lt;/h2&gt;
&lt;p&gt;生命周期钩子函数为我们提供了在Vue实例生命周期不同阶段执行代码的能力。这对于非响应式的操作非常有用，例如直接操作DOM、添加事件监听器或者创建定时器等。这些操作如果在数据变化时执行可能会导致不必要的性能开销，而生命周期钩子函数让我们可以更合理地安排这些操作的执行时机。一些常用的库，例如&lt;code&gt;react&lt;/code&gt;，&lt;code&gt;webpack&lt;/code&gt;都提供了生命周期的钩子，方便开发者理解整个运行流程。&lt;/p&gt;
&lt;h2 id="vue3-有哪些生命周期分别在什么时候调用"&gt;Vue3 有哪些生命周期，分别在什么时候调用？&lt;/h2&gt;
&lt;p&gt;Vue3的生命周期钩子函数主要包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;beforeCreate&lt;/code&gt;: 创建实例之前调用，此时实例的数据观测、事件等还未初始化。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;created&lt;/code&gt;: 创建实例后调用，此时实例的数据观测、事件等已经初始化完成。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;beforeMount&lt;/code&gt;: 挂载实例之前调用，此时模板已经编译完成，但是还未挂载到DOM。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mounted&lt;/code&gt;: 挂载实例后调用，此时实例已经挂载到DOM，可以进行DOM操作。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;beforeUpdate&lt;/code&gt;: 数据更新之前调用，此时可以进行状态的最后更改。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;updated&lt;/code&gt;: 数据更新后调用，此时DOM已经完成更新，可以进行DOM操作。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;beforeUnmount&lt;/code&gt;: 卸载实例之前调用，此时实例仍然完全可用。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;unmounted&lt;/code&gt;: 卸载实例后调用，此时实例已经完全卸载。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;生命周期类型的枚举位于&lt;code&gt;packages/runtime-core/src/enums.ts&lt;/code&gt;目录下：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;export&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;enum&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;LifecycleHooks&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;  &lt;span style="color:#a6e22e"&gt;BEFORE_CREATE&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;bc&amp;#39;&lt;/span&gt;, &lt;span style="color:#75715e"&gt;// 创建之前
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;  &lt;span style="color:#a6e22e"&gt;CREATED&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;c&amp;#39;&lt;/span&gt;, &lt;span style="color:#75715e"&gt;// 创建
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;  &lt;span style="color:#a6e22e"&gt;BEFORE_MOUNT&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;bm&amp;#39;&lt;/span&gt;, &lt;span style="color:#75715e"&gt;// 挂载之前
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;  &lt;span style="color:#a6e22e"&gt;MOUNTED&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;m&amp;#39;&lt;/span&gt;, &lt;span style="color:#75715e"&gt;// 挂载
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;  &lt;span style="color:#a6e22e"&gt;BEFORE_UPDATE&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;bu&amp;#39;&lt;/span&gt;, &lt;span style="color:#75715e"&gt;// 更新之前
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;  &lt;span style="color:#a6e22e"&gt;UPDATED&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;u&amp;#39;&lt;/span&gt;, &lt;span style="color:#75715e"&gt;// 更新
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;  &lt;span style="color:#a6e22e"&gt;BEFORE_UNMOUNT&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;bum&amp;#39;&lt;/span&gt;, &lt;span style="color:#75715e"&gt;// 卸载之前
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;  &lt;span style="color:#a6e22e"&gt;UNMOUNTED&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;um&amp;#39;&lt;/span&gt;, &lt;span style="color:#75715e"&gt;// 卸载之后
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;  &lt;span style="color:#a6e22e"&gt;DEACTIVATED&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;da&amp;#39;&lt;/span&gt;, &lt;span style="color:#75715e"&gt;// 被 keep-alive 缓存的组件停用时调用。
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;  &lt;span style="color:#a6e22e"&gt;ACTIVATED&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;a&amp;#39;&lt;/span&gt;, &lt;span style="color:#75715e"&gt;// 被 keep-alive 缓存的组件激活时调用。
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;  &lt;span style="color:#a6e22e"&gt;RENDER_TRIGGERED&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;rtg&amp;#39;&lt;/span&gt;, &lt;span style="color:#75715e"&gt;// 依赖被收集时调用
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;  &lt;span style="color:#a6e22e"&gt;RENDER_TRACKED&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;rtc&amp;#39;&lt;/span&gt;, &lt;span style="color:#75715e"&gt;// 依赖被触发时调用
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;  &lt;span style="color:#a6e22e"&gt;ERROR_CAPTURED&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;ec&amp;#39;&lt;/span&gt;, &lt;span style="color:#75715e"&gt;// 错误捕获
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;  &lt;span style="color:#a6e22e"&gt;SERVER_PREFETCH&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;sp&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;上面生命周期可以用一张图来表示：&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://amatsuzero.github.io/LastStand/posts/frontend/vue/lifecycle/image-01.webp"&gt;&lt;/p&gt;
&lt;h2 id="选项式和组合式生命周期的区别"&gt;选项式和组合式生命周期的区别&lt;/h2&gt;
&lt;p&gt;在Vue3中，我们可以使用选项式API和组合式API来定义组件。这两种API对应的生命周期钩子函数有一些区别。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;选项式API的生命周期钩子函数定义在组件选项对象的methods中，例如：&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;export&lt;/span&gt; default {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;  methods: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;    created() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;      &lt;span style="color:#f92672"&gt;//&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; something
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;   }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;组合式API的生命周期钩子函数定义在&lt;code&gt;setup&lt;/code&gt;函数中，需要使用&lt;code&gt;import&lt;/code&gt;从&lt;code&gt;vue&lt;/code&gt;中引入，例如：&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;import { onMounted } from &lt;span style="color:#e6db74"&gt;&amp;#39;vue&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;​&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;export&lt;/span&gt; default {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;  setup() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;    onMounted(() &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;      &lt;span style="color:#f92672"&gt;//&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; something
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;   });
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;需要注意的是，在组合式API中没有&lt;code&gt;beforecate&lt;/code&gt;和&lt;code&gt;created&lt;/code&gt;钩子，因为他们本身被&lt;code&gt;setup&lt;/code&gt;这个函数替代了，直接把相关逻辑写在&lt;code&gt;setup&lt;/code&gt;中就行了&lt;/p&gt;</description></item><item><title>组件通信</title><link>https://amatsuzero.github.io/LastStand/posts/frontend/vue/vue-008/</link><pubDate>Fri, 04 Oct 2024 00:00:00 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/frontend/vue/vue-008/</guid><description>&lt;h2 id="vue3-组件通信方式"&gt;Vue3 组件通信方式&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;props&lt;/li&gt;
&lt;li&gt;$emit&lt;/li&gt;
&lt;li&gt;expose / ref&lt;/li&gt;
&lt;li&gt;$attrs&lt;/li&gt;
&lt;li&gt;v-model&lt;/li&gt;
&lt;li&gt;provide / inject&lt;/li&gt;
&lt;li&gt;Vuex&lt;/li&gt;
&lt;li&gt;mitt&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="vue3-通信使用写法"&gt;Vue3 通信使用写法&lt;/h2&gt;
&lt;h3 id="1-props"&gt;1. props&lt;/h3&gt;
&lt;p&gt;用 props 传数据给子组件有两种方法，如下&lt;/p&gt;
&lt;p&gt;方法一，setup() 方法写法&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// Parent.vue 传送
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;child&lt;/span&gt; &lt;span style="color:#f92672"&gt;:&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;msg1&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;msg1&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;:&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;msg2&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;msg2&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;/child&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;script&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;child&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;./child.vue&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;ref&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;reactive&lt;/span&gt; } &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;vue&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;export&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;default&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;(){
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;msg1&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;这是传级子组件的信息1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;setup&lt;/span&gt;(){
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 创建一个响应式数据
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 写法一 适用于基础类型 ref 还有其他用处，下面章节有介绍
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;msg2&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ref&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;这是传级子组件的信息2&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 写法二 适用于复杂类型，如数组、对象
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;msg2&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;reactive&lt;/span&gt;([&lt;span style="color:#e6db74"&gt;&amp;#34;这是传级子组件的信息2&amp;#34;&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;msg2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;/script&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// Child.vue 接收
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;script&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;export&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;default&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;props&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; [&lt;span style="color:#e6db74"&gt;&amp;#34;msg1&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;msg2&amp;#34;&lt;/span&gt;],&lt;span style="color:#75715e"&gt;// 如果这行不写，下面就接收不到
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;setup&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;props&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;props&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// { msg1:&amp;#34;这是传给子组件的信息1&amp;#34;, msg2:&amp;#34;这是传给子组件的信息2&amp;#34; }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;/script&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;方法二，setup 语法糖&lt;/p&gt;</description></item><item><title>插槽</title><link>https://amatsuzero.github.io/LastStand/posts/frontend/vue/vue-009/</link><pubDate>Fri, 04 Oct 2024 00:00:00 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/frontend/vue/vue-009/</guid><description>&lt;h2 id="一插槽的几种使用方式"&gt;一、插槽的几种使用方式&lt;/h2&gt;
&lt;h3 id="1-普通插槽"&gt;1. 普通插槽&lt;/h3&gt;
&lt;p&gt;举例来说，这里有一个 &lt;code&gt;&amp;lt;FancyButton&amp;gt;&lt;/code&gt; 组件，可以像这样使用：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;FancyButton&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Click me! &lt;span style="color:#75715e"&gt;&amp;lt;!-- 插槽内容 --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;FancyButton&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;而 &lt;code&gt;&amp;lt;FancyButton&amp;gt;&lt;/code&gt; 的模板是这样的：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;button&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;fancy-btn&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;slot&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style="color:#f92672"&gt;slot&lt;/span&gt;&amp;gt; &lt;span style="color:#75715e"&gt;&amp;lt;!-- 插槽出口 --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;button&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;&amp;lt;slot&amp;gt;&lt;/code&gt; 元素是一个 &lt;strong&gt;插槽出口&lt;/strong&gt; (slot outlet)，标示了父元素提供的 &lt;strong&gt;插槽内容&lt;/strong&gt; (slot content) 将在哪里被渲染。&lt;/p&gt;
&lt;p&gt;最终渲染出的 DOM 是这样：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;button&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;fancy-btn&amp;#34;&lt;/span&gt;&amp;gt;Click me!&amp;lt;/&lt;span style="color:#f92672"&gt;button&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="2-具名插槽"&gt;2. 具名插槽&lt;/h3&gt;
&lt;p&gt;有时在一个组件中包含多个插槽出口是很有用的。举例来说，在一个 &lt;code&gt;&amp;lt;BaseLayout&amp;gt;&lt;/code&gt; 组件中，有如下模板：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;div&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;container&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;header&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;!-- 标题内容放这里 --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;header&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;main&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;!-- 主要内容放这里 --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;main&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;footer&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;!-- 底部内容放这里 --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;footer&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;对于这种场景， &lt;code&gt;&amp;lt;slot&amp;gt;&lt;/code&gt; 元素可以有一个特殊的 attribute &lt;code&gt;name&lt;/code&gt;，用来给各个插槽分配唯一的 ID，以确定每一处要渲染的内容：&lt;/p&gt;</description></item><item><title>v-if/v-show</title><link>https://amatsuzero.github.io/LastStand/posts/frontend/vue/v-if-v-show/</link><pubDate>Fri, 04 Oct 2024 00:00:00 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/frontend/vue/v-if-v-show/</guid><description>&lt;h2 id="v-show原理"&gt;v-show原理&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;export&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;vShow&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ObjectDirective&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;VShowElement&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;beforeMount&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;el&lt;/span&gt;, { &lt;span style="color:#a6e22e"&gt;value&lt;/span&gt; }, { &lt;span style="color:#a6e22e"&gt;transition&lt;/span&gt; }) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;el&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;_vod&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;el&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;style&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;display&lt;/span&gt; &lt;span style="color:#f92672"&gt;===&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;none&amp;#39;&lt;/span&gt; &lt;span style="color:#f92672"&gt;?&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;&amp;#39;&lt;/span&gt; &lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;el&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;style&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;display&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;transition&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;transition&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;beforeEnter&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;el&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; } &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;setDisplay&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;el&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;mounted&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;el&lt;/span&gt;, { &lt;span style="color:#a6e22e"&gt;value&lt;/span&gt; }, { &lt;span style="color:#a6e22e"&gt;transition&lt;/span&gt; }) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;transition&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;transition&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;enter&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;el&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;updated&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;el&lt;/span&gt;, { &lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;oldValue&lt;/span&gt; }, { &lt;span style="color:#a6e22e"&gt;transition&lt;/span&gt; }) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;beforeUnmount&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;el&lt;/span&gt;, { &lt;span style="color:#a6e22e"&gt;value&lt;/span&gt; }) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;setDisplay&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;el&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;有&lt;code&gt;transition&lt;/code&gt;就执行&lt;code&gt;transition&lt;/code&gt;，没有&lt;code&gt;transition&lt;/code&gt;就直接设置&lt;code&gt;display&lt;/code&gt;。不管初始条件是什么，元素总是会被渲染。&lt;/p&gt;
&lt;h2 id="v-if原理"&gt;v-if原理&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;export&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;transformIf&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;createStructuralDirectiveTransform&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;/^(if|else|else-if)$/&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; (&lt;span style="color:#a6e22e"&gt;node&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;dir&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;context&lt;/span&gt;) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;processIf&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;node&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;dir&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;context&lt;/span&gt;, (&lt;span style="color:#a6e22e"&gt;ifNode&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;branch&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;isRoot&lt;/span&gt;) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; () =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;isRoot&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;ifNode&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;codegenNode&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;createCodegenNodeForBranch&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;branch&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;key&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;context&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ) &lt;span style="color:#a6e22e"&gt;as&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;IfConditionalExpression&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; } &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// attach this branch&amp;#39;s codegen node to the v-if root.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;parentCondition&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;getParentCondition&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;ifNode&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;codegenNode&lt;/span&gt;&lt;span style="color:#f92672"&gt;!&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;parentCondition&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;alternate&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;createCodegenNodeForBranch&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;branch&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;key&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ifNode&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;branches&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;length&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;context&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; )
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; })
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;返回一个&lt;code&gt;node&lt;/code&gt;节点，&lt;code&gt;render&lt;/code&gt;函数通过表达式的值来决定是否生成&lt;code&gt;DOM&lt;/code&gt;&lt;/p&gt;</description></item><item><title>v-for</title><link>https://amatsuzero.github.io/LastStand/posts/frontend/vue/v-for/</link><pubDate>Sat, 05 Oct 2024 00:00:00 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/frontend/vue/v-for/</guid><description>&lt;p&gt;在 &lt;code&gt;Vue.js&lt;/code&gt; 开发中，&lt;code&gt;v-for&lt;/code&gt; 是我们用来遍历数组、对象或其他数据结构的核心指令。然而，很多开发者可能忽略了其中的一个细微差别：&lt;code&gt;in&lt;/code&gt; 和 &lt;code&gt;of&lt;/code&gt;。这两个关键字看似相似，但却有各自不同的使用场景和适用数据类型。理解它们的区别，可以帮助我们编写更简洁、高效的代码。&lt;/p&gt;
&lt;p&gt;本文将详细探讨 &lt;code&gt;v-for&lt;/code&gt; 中的 &lt;code&gt;in&lt;/code&gt; 和 &lt;code&gt;of&lt;/code&gt;，并讲解它们各自的适用场景，帮助你在 &lt;code&gt;Vue.js&lt;/code&gt; 项目中做出最佳选择。&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="什么是-v-for"&gt;什么是 &lt;code&gt;v-for&lt;/code&gt;？&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;v-for&lt;/code&gt; 是 &lt;code&gt;Vue.js&lt;/code&gt; 提供的用于遍历数据的指令，它可以帮助你快速渲染列表、表格等动态生成的内容。在使用 &lt;code&gt;v-for&lt;/code&gt; 时，我们通常需要遍历一个数据集合，并将每一项绑定到 &lt;code&gt;DOM&lt;/code&gt; 元素上。&lt;/p&gt;
&lt;h3 id="in-和-of-的概念"&gt;&lt;code&gt;in&lt;/code&gt; 和 &lt;code&gt;of&lt;/code&gt; 的概念&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;v-for&lt;/code&gt; 中的 &lt;code&gt;in&lt;/code&gt; 和 &lt;code&gt;of&lt;/code&gt; 是遍历数据时的两个常用关键字，它们的主要区别在于：&lt;strong&gt;&lt;code&gt;in&lt;/code&gt; 更通用，可以遍历数组、对象和整数范围；而 &lt;code&gt;of&lt;/code&gt; 专注于遍历可迭代对象（如数组、字符串、&lt;code&gt;Set&lt;/code&gt;、&lt;code&gt;Map&lt;/code&gt; 等）&lt;/strong&gt; 。&lt;/p&gt;
&lt;p&gt;接下来，我们深入探讨它们的具体用法及差异。&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="1-in适用于数组对象整数范围"&gt;1. &lt;code&gt;in&lt;/code&gt;：适用于数组、对象、整数范围&lt;/h3&gt;
&lt;h4 id="11-遍历数组"&gt;1.1 遍历数组&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;in&lt;/code&gt; 是 &lt;code&gt;Vue.js&lt;/code&gt; 中默认推荐的方式，用于遍历数组中的元素。你可以轻松地用 &lt;code&gt;in&lt;/code&gt; 处理数组中的每个值。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;ul&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;  &amp;lt;&lt;span style="color:#f92672"&gt;li&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;v-for&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;item in items&amp;#34;&lt;/span&gt;&amp;gt;{{ item }}&amp;lt;/&lt;span style="color:#f92672"&gt;li&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;ul&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;假设 &lt;code&gt;items = ['apple', 'banana', 'cherry']&lt;/code&gt;，输出结果为：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;li&lt;/span&gt;&amp;gt;apple&amp;lt;/&lt;span style="color:#f92672"&gt;li&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;li&lt;/span&gt;&amp;gt;banana&amp;lt;/&lt;span style="color:#f92672"&gt;li&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;li&lt;/span&gt;&amp;gt;cherry&amp;lt;/&lt;span style="color:#f92672"&gt;li&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="12-遍历对象"&gt;1.2 遍历对象&lt;/h4&gt;
&lt;p&gt;当你需要遍历对象的键和值时，&lt;code&gt;in&lt;/code&gt; 也非常方便。通过 &lt;code&gt;(value, key)&lt;/code&gt; 语法，你可以轻松获取对象的键和值。&lt;/p&gt;</description></item><item><title>vue事件处理</title><link>https://amatsuzero.github.io/LastStand/posts/frontend/vue/vue-012/</link><pubDate>Sat, 05 Oct 2024 00:00:00 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/frontend/vue/vue-012/</guid><description>&lt;h2 id="一dom-事件流"&gt;一、DOM 事件流&lt;/h2&gt;
&lt;p&gt;想必看过《红宝书》的前端 er 对标题都不会特别陌生，我们来看看定义：当一个 HTML 元素产生一个事件时，该事件会在树形结构的 DOM 上面沿着元素节点路径进行传播，事件所经过的路径结点都会收到该事件，这个传播过程可称为 &lt;strong&gt;DOM 事件流&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://amatsuzero.github.io/LastStand/posts/frontend/vue/vue-012/image-01.webp"&gt;&lt;/p&gt;
&lt;h2 id="二dom-事件流模型"&gt;二、DOM 事件流模型&lt;/h2&gt;
&lt;p&gt;DOM 事件流分为 &lt;strong&gt;捕获型事件流&lt;/strong&gt; 和 &lt;strong&gt;冒泡型事件流&lt;/strong&gt;。两种事件流分别对应三阶段 DOM 事件流模型中的捕获阶段和冒泡阶段：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;捕获&lt;/strong&gt;阶段：事件从最外面的祖先节点依次传递到最里面的后代节点&lt;/li&gt;
&lt;li&gt;目标阶段：真正的目标节点正在处理事件的阶段&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;冒泡&lt;/strong&gt;阶段：事件又从最里面的后代节点逐层传出到最外面的祖先节点&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://amatsuzero.github.io/LastStand/posts/frontend/vue/vue-012/image-02.webp"&gt;&lt;/p&gt;
&lt;h2 id="三vue-之事件处理"&gt;三、Vue 之事件处理&lt;/h2&gt;
&lt;p&gt;Vue 中提供了事件绑定的语法糖，我们可以很简单地在标签中直接使用 &lt;code&gt;@click=&amp;quot;handleClick($event)&amp;quot;&lt;/code&gt; 就可以绑定点击事件。&lt;/p&gt;
&lt;p&gt;而且在 Vue 里面，&lt;strong&gt;Vue 的事件触发默认为冒泡过程监听&lt;/strong&gt;，意思就是上面 &lt;code&gt;@click=&amp;quot;handleClick($event)&amp;quot;&lt;/code&gt; 中点击事件的执行是冒泡过程触发的。&lt;/p&gt;
&lt;h2 id="四vue-之事件修饰符"&gt;四、Vue 之事件修饰符&lt;/h2&gt;
&lt;h3 id="41-capture"&gt;4.1 &lt;code&gt;.capture&lt;/code&gt;&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;捕获监听器&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;div&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;@&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;click&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;log(1)&amp;#34;&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;@&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;click&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;.&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;capture&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;log(1)&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;style&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;background-color: #00f&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;div&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;@&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;click&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;log(2)&amp;#34;&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;@&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;click&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;.&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;capture&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;log(2)&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;style&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;background-color: #66f&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;div&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;@&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;click&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;log(3)&amp;#34;&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;@&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;click&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;.&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;capture&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;log(3)&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;style&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;background-color: #ccf&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;div&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;@&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;click&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;log(4)&amp;#34;&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;@&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;click&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;.&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;capture&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;log(4)&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;style&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;background-color: #fff&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 点击这里
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;控制台打印结果为：&lt;code&gt;1 2 3 4 4 3 2 1&lt;/code&gt;&lt;/p&gt;</description></item><item><title>自定义指令</title><link>https://amatsuzero.github.io/LastStand/posts/frontend/vue/vue-013/</link><pubDate>Sat, 05 Oct 2024 00:00:00 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/frontend/vue/vue-013/</guid><description>&lt;h3 id="如何自定义指令"&gt;如何自定义指令？&lt;/h3&gt;
&lt;p&gt;其实关于这个问题官方文档上已经有了很好的示例的，我们先来温故一下。&lt;/p&gt;
&lt;p&gt;除了核心功能默认内置的指令 (&lt;code&gt;v-model&lt;/code&gt; 和 &lt;code&gt;v-show&lt;/code&gt;)，Vue 也允许注册自定义指令。注意，在 Vue2.0 中，代码复用和抽象的主要形式是组件。然而，有的情况下，你仍然需要对普通 DOM 元素进行底层操作，这时候就会用到自定义指令。举个聚焦输入框的例子，如下：&lt;/p&gt;
&lt;p&gt;当页面加载时，该元素将获得焦点 (注意： &lt;code&gt;autofocus&lt;/code&gt; 在移动版 &lt;code&gt;Safari&lt;/code&gt; 上不工作)。事实上，只要你在打开这个页面后还没点击过任何内容，这个输入框就应当还是处于&lt;strong&gt;聚焦状态&lt;/strong&gt;。现在让我们用指令来实现这个功能：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 注册一个全局自定义指令 `v-focus`
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;Vue&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;directive&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;focus&amp;#39;&lt;/span&gt;, {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 当被绑定的元素插入到 DOM 中时……
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;inserted&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;el&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 聚焦元素
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;el&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;focus&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;如果想注册局部指令，组件中也接受一个 &lt;code&gt;directives&lt;/code&gt; 的选项：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;directives&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;focus&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 指令的定义
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;inserted&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;el&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;el&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;focus&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;然后你可以在模板中任何元素上使用新的 &lt;code&gt;v-focus property&lt;/code&gt;，如下：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;input&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;v-focus&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="指令内部提供的钩子函数"&gt;指令内部提供的钩子函数&lt;/h4&gt;
&lt;p&gt;一个指令定义对象可以提供如下几个钩子函数 (均为可选)：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;bind:&lt;/code&gt; 只调用一次，指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;inserted:&lt;/code&gt; 被绑定元素插入父节点时调用 (仅保证父节点存在，但不一定已被插入文档中)。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;update:&lt;/code&gt; 所在组件的 VNode 更新时调用，**但是可能发生在其子 VNode 更新之前。**指令的值可能发生了改变，也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;componentUpdated:&lt;/code&gt; 指令所在组件的 VNode 及&lt;strong&gt;其子VNode&lt;/strong&gt;全部更新后调用。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;unbind:&lt;/code&gt; 只调用一次，指令与元素解绑时调用。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="钩子函数参数"&gt;钩子函数参数&lt;/h4&gt;
&lt;p&gt;指令钩子函数会被传入以下参数：&lt;/p&gt;</description></item><item><title>mixin-混入</title><link>https://amatsuzero.github.io/LastStand/posts/frontend/vue/vue-014/</link><pubDate>Sat, 05 Oct 2024 00:00:00 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/frontend/vue/vue-014/</guid><description>&lt;h2 id="1-什么是mixin"&gt;1. 什么是Mixin？&lt;/h2&gt;
&lt;p&gt;想要使用一个事物或者工具，我们首要先了解它是什么，这样我们才好对症下药。&lt;/p&gt;
&lt;p&gt;其实Mixin不是Vue专属的，可以说它是一种思想，也可以说它就是混入的意思，在很多开发框架中都实现了Mixin(混入)，我们这里主要讲解的是Vue中的Mixin。&lt;/p&gt;
&lt;p&gt;老规矩，先看官方文档。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;官方解释：&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;混入 (mixin) 提供了一种非常灵活的方式，来分发 Vue 组件中的可复用功能。一个混入对象可以包含任意组件选项。当组件使用混入对象时，所有混入对象的选项将被“混合”进入该组件本身的选项。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;官方的解释通常都是晦涩难懂的，因为要专业和准确嘛！&lt;/p&gt;
&lt;p&gt;我们可以用我们自己容易理解的话来说说Vue中的Mixin是什么。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;民间解释：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;将组件的公共逻辑或者配置提取出来，哪个组件需要用到时，直接将提取的这部分混入到组件内部即可。这样既可以减少代码冗余度，也可以让后期维护起来更加容易。&lt;/p&gt;
&lt;p&gt;这里需要注意的是：提取的是逻辑或配置，而不是HTML代码和CSS代码。其实大家也可以换一种想法，mixin就是组件中的组件，Vue组件化让我们的代码复用性更高，那么组件与组件之间还有重复部分，我们使用Mixin在抽离一遍。&lt;/p&gt;
&lt;h2 id="2-mixin和vuex的区别"&gt;2. Mixin和Vuex的区别？&lt;/h2&gt;
&lt;p&gt;上面一点说Mixin就是一个抽离公共部分的作用。在Vue中，Vuex状态管理似乎也是做的这一件事，它也是将组件之间可能共享的数据抽离出来。两者看似一样，实则还是有细微的区别，区别如下：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Vuex公共状态管理，如果在一个组件中更改了Vuex中的某个数据，那么其它所有引用了Vuex中该数据的组件也会跟着变化。&lt;/li&gt;
&lt;li&gt;Mixin中的数据和方法都是独立的，组件之间使用后是互相不影响的。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="3-如何使用"&gt;3. 如何使用？&lt;/h2&gt;
&lt;p&gt;我们了解了Mixin的概念，那么如何使用它呢？这才是我们的重点。&lt;/p&gt;
&lt;h3 id="31-准备工作"&gt;3.1 准备工作&lt;/h3&gt;
&lt;p&gt;接下来我们的mixin就放在Vue2.x的脚手架项目中演示。&lt;/p&gt;
&lt;p&gt;利用Vue-cli初始化一个最简单的项目：&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://amatsuzero.github.io/LastStand/posts/frontend/vue/vue-014/image-01.webp"&gt;&lt;/p&gt;
&lt;h3 id="31-mixin定义"&gt;3.1 mixin定义&lt;/h3&gt;
&lt;p&gt;定义mixin也非常简单，它就是一个对象而已，只不过这个对象里面可以包含Vue组件中的一些常见配置，如data、methods、created等等。&lt;/p&gt;
&lt;p&gt;在我们的项目src目录下新建mixin文件夹，然后新建index.js文件，该文件存放我们的mixin代码。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;代码如下：&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// src/mixin/index.js
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;export&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;mixins&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; {};
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;computed&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {},
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;created&lt;/span&gt;() {},
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;mounted&lt;/span&gt;() {},
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;methods&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {},
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img loading="lazy" src="https://amatsuzero.github.io/LastStand/posts/frontend/vue/vue-014/image-02.webp"&gt;&lt;/p&gt;
&lt;p&gt;可以看到我们的mixin非常的简单，主要包含了一个Vue组件的常见的逻辑结构。&lt;/p&gt;
&lt;p&gt;接下来让我们在mixin中简单的写点东西，&lt;strong&gt;代码如下：&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;export&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;mixins&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;msg&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;我是小猪课堂&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; };
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;computed&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {},
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;created&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;我是mixin中的created生命周期函数&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;mounted&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;我是mixin中的mounted生命周期函数&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;methods&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;clickMe&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;我是mixin中的点击事件&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="32-局部混入"&gt;3.2 局部混入&lt;/h3&gt;
&lt;p&gt;我们的公共mixin定义好后，最重要就是如何使用它。根据不同的业务场景，我们可以分为两种：局部混入和全局混入。顾名思义，局部混入和组件的按需加载有点类似，就是需要用到mixin中的代码时，我们再在组件章引入它。全局混入的话，则代表我在项目的任何组件中都可以使用mixin。&lt;/p&gt;</description></item><item><title>工具函数</title><link>https://amatsuzero.github.io/LastStand/posts/frontend/vue/vue-015/</link><pubDate>Sat, 05 Oct 2024 00:00:00 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/frontend/vue/vue-015/</guid><description>&lt;h4 id="一vueutilvuejs的工具函数集合"&gt;一、Vue.util：Vue.js的工具函数集合&lt;/h4&gt;
&lt;p&gt;Vue.util是Vue.js内部的一个工具函数集合，包含了多种实用的方法，用于处理各种常见的任务。然而，需要注意的是，Vue.util并不是Vue.js公开API的一部分，这意味着它的使用可能会随着Vue.js版本的更新而发生变化。因此，在开发过程中，应尽量避免直接使用Vue.util中的方法，而是使用Vue.js提供的公开API或其他更稳定的解决方案。&lt;/p&gt;
&lt;p&gt;尽管如此，了解Vue.util中的一些方法仍然有助于我们更好地理解Vue.js的内部机制。例如，Vue.util.extend方法用于将一个或多个对象的属性混合到目标对象中，这在需要将多个对象合并到一个新对象中时非常有用。然而，随着Vue.js的发展，许多原本在Vue.util中的方法已经被移动到其他更合适的API中，或者被更现代的方法所替代。&lt;/p&gt;
&lt;h4 id="二vueset动态添加响应式属性"&gt;二、Vue.set：动态添加响应式属性&lt;/h4&gt;
&lt;p&gt;Vue.set是Vue.js提供的一个全局方法，用于向响应式对象添加一个新的属性，并确保该属性是响应式的。在默认情况下，Vue.js只能检测到已经存在的对象的属性并将其转换为响应式属性，但对于后期动态添加的属性，Vue.js无法自动进行响应式转换。这时，就可以使用Vue.set方法手动将属性转换为响应式。&lt;/p&gt;
&lt;p&gt;Vue.set方法接受三个参数：对象、属性名和属性值。例如：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;Vue&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;set&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;vm&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;someObject&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;newProperty&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;Hello, Vue!&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;上面的代码将&lt;code&gt;someObject&lt;/code&gt;对象的&lt;code&gt;newProperty&lt;/code&gt;属性设置为&lt;code&gt;'Hello, Vue!'&lt;/code&gt;，并将其转换为响应式属性。这样，当属性值发生修改时，Vue可以检测到并响应式地更新视图。&lt;/p&gt;
&lt;p&gt;Vue.set方法的主要优势在于它能够将属性添加为响应式属性，使得Vue.js能够跟踪和响应属性值的变化，从而及时更新视图。此外，Vue.set方法还可以用于在数组中添加新元素，使其成为响应式。&lt;/p&gt;
&lt;h4 id="三vuedelete删除响应式对象的属性"&gt;三、Vue.delete：删除响应式对象的属性&lt;/h4&gt;
&lt;p&gt;Vue.delete是Vue.js提供的另一个全局方法，用于从响应式对象中删除指定的属性。与Vue.set方法类似，Vue.delete也可以触发响应式更新，使Vue能够正确追踪到属性的删除操作。&lt;/p&gt;
&lt;p&gt;Vue.delete方法接受两个参数：要删除的属性所在的对象和要删除的属性名。例如：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;Vue&lt;/span&gt;.&lt;span style="color:#66d9ef"&gt;delete&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;someObject&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;someProperty&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;上面的代码将从&lt;code&gt;someObject&lt;/code&gt;对象中删除&lt;code&gt;someProperty&lt;/code&gt;属性，并相应地更新视图。&lt;/p&gt;
&lt;p&gt;需要注意的是，Vue.delete方法只能用于响应式对象，而不能用于普通的JavaScript对象。此外，在删除数组中的元素时，Vue.js提供了一些数组特定的方法（如splice、push、pop等）来确保数组的响应式更新。因此，在删除数组元素时，应优先使用这些方法而不是Vue.delete。&lt;/p&gt;
&lt;h4 id="四实际应用中的注意事项"&gt;四、实际应用中的注意事项&lt;/h4&gt;
&lt;p&gt;在使用Vue.set和Vue.delete等工具函数时，需要注意以下几点：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;避免直接操作对象或数组&lt;/strong&gt;：在Vue.js中，直接修改对象或数组的属性或元素可能不会触发视图更新。因此，应优先使用Vue.set和Vue提供的数组方法来修改响应式数据。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;注意命名冲突&lt;/strong&gt;：在添加新属性时，应确保属性名不与现有属性名冲突，以避免覆盖现有属性。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;了解Vue.js的响应式机制&lt;/strong&gt;：为了更好地使用Vue.set和Vue.delete等工具函数，需要了解Vue.js的响应式机制以及它是如何跟踪和响应数据变化的。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="常见考点"&gt;常见考点&lt;/h2&gt;
&lt;h3 id="1-vue-内置工具函数"&gt;&lt;strong&gt;1. Vue 内置工具函数&lt;/strong&gt;&lt;/h3&gt;
&lt;h4 id="问题"&gt;&lt;strong&gt;问题：&lt;/strong&gt;&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;Vue 提供了哪些内置工具函数？&lt;/li&gt;
&lt;li&gt;这些工具函数的使用场景是什么？&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id="考察点"&gt;&lt;strong&gt;考察点：&lt;/strong&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Vue.set 和 Vue.delete&lt;/strong&gt;： Vue 中的 &lt;code&gt;Vue.set&lt;/code&gt; 和 &lt;code&gt;Vue.delete&lt;/code&gt; 是为了响应式系统而提供的工具函数，它们用于确保在数组或对象中添加、删除元素时，能够保持数据的响应性。&lt;br&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Vue.set&lt;/code&gt;：用于向对象中添加新的属性，并确保该属性是响应式的。&lt;br&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;Vue&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;set&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;obj&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;newProp&amp;#39;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Vue.delete&lt;/code&gt;：用于删除对象或数组中的元素，并保持响应性。&lt;br&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;Vue&lt;/span&gt;.&lt;span style="color:#66d9ef"&gt;delete&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;obj&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;propertyName&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;Vue&lt;/span&gt;.&lt;span style="color:#66d9ef"&gt;delete&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;arr&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;index&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Vue.nextTick&lt;/strong&gt;： &lt;code&gt;Vue.nextTick&lt;/code&gt; 是一个异步队列，用于在 DOM 更新后执行回调函数。它保证了在 Vue 完成 DOM 更新后，回调才会被执行。&lt;br&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;Vue&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;nextTick&lt;/span&gt;(() =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;DOM has been updated!&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Vue.util&lt;/strong&gt;： Vue 提供了一些工具函数，如 &lt;code&gt;Vue.util.extend&lt;/code&gt; 用于对象的深拷贝，&lt;code&gt;Vue.util.merge&lt;/code&gt; 用于合并对象。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id="2-自定义工具函数的常见应用"&gt;&lt;strong&gt;2. 自定义工具函数的常见应用&lt;/strong&gt;&lt;/h3&gt;
&lt;h4 id="问题-1"&gt;&lt;strong&gt;问题：&lt;/strong&gt;&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;你在 Vue 项目中常用哪些自定义工具函数？请列举一些例子。&lt;/li&gt;
&lt;li&gt;如何编写一个简单的工具函数来简化 Vue 中的日期格式化？&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id="考察点-1"&gt;&lt;strong&gt;考察点：&lt;/strong&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;日期格式化工具函数&lt;/strong&gt;： 在 Vue 项目中，常常需要对日期进行格式化。你可以创建一个工具函数来统一处理日期格式。 在组件中使用该工具函数：&lt;br&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// utils/date.js
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;export&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;formatDate&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;date&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;format&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;YYYY-MM-DD&amp;#39;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;d&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; Date(&lt;span style="color:#a6e22e"&gt;date&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;map&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;YYYY&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;d&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;getFullYear&lt;/span&gt;(),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;MM&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; String(&lt;span style="color:#a6e22e"&gt;d&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;getMonth&lt;/span&gt;() &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;).&lt;span style="color:#a6e22e"&gt;padStart&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;DD&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; String(&lt;span style="color:#a6e22e"&gt;d&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;getDate&lt;/span&gt;()).&lt;span style="color:#a6e22e"&gt;padStart&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;HH&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; String(&lt;span style="color:#a6e22e"&gt;d&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;getHours&lt;/span&gt;()).&lt;span style="color:#a6e22e"&gt;padStart&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;mm&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; String(&lt;span style="color:#a6e22e"&gt;d&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;getMinutes&lt;/span&gt;()).&lt;span style="color:#a6e22e"&gt;padStart&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;ss&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; String(&lt;span style="color:#a6e22e"&gt;d&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;getSeconds&lt;/span&gt;()).&lt;span style="color:#a6e22e"&gt;padStart&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; };
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;format&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;replace&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;/YYYY|MM|DD|HH|mm|ss/g&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;matched&lt;/span&gt; =&amp;gt; &lt;span style="color:#a6e22e"&gt;map&lt;/span&gt;[&lt;span style="color:#a6e22e"&gt;matched&lt;/span&gt;]);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;formatDate&lt;/span&gt; } &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;./utils/date&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;export&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;default&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;date&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;2024-12-15T12:00:00&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; };
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;computed&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;formattedDate&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;formatDate&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;date&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;YYYY-MM-DD HH:mm:ss&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;深拷贝工具函数&lt;/strong&gt;： 在某些场景下，你可能需要深拷贝对象，避免对原始对象进行修改。&lt;br&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;export&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;deepClone&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;obj&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;JSON&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;parse&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;JSON&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;stringify&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;obj&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h3 id="3-vue-的过滤器filters"&gt;&lt;strong&gt;3. Vue 的过滤器（Filters）&lt;/strong&gt;&lt;/h3&gt;
&lt;h4 id="问题-2"&gt;&lt;strong&gt;问题：&lt;/strong&gt;&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;Vue 中的过滤器有什么作用？举个例子说明。&lt;/li&gt;
&lt;li&gt;过滤器和工具函数有何区别，何时使用过滤器，何时使用工具函数？&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id="考察点-2"&gt;&lt;strong&gt;考察点：&lt;/strong&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Vue 过滤器&lt;/strong&gt;： 过滤器是用于格式化输出数据的一种工具，在 Vue 模板中可以直接使用，但仅适用于模板中的数据绑定。常用的场景是格式化日期、数字等。&lt;br&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;Vue&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;filter&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;currency&amp;#39;&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;$&amp;#39;&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;toFixed&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 在模板中使用
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{{ &lt;span style="color:#a6e22e"&gt;price&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;currency&lt;/span&gt; }}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;工具函数与过滤器的区别&lt;/strong&gt;：&lt;br&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;过滤器&lt;/strong&gt;：通常用于模板中，只能格式化输出。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;工具函数&lt;/strong&gt;：可以在组件的任何地方使用，提供更强的逻辑处理能力，适合更复杂的功能（如数据计算、事件管理等）。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id="4-vuex-与工具函数"&gt;&lt;strong&gt;4. Vuex 与工具函数&lt;/strong&gt;&lt;/h3&gt;
&lt;h4 id="问题-3"&gt;&lt;strong&gt;问题：&lt;/strong&gt;&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;如何通过工具函数简化 Vuex 的一些操作？&lt;/li&gt;
&lt;li&gt;你会如何编写一个工具函数来帮助管理 Vuex 中的 getter、mutation 或 action？&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id="考察点-3"&gt;&lt;strong&gt;考察点：&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;在 Vuex 中，常常需要对数据进行集中管理。可以通过工具函数来简化 Vuex 操作，避免重复代码。&lt;/p&gt;</description></item><item><title>$nextTick</title><link>https://amatsuzero.github.io/LastStand/posts/frontend/vue/nexttick/</link><pubDate>Sat, 05 Oct 2024 00:00:00 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/frontend/vue/nexttick/</guid><description>&lt;p&gt;&lt;code&gt;nextTick&lt;/code&gt; 是 Vue 的一个核心实现，&lt;code&gt;$nextTick&lt;/code&gt;方法将回调延迟到下次DOM更新循环之后执行。&lt;strong&gt;Vue 的 nextTick 其本质是对 JavaScript 执行原理 EventLoop 的一种应用。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;nextTick 的核心是利用了如 Promise 、MutationObserver、setImmediate、setTimeout的原生 JavaScript 方法来模拟对应的微/宏任务的实现，本质是为了利用 JavaScript 的这些异步回调任务队列来实现 Vue 框架中自己的异步回调队列&lt;/p&gt;
&lt;h2 id="前置知识---js事件循环"&gt;前置知识 - js事件循环&lt;/h2&gt;
&lt;h2 id="js-运行机制"&gt;JS 运行机制&lt;/h2&gt;
&lt;p&gt;JS 执行是单线程的，基于事件循环。事件循环大致分为以下步骤：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;所有同步任务都在主线程上执行，形成一个执行栈。&lt;/li&gt;
&lt;li&gt;异步任务放进任务队列，异步任务分为宏任务和微任务&lt;/li&gt;
&lt;li&gt;执行栈所有同步任务执行完成，就会执行任务队列。对应的异步任务，结束等待状态，进入执行栈，开始执行。&lt;/li&gt;
&lt;li&gt;主线程不断重复上面的第三步。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;主线程的执行过程就是一个 tick，而所有的异步结果都是通过 “任务队列” 来调度。 消息队列中存放的是一个个的任务（task）。 task 分为两大类，分别是 macro task 和 micro task，并且每个 macro task(宏任务) 结束后，都要清空所有的 micro task(微任务)。&lt;/p&gt;
&lt;p&gt;如图所示&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;macroTask&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;of&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;macroTaskQueue&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 执行宏任务
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;handleMacroTask&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 执行所有微任务
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;microTask&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;of&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;microTaskQueue&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;handleMicroTask&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;microTask&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;宏任务&lt;/code&gt;： script、setTimeout、setInterval、Node中的setImmediate 等&lt;br&gt;
&lt;code&gt;微任务&lt;/code&gt;： Promise.then、MutationObserver、Node 中的 Process.nextTick等&lt;/p&gt;</description></item><item><title>异步组件</title><link>https://amatsuzero.github.io/LastStand/posts/frontend/vue/vue-017/</link><pubDate>Sat, 05 Oct 2024 00:00:00 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/frontend/vue/vue-017/</guid><description>&lt;p&gt;当我们的项目达到一定的规模时，对于某些组件来说，我们并不希望一开始全部加载，而是需要的时候进行加载；这样的做得目的可以很好的提高用户体验。&lt;/p&gt;
&lt;p&gt;为了实现这个功能，Vue3中为我们提供了一个方法，即&lt;code&gt;defineAsyncComponent&lt;/code&gt;，这个方法可以传递两种类型的参数，分别是函数类型和对象类型，接下来我们分别学习。&lt;/p&gt;
&lt;h2 id="传递工厂函数作为参数"&gt;传递工厂函数作为参数&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;defineAsyncComponent&lt;/code&gt;方法接收一个工厂函数是它的基本用法，这个工厂函数必须返回一个&lt;code&gt;Promise&lt;/code&gt;，&lt;code&gt;Promise&lt;/code&gt;的&lt;code&gt;resolve&lt;/code&gt;应该返回一个组件。&lt;/p&gt;
&lt;p&gt;我们这里以Vue Cli创建的项目为例，这里我稍微做了一下修改，将头部的图片拆分为一个组件，代码如下：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;template&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;logo&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;img&lt;/span&gt; &lt;span style="color:#f92672"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;hello&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;world&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;msg&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Welcome to Your Vue.js App&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;/template&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;script&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;setup&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;LogoImg&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;./components/LogoImg.vue&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;HelloWorld&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;./components/HelloWorld.vue&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;/script&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;现在我们就将&lt;code&gt;&amp;lt;hello-world&amp;gt;&lt;/code&gt;组件修改为异步组件，示例代码如下：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;template&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;logo&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;img&lt;/span&gt; &lt;span style="color:#f92672"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;hello&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;world&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;msg&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Welcome to Your Vue.js App&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;/template&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;script&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;setup&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;defineAsyncComponent&lt;/span&gt; } &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;vue&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;LogoImg&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;./components/LogoImg.vue&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 简单用法
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;HelloWorld&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;defineAsyncComponent&lt;/span&gt;(() =&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;import&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;./components/HelloWorld.vue&amp;#39;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;/script&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;我们这里为了看到效果，将&lt;code&gt;import&lt;/code&gt;延迟执行，示例代码如下：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;script&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;setup&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;defineAsyncComponent&lt;/span&gt; } &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;vue&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;LogoImg&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;./components/LogoImg.vue&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 定义一个耗时执行的函数，t 表示延迟的时间， callback 表示需要执行的函数，可选
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;time&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;t&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;callback&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; () =&amp;gt; {}) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; Promise(&lt;span style="color:#a6e22e"&gt;resolve&lt;/span&gt; =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;setTimeout&lt;/span&gt;(() =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;callback&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;resolve&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }, &lt;span style="color:#a6e22e"&gt;t&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; })
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 定义异步组件，这里这样写是为了查看效果
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;HelloWorld&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;defineAsyncComponent&lt;/span&gt;(() =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; Promise((&lt;span style="color:#a6e22e"&gt;resolve&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;reject&lt;/span&gt;) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ;(&lt;span style="color:#66d9ef"&gt;async&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; () {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;try&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;await&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;time&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;2000&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;res&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;await&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;import&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;./components/HelloWorld.vue&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;resolve&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;res&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; } &lt;span style="color:#66d9ef"&gt;catch&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;error&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;reject&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;error&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; })()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; })
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;/script&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;代码运行结果如下所示：&lt;/p&gt;</description></item><item><title>vue路由</title><link>https://amatsuzero.github.io/LastStand/posts/frontend/vue/vue-018/</link><pubDate>Sat, 05 Oct 2024 00:00:00 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/frontend/vue/vue-018/</guid><description>&lt;h2 id="从后端路由开始"&gt;从后端路由开始&lt;/h2&gt;
&lt;p&gt;路由这个概念最先是后端出现的。在以前用模板引擎开发页面时，经常会看到这样&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;http://www.xxx.com/login
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;大致流程可以看成这样：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;浏览器发出请求&lt;/li&gt;
&lt;li&gt;服务器监听到80端口（或443）有请求过来，并解析url路径&lt;/li&gt;
&lt;li&gt;根据服务器的路由配置，返回相应信息（可以是 html 字串，也可以是 json 数据，图片等）&lt;/li&gt;
&lt;li&gt;浏览器根据数据包的 Content-Type 来决定如何解析数据&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;简单来说路由就是用来跟后端服务器进行交互的一种方式，通过不同的路径，来请求不同的资源，请求不同的页面是路由的其中一种功能。&lt;/p&gt;
&lt;h2 id="前端路由"&gt;前端路由&lt;/h2&gt;
&lt;h4 id="1-hash-模式"&gt;1. hash 模式&lt;/h4&gt;
&lt;p&gt;随着 ajax 的流行，异步数据请求交互运行在不刷新浏览器的情况下进行。而异步交互体验的更高级版本就是 SPA —— 单页应用。单页应用不仅仅是在页面交互是无刷新的，连页面跳转都是无刷新的，为了实现单页应用，所以就有了前端路由。 类似于服务端路由，前端路由实现起来其实也很简单，就是匹配不同的 url 路径，进行解析，然后动态的渲染出区域 html 内容。但是这样存在一个问题，就是 url 每次变化的时候，都会造成页面的刷新。那解决问题的思路便是在改变 url 的情况下，保证页面的不刷新。在 2014 年之前，大家是通过 hash 来实现路由，url hash 就是类似于：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;http://www.xxx.com/#/login
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这种 #。后面 hash 值的变化，并不会导致浏览器向服务器发出请求，浏览器不发出请求，也就不会刷新页面。另外每次 hash 值的变化，还会触发&lt;code&gt;hashchange&lt;/code&gt; 这个事件，通过这个事件我们就可以知道 hash 值发生了哪些变化。然后我们便可以监听&lt;code&gt;hashchange&lt;/code&gt;来实现更新页面部分内容的操作：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;matchAndUpdate&lt;/span&gt; () {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// todo 匹配 hash 做 dom 更新操作
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;window.&lt;span style="color:#a6e22e"&gt;addEventListener&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;hashchange&amp;#39;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;matchAndUpdate&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="2-history-模式"&gt;2. history 模式&lt;/h4&gt;
&lt;p&gt;14年后，因为HTML5标准发布。多了两个 API，&lt;code&gt;pushState&lt;/code&gt; 和 &lt;code&gt;replaceState&lt;/code&gt;，通过这两个 API 可以改变 url 地址且不会发送请求。同时还有&lt;code&gt;popstate&lt;/code&gt; 事件。通过这些就能用另一种方式来实现前端路由了，但原理都是跟 hash 实现相同的。用了 HTML5 的实现，单页路由的 url 就不会多出一个#，变得更加美观。但因为没有 # 号，所以当用户刷新页面之类的操作时，浏览器还是会给服务器发送请求。为了避免出现这种情况，所以这个实现需要服务器的支持，需要把所有路由都重定向到根页面。&lt;/p&gt;</description></item><item><title>状态管理</title><link>https://amatsuzero.github.io/LastStand/posts/frontend/vue/vue-019/</link><pubDate>Sat, 05 Oct 2024 00:00:00 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/frontend/vue/vue-019/</guid><description>&lt;p&gt;本知识点将以 &lt;code&gt;Pinia&lt;/code&gt; 为例，介绍 Vue 中的状态管理。&lt;/p&gt;
&lt;h2 id="前言"&gt;前言&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://pinia.vuejs.org/zh/"&gt;Pinia&lt;/a&gt;简称小菠萝🍍，是一个专为Vue 3设计的现代化状态管理库，为&lt;code&gt;Vue 3&lt;/code&gt;开发的，它提供了一种简单、可扩展和类型安全的方式来管理应用程序的状态。&lt;/p&gt;
&lt;p&gt;与&lt;code&gt;Vue 2&lt;/code&gt;中的Vuex相比，&lt;code&gt;Pinia&lt;/code&gt;提供了更好的&lt;code&gt;TypeScrip&lt;/code&gt;t支持，具有更好的类型定义和类型推断，可在编译时捕获错误，提供更高的代码可靠性和开发体验。它是专为&lt;code&gt;Vue 3&lt;/code&gt;设计的，充分利用了&lt;code&gt;Vue 3&lt;/code&gt;的新特性，如&lt;code&gt;Composition API&lt;/code&gt;，以提供更直接、自然和灵活的状态管理体验。&lt;code&gt;Pinia&lt;/code&gt;的核心概念是&lt;code&gt;Store&lt;/code&gt;，它类似于&lt;code&gt;Vuex&lt;/code&gt;中的模块，用于管理应用程序的状，可以将相关的状态和逻辑组合到单个&lt;code&gt;Store&lt;/code&gt;中，使代码更清晰、结构更有组织性。除此之外海提供了许多有用的特性和功能，例如模块化组织、状态持久化、插件扩展等。&lt;/p&gt;
&lt;p&gt;总的来说，&lt;code&gt;Pinia&lt;/code&gt;是一个功能强大而灵活的状态管理解决方案，适用于各种规模的&lt;code&gt;Vue 3&lt;/code&gt;应用程序。它提供了现代化的特性和工具，帮助我们更好地组织、管理和扩展应用程序的状态，同时提供了更好的类型安全和开发体验。&lt;/p&gt;
&lt;h2 id="安装"&gt;安装&lt;/h2&gt;
&lt;p&gt;运行安装命令&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;npm install pinia
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;在&lt;code&gt;main.ts&lt;/code&gt;中引入&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ts" data-lang="ts"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// main.ts
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;createApp&lt;/span&gt; } &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;vue&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;createPinia&lt;/span&gt; } &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;pinia&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;App&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;./App.vue&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;pinia&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;createPinia&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;app&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;createApp&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;App&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;app&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;use&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;pinia&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;app&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;mount&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;#app&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="初始化store"&gt;初始化Store&lt;/h2&gt;
&lt;p&gt;新建&lt;code&gt;stores&lt;/code&gt;文件，用于存放所有的&lt;code&gt;store&lt;/code&gt;，然后创建&lt;code&gt;index.ts&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;同过 &lt;code&gt;defineStore()&lt;/code&gt; 定义一个&lt;code&gt;store&lt;/code&gt;，它接受一个参数作为仓库名称，也就是&lt;code&gt;Id&lt;/code&gt;。它返回一个函数，默认我们使用&lt;code&gt;user&lt;/code&gt;开头的风格来接收。第二个参数为一个&lt;code&gt;Setup&lt;/code&gt;函数或者&lt;code&gt;Option&lt;/code&gt;对象。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ts" data-lang="ts"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;defineStore&lt;/span&gt; } &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;pinia&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;export&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;useUsersStore&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;defineStore&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;users&amp;#39;&lt;/span&gt;, {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 其他配置...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="option-store"&gt;Option Store&lt;/h2&gt;
&lt;p&gt;这种方式熟悉&lt;code&gt;Vuex&lt;/code&gt;的很了解，传入一个带有 &lt;code&gt;state&lt;/code&gt;、&lt;code&gt;actions&lt;/code&gt; 与 &lt;code&gt;getters&lt;/code&gt; 属性的 &lt;code&gt;Option&lt;/code&gt; 对象&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ts" data-lang="ts"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;export&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;userUsersStore&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;defineStore&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;users&amp;#39;&lt;/span&gt;, {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;state&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; () &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;name&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;inkun&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;current&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;100&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;getters&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;getName&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;state&lt;/span&gt;) &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;state&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;name&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;🐔你好帅&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;actions&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;getUserInfo&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;在 &lt;code&gt;Option Store&lt;/code&gt; 中：&lt;/p&gt;</description></item><item><title>服务器渲染</title><link>https://amatsuzero.github.io/LastStand/posts/frontend/vue/vue-020/</link><pubDate>Sat, 05 Oct 2024 00:00:00 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/frontend/vue/vue-020/</guid><description>&lt;h2 id="前言"&gt;前言&lt;/h2&gt;
&lt;p&gt;什么是SSR(Server-Side Rendering)？类似于用Java、ASP.NET、php开发前端页面，服务端准备数据并执行页面渲染，然后把完整的HTML发送给客户端。现代化的SSR通常和Vue、React等前端框架强关联，通过Node.js在服务端提前将page、component使用同构方式渲染为html代码，其目的是在实现SSR时尽量复用一套渲染机制。例如Vue框架就同时支持了CSR(Client-Side Rendering)和SSR。&lt;/p&gt;
&lt;p&gt;SSR能解决什么问题？&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;SEO: &lt;code&gt;Google&lt;/code&gt;、&lt;code&gt;百度&lt;/code&gt;、&lt;code&gt;Yandex&lt;/code&gt;、&lt;code&gt;Bing&lt;/code&gt;或者&lt;code&gt;Yahoo&lt;/code&gt;等搜索引擎会通过网络爬取你的页面并建立索引，如果的信息越完整，那么你的网站就更容易被检索到。使用SSR技术，让页面在服务端提前渲染好再返回给客户端，这样各类搜索引擎就能拿到比较完整的页面信息，提升检索质量。&lt;/li&gt;
&lt;li&gt;首屏渲染：SPA(Single Page Application)将页面渲染放到客户端执行，并且在渲染之前要加载大量的Javascript代码，所以首屏渲染需要花费较长时间。而SSR直接在服务端渲染完再返回客户端，使用户能够快速看到页面内容。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;有哪些框架支持SSR？&lt;/strong&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;开源库&lt;/th&gt;
&lt;th&gt;支持语言&lt;/th&gt;
&lt;th&gt;star数&lt;/th&gt;
&lt;th&gt;描述&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/nuxt/nuxt"&gt;Nuxt&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Vue&lt;/td&gt;
&lt;td&gt;54.9k&lt;/td&gt;
&lt;td&gt;快速构架、类型安全、高性能、易扩展&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/vercel/next.js"&gt;Next&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;React&lt;/td&gt;
&lt;td&gt;127k&lt;/td&gt;
&lt;td&gt;老牌框架、社区完善、Data Fetch、Styling&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://quasar.dev/"&gt;quasar&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Vue&lt;/td&gt;
&lt;td&gt;26k&lt;/td&gt;
&lt;td&gt;丰富的UI、支持桌面端和移动端&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://remix.run/"&gt;Remix&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;React&lt;/td&gt;
&lt;td&gt;29.9k&lt;/td&gt;
&lt;td&gt;极致的用户体验、开箱即用&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;本知识点将以 Nuxt 为例，介绍如何实现 SSR。&lt;/p&gt;
&lt;h2 id="什么是nuxt"&gt;什么是Nuxt&lt;/h2&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://amatsuzero.github.io/LastStand/posts/frontend/vue/vue-020/image-01.webp"&gt;&lt;/p&gt;
&lt;p&gt;基于Vue、React、Angular实现的&lt;code&gt;full-stack&lt;/code&gt;框架数不胜数，但就Vue框架领域内，应该数Nuxt最为Top 1。Nuxt保持了&lt;code&gt;Vue&lt;/code&gt;生态的&lt;code&gt;“开箱即用”&lt;/code&gt;特性，类似于Vite，几条指令就可直接run起来。如果你熟悉Vue，那么基于Nuxt写应用，体验上和写Vue客户端应用极其相似。&lt;/p&gt;
&lt;p&gt;Nuxt提前预制了一套目录结构，并自动处理路由、导入、数据获取，开发人员仅需按约定的规则实现页面、组件、数据API即可，极大降低开发人员学习成本。Nuxt的特性可总结为：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;基于文件的路由: 页面统一添加到&lt;code&gt;pages/&lt;/code&gt;目录下，例如添加index.vue、about.vue、contact.vue，就可以通过&lt;code&gt;/&lt;/code&gt;访问首页，通过&lt;code&gt;/about&lt;/code&gt;返回关于页面；&lt;/li&gt;
&lt;li&gt;代码分割：得益于Vue的&lt;code&gt;Virtual Node&lt;/code&gt;，Nuxt根据目录规则提前生成完整的依赖树，这样能够将所有code拆分为最小单元的&lt;code&gt;chunks&lt;/code&gt;, 从而减少应用初始化加载时间；&lt;/li&gt;
&lt;li&gt;开箱即用的SSR：Nuxt内部使用Vue的SSR，除了Vue实现SSR、CSR本身的差异，可以像开发CSR的Vue应用一样来开发SSR，降低研发心智负担；&lt;/li&gt;
&lt;li&gt;自动导入：在实现页面或组件时，不需要像CSR手动导入(&lt;code&gt;import Card from './Card.Vue'&lt;/code&gt;)依赖，当Nuxt识别到有使用外部组件，bundle过程会自动识别；&lt;/li&gt;
&lt;li&gt;数据获取工具：提供一套组合式FetchAPI，实现client、server端的同构；&lt;/li&gt;
&lt;li&gt;配置好的构建工具：&lt;strong&gt;默认使用Vite构建，同时支持Webpack、Rspack&lt;/strong&gt;；&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Nuxt的架构设计和&lt;code&gt;vue/core&lt;/code&gt;很相似，将整体功能拆分为独立的package:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;核心引擎：&lt;a href="https://github.com/nuxt/nuxt/tree/main/packages/nuxt"&gt;nuxt&lt;/a&gt;；&lt;/li&gt;
&lt;li&gt;bundlers: 打包器包含&lt;code&gt;@nuxt/vite-builde&lt;/code&gt;、&lt;code&gt;nuxt/webpack-builder&lt;/code&gt;、&lt;code&gt;@nuxt/rspack-builder&lt;/code&gt;；&lt;/li&gt;
&lt;li&gt;命令行工具：&lt;a href="https://github.com/nuxt/nuxt/tree/main/packages/nuxi"&gt;nuxi&lt;/a&gt;；&lt;/li&gt;
&lt;li&gt;服务端引擎：&lt;a href="https://github.com/unjs/nitro"&gt;nitro&lt;/a&gt;；&lt;/li&gt;
&lt;li&gt;开发套件：&lt;a href="https://github.com/nuxt/nuxt/tree/main/packages/kit"&gt;@nuxt/kit&lt;/a&gt;；&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="上手体验"&gt;上手体验&lt;/h2&gt;
&lt;h3 id="初始化项目"&gt;初始化项目&lt;/h3&gt;
&lt;p&gt;使用&lt;code&gt;nuxi&lt;/code&gt;提供的指令初始化项目：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-kotlin" data-lang="kotlin"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;npx nuxi&lt;span style="color:#a6e22e"&gt;@latest&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;init&lt;/span&gt; nuxt-learn-examples
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;如果安装过程下载失败，可能需要配置hosts:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;185.199.108.133 raw.githubusercontent.com
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;最新nuxt版本3.14初始化的项目目录比较简单，少了pages、plugins等目录&lt;/strong&gt;，入口为&lt;code&gt;app.vue&lt;/code&gt;：&lt;/p&gt;</description></item><item><title>Vue3 API</title><link>https://amatsuzero.github.io/LastStand/posts/frontend/vue/vue3-api/</link><pubDate>Sat, 05 Oct 2024 00:00:00 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/frontend/vue/vue3-api/</guid><description>&lt;h2 id="前言"&gt;📍前言&lt;/h2&gt;
&lt;p&gt;最近在一次理解&lt;code&gt;vue&lt;/code&gt;项目的代码时，发现周一对好多&lt;code&gt;API&lt;/code&gt;都不太熟悉。这间接导致的问题是，代码理解速度要比平常要慢很多。于是乎，赶忙把&lt;code&gt;vue API&lt;/code&gt;的学习提上了日程。&lt;/p&gt;
&lt;p&gt;在下面的文章中，将地板式地扫盲&lt;code&gt;vue3&lt;/code&gt;文档中&lt;code&gt;API&lt;/code&gt;模块的所有内容，融入周一的理解进行深入介绍。下面就来一起看看吧~🍬&lt;/p&gt;
&lt;h2 id="一框架搭建"&gt;一、🖇框架搭建&lt;/h2&gt;
&lt;h2 id="1关于文档"&gt;1、关于文档&lt;/h2&gt;
&lt;p&gt;首先附上官方文档的具体材料：&lt;a href="https://cn.vuejs.org/api/"&gt;cn.vuejs.org/api/&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="2vue3-api整体盘点"&gt;2、VUE3 API整体盘点&lt;/h2&gt;
&lt;p&gt;在&lt;code&gt;vue3&lt;/code&gt;的全新&lt;code&gt;API&lt;/code&gt;中，有部分在&lt;code&gt;vue2&lt;/code&gt;的基础上沿用了。还有另外一部分，是&lt;code&gt;vue3&lt;/code&gt;所新增加的。我们先来看&lt;code&gt;vue3 API&lt;/code&gt;文档主要包含哪些内容？&lt;/p&gt;
&lt;p&gt;&lt;code&gt;vue3 API&lt;/code&gt;主要包含以下六个部分：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;全局API —— 全局会用到的API&lt;/li&gt;
&lt;li&gt;组合式API —— vue3所拥有的组合式API&lt;/li&gt;
&lt;li&gt;选项式API —— vue2所拥有的选项式API&lt;/li&gt;
&lt;li&gt;内置内容 —— 指令、组件、特殊元素和特殊属性&lt;/li&gt;
&lt;li&gt;单文件组件 —— 语法定义、&lt;/li&gt;
&lt;li&gt;进阶API —— 渲染函数、服务端渲染、TS工具类型和自定义渲染&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://amatsuzero.github.io/LastStand/posts/frontend/vue/vue3-api/image-01.webp"&gt;&lt;/p&gt;
&lt;p&gt;下面将依据上面提到的六大点内容，来进行相应的剖析和讲解。&lt;/p&gt;
&lt;h2 id="二全局api"&gt;二、🎨全局API&lt;/h2&gt;
&lt;p&gt;vue3的全局API包含两个部分：应用实例和通用API。那它们各自都有哪些内容呢？&lt;/p&gt;
&lt;h2 id="1应用实例"&gt;1、应用实例&lt;/h2&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://amatsuzero.github.io/LastStand/posts/frontend/vue/vue3-api/image-02.webp"&gt;&lt;/p&gt;
&lt;h2 id="2通用api"&gt;2、通用API&lt;/h2&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://amatsuzero.github.io/LastStand/posts/frontend/vue/vue3-api/image-03.webp"&gt;&lt;/p&gt;
&lt;h2 id="三组合式api"&gt;三、🚲组合式API&lt;/h2&gt;
&lt;p&gt;谈到&lt;code&gt;vue3&lt;/code&gt; ，相信大家最为熟悉的就是 &lt;code&gt;composition API&lt;/code&gt; 了，也就是 &lt;code&gt;组合式 API&lt;/code&gt; 。那么，&lt;code&gt;vue3&lt;/code&gt; 的 &lt;code&gt;组合式 API&lt;/code&gt; 都给我们带来了什么呢？&lt;/p&gt;
&lt;h2 id="1setup"&gt;1、setup&lt;/h2&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://amatsuzero.github.io/LastStand/posts/frontend/vue/vue3-api/image-04.webp"&gt;&lt;/p&gt;
&lt;h2 id="2响应式核心"&gt;2、响应式：核心&lt;/h2&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://amatsuzero.github.io/LastStand/posts/frontend/vue/vue3-api/image-05.webp"&gt;&lt;/p&gt;
&lt;h2 id="3响应式工具函数"&gt;3、响应式：工具函数&lt;/h2&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://amatsuzero.github.io/LastStand/posts/frontend/vue/vue3-api/image-06.webp"&gt;&lt;/p&gt;
&lt;h2 id="4响应式进阶"&gt;4、响应式：进阶&lt;/h2&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://amatsuzero.github.io/LastStand/posts/frontend/vue/vue3-api/image-07.webp"&gt;&lt;/p&gt;
&lt;h2 id="5生命周期钩子"&gt;5、生命周期钩子&lt;/h2&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://amatsuzero.github.io/LastStand/posts/frontend/vue/vue3-api/image-08.webp"&gt;&lt;/p&gt;
&lt;h2 id="6依赖注入"&gt;6、依赖注入&lt;/h2&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://amatsuzero.github.io/LastStand/posts/frontend/vue/vue3-api/image-09.webp"&gt;&lt;/p&gt;
&lt;h2 id="四选项式api"&gt;四、🌠选项式API&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;选项式API&lt;/code&gt; 即 &lt;code&gt;options API&lt;/code&gt; 。可能有的小伙伴会觉得它在 &lt;code&gt;vue2&lt;/code&gt; 项目下会更为常见一些。但在 &lt;code&gt;vue3&lt;/code&gt; 项目中，也是有一些 &lt;code&gt;选项式API&lt;/code&gt; 值得我们去挖掘的。那都有哪些内容呢，我们来一探究竟。&lt;/p&gt;</description></item><item><title>响应式原理</title><link>https://amatsuzero.github.io/LastStand/posts/frontend/vue/vue-022/</link><pubDate>Sat, 05 Oct 2024 00:00:00 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/frontend/vue/vue-022/</guid><description>&lt;h2 id="什么是响应式系统"&gt;什么是响应式系统&lt;/h2&gt;
&lt;p&gt;在 Vue 中，数据驱动视图是一个非常重要的概念。当数据发生变化时，视图会自动更新，这是因为 Vue 实现了一个响应式系统，通过追踪依赖关系来自动更新视图。&lt;/p&gt;
&lt;p&gt;简单来说，响应式系统就是 Vue 能够监听数据变化，并在变化时自动更新 DOM 的核心机制。在 Vue3 中，响应式系统的改进使得响应式数据可以更加高效地更新视图，同时也提升了开发体验和性能。&lt;/p&gt;
&lt;h2 id="vue2-的响应式原理"&gt;Vue2 的响应式原理&lt;/h2&gt;
&lt;p&gt;在 Vue2 中，响应式原理是通过 Object.defineProperty 来实现的。Vue 会在数据对象上定义 getter 和 setter，来实现数据变化时更新视图的功能。&lt;/p&gt;
&lt;p&gt;举个例子，当一个数据对象被定义为响应式时，我们可以通过访问这个对象的属性来触发 get 操作。具体实现如下：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Object.&lt;span style="color:#a6e22e"&gt;defineProperty&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;obj&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;foo&amp;#39;&lt;/span&gt;, {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;get&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;get foo&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;obj&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;_foo&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;set&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;newVal&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;set foo&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;obj&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;_foo&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;newVal&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;在上面的代码中，我们通过 Object.defineProperty 方法来监听对象上的属性 foo，当访问 foo 属性时，会触发 get 操作，并输出日志。同理，当给 foo 属性赋值时，会触发 set 操作，并输出日志。&lt;/p&gt;
&lt;p&gt;在 Vue2 中，我们可以通过使用上面的方法来将数据对象中的所有属性转化成响应式的，以实现数据变化时更新视图的功能。&lt;/p&gt;
&lt;h2 id="vue3-的响应式原理"&gt;Vue3 的响应式原理&lt;/h2&gt;
&lt;p&gt;在 Vue3 中，响应式原理的实现方式和 Vue2 相比，有了相当大的变化。Vue3 直接使用了 ES6 Proxy 对象来拦截对对象的访问操作。Proxy 可以监听到对对象进行的访问、赋值等操作，并在这些操作发生时通知相关依赖以维护响应式系统的更新。&lt;/p&gt;</description></item><item><title>watch与watchEffect</title><link>https://amatsuzero.github.io/LastStand/posts/frontend/vue/vue-023/</link><pubDate>Sat, 05 Oct 2024 00:00:00 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/frontend/vue/vue-023/</guid><description>&lt;h2 id="watch"&gt;Watch&lt;/h2&gt;
&lt;h3 id="基本用法"&gt;基本用法&lt;/h3&gt;
&lt;p&gt;当我们需要在数据变化时执行一些“副作用”：如更改 DOM、执行异步操作，我们可以使用 &lt;code&gt;watch&lt;/code&gt; 函数：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;script&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;setup&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;import { ref, watch } from &amp;#39;vue&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;const question = ref(&amp;#39;&amp;#39;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;const answer = ref(&amp;#39;This is answer. ;-)&amp;#39;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;// 侦听一个 ref
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;watch(question, async (newQuestion, oldQuestion) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; answer.value = &amp;#39;Thinking...&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; const res = await fetch(&amp;#39;https://...&amp;#39;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; answer.value = (await res.json()).answer
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;template&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;input&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;v-model=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;question&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;{{ answer }}&lt;span style="color:#f92672"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;watch()&lt;/code&gt; 一共可以接受三个参数，侦听数据源、回调函数和配置选项。&lt;/p&gt;
&lt;h3 id="侦听数据源"&gt;侦听数据源&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;watch&lt;/code&gt; 的第一个参数可以是不同形式的“数据源”，它可以是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;一个 ref&lt;/li&gt;
&lt;li&gt;一个计算属性&lt;/li&gt;
&lt;li&gt;一个 getter 函数（有返回值的函数）&lt;/li&gt;
&lt;li&gt;一个响应式对象&lt;/li&gt;
&lt;li&gt;以上类型的值组成的数组&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;x&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ref&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;y&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ref&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;doubleX&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;computed&lt;/span&gt;(() =&amp;gt; &lt;span style="color:#a6e22e"&gt;x&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;value&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;obj&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;reactive&lt;/span&gt;({ &lt;span style="color:#a6e22e"&gt;count&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; })
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 单个 ref
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;watch&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;x&lt;/span&gt;, (&lt;span style="color:#a6e22e"&gt;newValue&lt;/span&gt;) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;`x is &lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;newValue&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 计算属性
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;watch&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;doubleX&lt;/span&gt;, (&lt;span style="color:#a6e22e"&gt;newValue&lt;/span&gt;) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;`doubleX is &lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;newValue&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// getter 函数
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;watch&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; () =&amp;gt; &lt;span style="color:#a6e22e"&gt;x&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;value&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;y&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; (&lt;span style="color:#a6e22e"&gt;sum&lt;/span&gt;) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;`sum of x + y is: &lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;sum&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 响应式对象
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;watch&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;obj&lt;/span&gt;, (&lt;span style="color:#a6e22e"&gt;newValue&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;oldValue&lt;/span&gt;) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 在嵌套的属性变更时触发
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 注意：`newValue` 此处和 `oldValue` 是相等的
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 因为它们是同一个对象！
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 以上类型的值组成的数组
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;watch&lt;/span&gt;([&lt;span style="color:#a6e22e"&gt;x&lt;/span&gt;, () =&amp;gt; &lt;span style="color:#a6e22e"&gt;y&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;], ([&lt;span style="color:#a6e22e"&gt;newX&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;newY&lt;/span&gt;]) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;`x is &lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;newX&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt; and y is &lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;newY&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;注意，你不能直接侦听响应式对象的属性值，例如:&lt;/p&gt;</description></item></channel></rss>