我的 vue 怎么和你们的不一样(标题党

💣 事情经过

在某个中秋节, 心血来潮的我咔嚓咔嚓写起了 Yondaime (一个没什么人用的博客框架) 的一个 Feature, 具体功能是这样的, 小T同学说要在网站底部加上网站的备案号, 但思来想去, 直接在配置加上一个备案号的专属配置实在是不太通用, 毕竟下次他可能就这么要求:

"废物, 我要在底部加外链"

^_^ : 滚

因此解决方案是这样的, 在配置中加多一个底部栏的拓展, 允许用户自定义底部栏的文案, 具体 api 如下:

config.js 配置文件

{
  // ...省略好多配置
    footers: ['备案号: xxxxxx'],
    }

基于以上配置, 在项目中进行功能点开发:

<template>
      <div v-for="(footer, index) of footers" :key="index">
          <span>{{ footer }}</span>
            </div>
            </template>

        &lt;script&gt;
          export default {
              data() {
                    return {
                            footers: ['备案号: xxxxxx'],
                                  };
                                      }
                                        };
                                        &lt;/script&gt;</code></pre><p>嗯嗯, 大概就这样了, 很简单的一个功能</p><p>但是! 得兼容一下外链的场景, 因此 footers 格式修改一下:</p><pre><code class="ts">type Footer = string | { label: string, link: string }</code></pre><p>这种格式进可支持支持带链接的文本, 退可支持纯文本展示, 简称 "全 能"</p><p>啊? 你问我为什么不直接改成这样:</p><pre><code class="ts">type Footer = { label: string, link?: string }</code></pre><p>那是考虑到灵活性, 怎么扭都可以~ 🕶 墨镜一戴, 谁都不爱</p><p>于是乎, 根据上面的配置修改一下代码:</p><pre><code class="html">&lt;template&gt;
                                          &lt;div v-for="(footer, index) of footers" :key="index"&gt;
                                              &lt;a v-if="footer.link" :href="footer.link"&gt;{{ footer.label }}&lt;/a&gt;
                                                  &lt;span v-else&gt;{{ footer }}&lt;/span&gt;
                                                    &lt;/div&gt;
                                                    &lt;/template&gt;
                                                    
                                                    &lt;script&gt;
                                                      export default {
                                                          data() {
                                                                return {
                                                                        footers: ['备案号: xxxxxx', { label: 'Ruofee\'s blog', link: 'http://ruofee.cn' }],
                                                                              };
                                                                                  }
                                                                                    };
                                                                                    &lt;/script&gt;</code></pre><p>这么简单的改动, 爷测都不用测 - . -</p><h2 id="item-0-2">💥 终究还是出问题了</h2><p>小T同学用了以下的配置去添加网站的备案号:</p><pre><code class="js">{
                                                                                      // ...省略好多配置
                                                                                        footers: ['备案号: xxxxxx'],
                                                                                        }</code></pre><p>但展示的结果却出乎我的意料, 底部栏什么文本都没出现...</p><p>爷震惊了!</p><h2 id="item-0-3">💊 发现原因</h2><p>经过一番查找, 我发现原因在于:</p><p>当 footer 为"备案号: xxxxxx"时, v-if="footer.link" 竟然判定为 true 了, 也就是 footer.link 是存在的</p><p>我人都傻了</p><p>先把 footer.link 打印出来瞅瞅:</p><pre><code class="js">"function link() { [native code] }"</code></pre><p>诶, 竟然是个函数, 那看看函数执行会返回什么:</p><pre><code class="js">"&lt;a href="undefined"&gt;备案号: xxxxxx&lt;/a&gt;"</code></pre><p>footer.link 返回了一个超链接, 链接的 href 为 函数的第一个参数, 看到这里我更懵了, 难道是 vue 封装的时候把这个方法写在变量的原型链上吗, 作为一个通用的方法方便用户生成一个超链接? </p><p>那确实也有可能</p><p>...</p><p>吧?</p><p>A Long Time Later...</p><p>好吧我翻了 vue 和 vue-router 的源码, 还是没能找到, 该不会是 vue 的依赖库修改到了吧, 一想到我就脑壳痛, 阿西吧!</p><p>突然灵光一现, 该不会是 String 类型本身就有这个方法吧!</p><p>一试, 果然是这样, 一切都在我的掌控之中 ⭐️</p><blockquote><p><strong><code>link()</code></strong> 方法创建一个 HTML 元素 <a href="https://link.segmentfault.com/?enc=0RhkQfvxdwZp4VLmcxq3cg%3D%3D.2jPlspZGOojqdoOiakqDK2CdGZubQZbTc2Ly%2BApX61l4QvZu7HQzVDcLog5rJ3wV469ctJPYOcQxVBHbAkm7Kw%3D%3D" rel="nofollow" target="_blank"><code>&lt;a&gt;</code></a> ,用该字符串作为超链接的显示文本,参数作为指向另一个 URL 的超链接。</p><p><strong>已废弃:</strong> 该特性已经从 Web 标准中删除,虽然一些浏览器目前仍然支持它,但也许会在未来的某个时间停止支持,请尽量不要使用该特性。</p><p>From <a href="https://link.segmentfault.com/?enc=uYeySbpu3EZ0wv0fXBkOVQ%3D%3D.7jA3zYrHida%2BXh2Tp8jy%2B3tVF8TF5VQyJwAuHAxIN%2FH8Dauiwgu%2FLL0PSa9gCEX%2B9Qa6LCOXEjIdWUhNbp8YhSGzrVw2JkWMvnZZaPxBfp53GFDpLDbPafdLGgGHcQBg" rel="nofollow" target="_blank">MDN</a>.</p></blockquote><p>是我无知了 =.= 还一度以为是我的 vue 和其他人的不一样, 但这确实是个踩坑点</p><p>虽然是我不测试导致的后果 (删掉)</p><p>啊? 你问我为什么通过判断 footer 的类型来进行区分? 像这样:</p><pre><code class="html">&lt;template&gt;
                                                                                          &lt;div v-for="(footer, index) of footers" :key="index"&gt;
                                                                                              &lt;span v-if="typeof footer === 'string'"&gt;{{ footer }}&lt;/span&gt;
                                                                                                  &lt;a v-else :href="footer.link"&gt;{{ footer.label }}&lt;/a&gt;
                                                                                                    &lt;/div&gt;
                                                                                                    &lt;/template&gt;</code></pre><p>那肯定是因为<code>v-if="footer.link"</code>比 v-if=<code>"typeof footer === 'string'"</code>短一些 (逃</p><h2 id="item-0-4">🍔 后续</h2><p>我改成用类型进行判断了 @.@</p><p>嘻嘻</p>