吴凤岭 發表於 2021-6-21 16:11:00

Vue 在 typeScript 中写mixins。

<h2 id="前言">前言</h2>
<p>有个项目,需要使用 mixins 来管理一些通用方法。同时该项目使用 Typescript。</p>
<h2 id="问题">问题</h2>
<p>编译器报错,提示组件中没有该 mixin 中的内容。具体看一下代码。</p>
<p>MixinA:</p>
<pre><code>export const MixinA = {
    method: {
      sayHello() {
            // ...
      }
    }
}
</code></pre>
<p>component:</p>
<pre><code>export default Vue.extend({
    mixins: ,
    create() {
      this.sayHello();   // &lt;- 报错位置.
    }
})
</code></pre>
<p>报错:</p>
<pre><code>Property 'sayHello' does not exist on type 'CombinedVueInstance&lt;Vue, unknown, unknown, unknown, Readonly&lt;Record&lt;never, any&gt;&gt;&gt;'.Vetur(2339)
</code></pre>
<p>根据报错信息,可以看到是 Vetur 这个插件报的错。<br>
究其原因,还是因为 TypeScript 不够聪明,没法知道 Mixin 到底是什么样的。</p>
<h2 id="解决方案">解决方案</h2>
<p>这里有许许多多种,我收集整理一下。</p>
<ol>
<li>
<p>简单粗暴法 (as 强制转换) 极度不推荐</p>
<p>跟着上面的内容:</p>
<pre><code>(this as any).sayHello();
</code></pre>
<p>报错消失,但是这样会让代码很脏,组件阅读性差的同时,还要写很多 as 转换,同时,转换 any 让 typeScript 的意义荡然无存,还不如不用。</p>
</li>
<li>
<p>继承 mixins (只适合当个 mixin)</p>
<p>mixinA:</p>
<pre><code>export const MixinA = Vue.extend({
    method: {
      sayHello() {
            // ...
      }
    }
})
</code></pre>
<p>components:</p>
<pre><code>export default MixinA.extend({
    mixins: ,
    create() {
      this.sayHello();
    }
})
</code></pre>
<p>也不报错了,通过继承 mixinA 的方式,让编译器知道里面有什么东西。</p>
<p>缺点:违背 mixins 的设计初衷,mixins 本身就支持多 mixin 混入。</p>
<p>优点:简单粗暴。</p>
</li>
<li>
<p>使用 vue-typed-mixins</p>
<pre><code>import Vue from 'vue'
import mixins from 'vue-typed-mixins'

const mixinsA = Vue.extend({
data() {
    return {
    foo: 'test'
    }
}
})

const mixinsB = Vue.extend({
data() {
    return {
    bar: 123
    }
}
})

const App = mixins(mixinsA, mixinsB).extend({
data() {
    return {
    value: true
    }
},

computed: {
    concat(): string {
    return `${this.foo} ${this.bar} ${this.value}`
    }
}
})
</code></pre>
<p>优点:可以混合,多个 mixin<br>
缺点:使用习惯的修改。 还是比较支持的。</p>
</li>
<li>
<p>升级为 Vue3。<br>
Vue 官方在 3 后,有为 mixin 做的处理。(具体没有了解过,虽然很吐槽这种升级的方式)</p>
</li>
<li>
<p>遵循 Vue 和 TS 原则的一种解决方式.</p>
<p>mixinA :</p>
<pre><code>
// mixinA.vue
导出默认 Vue.extend({…})
</code></pre>
<p>mixinB:</p>
<pre><code>// mixinB.vue
导出默认 Vue.extend({…})
</code></pre>
<p>那么使用这两个的组件可以定义为:</p>
<pre><code>export default (Vue as VueConstructor&lt;Vue &amp; InstanceType&lt;typeof MixinA&gt;&amp; InstanceType&lt;typeof
MixinB&gt;&gt;).extend({
mixins: ,

</code></pre>
</li>
<li>
<p>自己写接口</p>
<pre><code>interface mixinState {
sayHello: () =&gt; {}
}

export default (Vue as VueConstructor&lt;Vue &amp; mixinState&gt;).extend({
name: 'Home',
create() {
    this.sayHello();
}
})

</code></pre>
<p>本质上与 第 5 种 是一样的。<br>
缺点:要写许多接口。</p>
</li>
<li>
<p>使用 vue-property-decorator 等。</p>
<p>使用类型注解的方式。没研究,不喜欢这种写法。</p>
</li>
</ol>


</div>
<div id="MySignature" role="contentinfo">
    以梦为马<br><br>
来源:https://www.cnblogs.com/lsAxy/p/14914053.html
頁: [1]
查看完整版本: Vue 在 typeScript 中写mixins。