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

时间:2020-10-23 21:22:34

标签: javascript vue.js webpack vuejs3 vue-composition-api

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


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

在Vue2中,将Vue导入基本文件,然后实例化一个新的Vue实例,并在后续文件中使用Vue的options-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();

2 个答案:

答案 0 :(得分:0)

如果您要使用Vue.ref这样的结构,则可以使用refimport {ref,reactive} from 'vue/dist/vue.js';

这不是必需的:

window.Vue = Vue;

,只要您在每个文件中使用import Vue from 'vue/dist/vue.js';,例如register.js(或解构后的版本)。即使您有多个导入,也并不意味着它将被多次重新包含。捆绑程序只会添加一次Vue(或Vue库的一部分)。

答案 1 :(得分:0)

在每个ref文件中从Vue 3(watchcomputed.js…)导入单独的零件时,应该没有额外的开销。实际上,如果您使用捆绑器,这将有助于树的摇动过程使生成的文件更小(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';