如何跨多个文件中的多个 Vue 实例正确使用 Vue 3 composition-api

How to correctly use Vue 3 composition-api across multiple Vue instances in multiple files

tl;dr 在基础 js 文件中导入 Vue3,然后在其他独​​立的 js 文件中使用 Vue 的组合 - api 的正确方法是什么在该基本文件之后加载?


我正在使用 Vue 来增强特定页面的用户体验。例如,在注册页面中执行 ajax 请求并在不重新加载页面的情况下显示服务器错误。简而言之,MPA 内的迷你 SPA...

在 Vue2 中,在基础文件中导入 Vue,然后实例化一个新的 Vue 实例并在后续文件中使用 Vue 的选项-api 没有问题。后续文件的大小保持最小,因为它们只包含该文件所需的逻辑。

但是由于Vue3的composition-api需要导入ref, reactive, watch, onMount...etc,导致后面的文件需要重新导入Vue。我尝试克服这个问题如下:

// register.blade.php (contains)
<div id="root">
  <input type="text" name="first_name" v-model="FirstName">
  <input type="text" name="last_name" v-model="LastName">
// (before edit) <script src="main.js"></script>
// (before edit) <script src="register.js"></script>
  <script src="{{ mix('/main.js') }}"></script>
  <script src="{{ mix('/register.js') }}"></script>
</div>
// main.js (contains)
// (before edit) import Vue from 'node_modules/vue/dist/vue.js';
// (before edit) window.Vue = Vue;
window.Vue = require('vue');
// register.js (contains)
const app = Vue.createApp({
  setup() {
    const FirstName = Vue.ref('');
    const LastName = Vue.ref('');
    const FullName = Vue.computed(() => FirstName.value + ' ' + LastName.value);

    return {
      FirstName, LastName, FullName
    }
  }
});
app.mount('#root');

这对于这个简单的例子来说效果很好,但我想知道使用 Vue. 作为前缀的方法是否正确?是否可以使用该方法访问 Vue 为 setup() 方法公开的所有函数?

编辑: 我正在使用由 laravel mix 包装的 webpack,为了简单起见,我从初始代码中删除了它,但我认为它被证明是相关的。对最初提供的代码中的编辑进行了注释以避免混淆。

// webpack.mix.js (contains)
mix.webpackConfig({
  resolve: {
    alias: {
      'vue$': path.resolve(__dirname, 'node_modules/vue/dist/vue.esm-bundler.js'),
    }
  }
});

mix.js('resources/main.js', 'public/main.js')
  .js('resources/register.js', 'public/register.js')
  .version();

你可以使用Vue.refref如果你这样解构import {ref,reactive} from 'vue/dist/vue.js';

这应该不是必需的:

window.Vue = Vue;

只要您在每个文件中使用 import Vue from 'vue/dist/vue.js';,例如 register.js(或解构版本)。即使您有多个导入,也不意味着它会 re-included 多次。打包器只会添加一次 Vue(或部分 Vue 库)。

从 Vue 3(refwatchcomputed…)导入每个 .js 文件中的单独部分时,应该没有额外的开销.事实上,如果您使用的是捆绑器,这将有助于 tree shaking 过程使生成的文件更小 (great explanation by Evan You)。

导入所有 Vue 并按照您当前的方式使用它没有任何问题,类似于您在 Vue 2 中的方式。如果语法困扰您,您可以解构您使用的内容,即

// register.js (contains)
const { ref, computed } = Vue;

const app = Vue.createApp({
  setup() {
    const FirstName = ref('');
    const LastName = ref('');
    const FullName = computed(() => FirstName.value + ' ' + LastName.value);

    return {
      FirstName, LastName, FullName
    }
  }
});

app.mount('#root');

编辑:

我不熟悉 Laravel Mix,但也许你可以尝试这样的操作:

// webpack.mix.js (contains)
const jsfiles = [
    'resources/main.js',
    'public/main.js',
    'resources/register.js',
    'public/register.js',
];

mix.js(...jsFiles).extract(['vue']).webpackConfig({
    resolve: {
        alias: {
            'vue$': path.resolve(__dirname, 'node_modules/vue/dist/vue.esm-bundler.js'),
        }
    }
}).version();

// now in your `register.js` and `main.js` use `import`, not `require`
//
// import Vue from 'vue';