从Laravel Blade File导入Vue js组件

时间:2019-09-26 17:06:26

标签: laravel vue.js laravel-blade

我已经在js/app.js文件中将一些组件注册为全局组件,但这会使编译后的app.js文件更大。

//example: app.js
Vue.component('profile-page', require('./components/profiles/ProfilePage.vue').default);

问题是:是否有办法将这些全局组件中的任何一个导入laravel-blade文件中,而不是将其全局注册到app.js文件中?

类似这样:

// laravel-blade file
<script>
    import ProfilePage from ...;
</script>

3 个答案:

答案 0 :(得分:2)

在另一个文件而不是app.js

中注册组件

resources/js/example.js

window.Vue = require('vue');
Vue.component('example-component', require('./components/ExampleComponent.vue').default);

将您的组件编译为webpack.mix.js中的另一个文件

mix.js('resources/js/app.js', 'public/js')
   .js('resources/js/example.js', 'public/js')
   .sass('resources/sass/app.scss', 'public/css');

将其包含在刀片服务器中

<script src="/js/example.js"></script>

答案 1 :(得分:2)

就像Caddy DZ回答的那样,这就是使用 laravel-mix 的方法。 (CaddyDz碰巧是我的密友hhhh)

https://stackoverflow.com/a/58122158/7668448

多页,多捆! laravel-mix-glob是答案

但是,如果有多页。并继续这样做。有点麻烦。还是不是最酷的方式。为此,我开发了一种包装 laravel-mix-glob 。这是laravel-mix的包装。那为你做一些魔术。

允许您使用 glob ,并自动为您处理所有添加的文件。代替逐个文件地管理它们。逐页。

使用非常简单。您可以在此处检查软件包:

https://www.npmjs.com/package/laravel-mix-glob

文档说明了所有内容。您必须检查有关 compileSpecifier

的部分

您可以阅读一遍。这样您将提高工作效率。魔术就发生了。甚至在文档中甚至说明了所有内容,甚至说明了 laravel-mix-glob 的工作方式。

您也可以检查此问题。显示出一些不错的观点:

https://github.com/MohamedLamineAllal/laravel-mix-glob/issues/5#issuecomment-537991979

即使在这里也要清除内容。这里是一个使用示例:

// imports
const mix = require('laravel-mix'); // you need the laravel mix instance
const MixGlob = require('laravel-mix-glob');

// init
const mixGlob = new MixGlob({mix}); // mix is required
// or 
const mixGlob = new MixGlob({
    mix, // mix required
    mapping: { // optional
        // see the doc
    },
    // more options maybe added in future version (fill issues if you need anything, or a PR if you like)
});


// use mixGlob
mixGlob.sass('resources/sass/**/*.compile.scss', 'public/css', null, {
    base: 'resources/sass/',
    // compileSpecifier: { 
    //     disabled: true // there is no compile specifier (disabled), and so it will not be removed from the extension (by default disabled = false, and the default specifier = 'compile', and it get removed from the path)
    //      ,
    //      specifier: 'cmp'
    // }
    // mapping: {   // this take precedency over any other mapping // useless feature as laravel-mix doesn't support output in different formats. (until i find a workaround)
    //     ext: {
    //         'scss': 'css' // multiple files separatly
    //     },
        // or
        // ext: 'css', // all to the same
        //   
    // }
})
.js(['resources/js/**/*.compile.{js,jsm}', '!resources/js/secondPattern/**/*'], 'public/js/', null, {
    base: 'resources/js/'
}) // multiple globs pattern as an array. Also with exclusion support (!)
.js('resources/js/secondPattern/**/*.compile.{js,jsm}', 'public/js', null, {
    base: 'resources/js/secondPattern'
})
.ts(['resources/js/ts/**/*.compile.ts', 'resources/js/tsx/**/*.compile.tsx'], 'public/js', null, {
    base: {
        ts: 'resources/js/ts/', // per file extension  mapping
        tsx: 'resources/js/tsx/**/*.compile.tsx'
    }
})
.mix('sass')('resources/sass/summernote.scss', '../resources/views/system/admin/dashboard/partials/_summernote_css.blade.php'); // laravel-mix instance

一些笔记

在下面

.js(['resources/js/**/*.compile.{js,jsm}', '!resources/js/secondPattern/**/*'], 'public/js/', null, {
    base: 'resources/js/'
})

它转换为获取目录js或其所有子目录中的所有jsmresources/js/文件。那不是resources/js/secondPattern/**/*的一部分。并将它们输出到public/js中。与基础resources/js/保持相同的结构。每当您添加一个尊重该结构的新文件时,该文件都会自动为您编译(laravel-mix watcher将重新启动,并伴随着整个构建)。而且您不必逐个文件地进行操作。完全没有

例如,假设一开始您有6个与模式匹配的文件。 laravel-mix-glob 将自动进行所有6个正确的调用。然后,即使您添加了新文件,它也会自动知道并重新编译。

laravel-mix-glob 会利用所有最佳的glob模式。以最直观的方式。从简单到最复杂。人们曾经使用过glob库。喝了或许多其他工具。只会觉得它太熟悉了。一切都很简单。这一切都在文档中进行了解释。也有很多例子。

compileSpecifier

这是一个重要功能。映像只想捆绑许多文件。添加说明符并具有可自动管理的功能并从输出中剥离功能是很有趣且有效的。这就是动机。默认情况下处于激活状态,您可以如以下示例所示将其禁用。

最后一句话

请检查文档,因为它比较完整,可以处理所有不同的部分。包裹已经在那里呆了几个月了。并且它已经在Linux中经过了很好的测试。在Windows中更少。但是两个平台的许多用户都使用了它。它完美而神奇地工作。为您提供更多的舒适感并提高您的生产力。

作为作者,我对社区也很开放。我非常高兴地审查和处理PR。而且我喜欢有贡献者。因此,任何有兴趣的人都可以告诉我。在这里或通过填写问题。

答案 2 :(得分:0)

要进一步扩展Salim Example,可以将Vue添加到窗口中,然后直接在Vue文件中创建导出的Vue组件。



1)在Laravel Mix中自动加载Vue


webpack.mix.js

const mix = require('laravel-mix');

mix.autoload({vue: ['Vue', 'window.Vue']})
   .js(...)
   .css(...)
   .version()

2)在创建Vue组件时在全球范围内注册它们


资源/js/components/profile/profile-image.vue

<template>
    <div class='profile-image' @click='show(user)'>
        <img :src='user.avatar' :alt='`${user.name} profile image`' />
    </div>
</template>

<script>
  /** Note: Global Component Registered Via Vue.component(...) **/

  Vue.component('profile-image', {   
     props: ['user'],

     methods: {
        /** 
         * Show User Profile Page
         */
         show(user) {
            const { location } = window;

            window.location = `${location.origin}/users/${user.id}`;
         }
      }
   });
</script>

3)无需要求每个组件,只需使用Laravel Mix

webpack.mix.js

const mix = require('laravel-mix');

mix.autoload({ 
  vue: [
     'Vue', 
     'window.Vue'
  ] 
})
.js([
      /* --------------------------------- 
       |   Card Components
       | ---------------------------------
       |
       | . Card.vue (Original)
       | . IconCard.vue (Topic Contextually Relevant Icon)
       | . DetailCard.vue (Shown On Detail Pages & Used To Summarize Index Tables)
       |
      */
      'resources/js/components/cards/card.vue',
      'resources/js/components/cards/icon-card.vue',
      'resources/js/components/cards/index-card.vue',
      'resources/js/components/cards/detail-card.vue',
      'resources/js/components/cards/organization-card.vue',

      /* --------------------------------- 
       |   Button Components
       | ---------------------------------
       |
       | . Button.vue (Original)
       | . ButtonRipple.vue (Interactive Click Effects)
       | . ButtonFabIcon.vue (Rounded, Material Design Icons)
       |
      */
      'resources/js/components/buttons/button.vue',
      'resources/js/components/buttons/primary.vue',
      'resources/js/components/buttons/success.vue',
      'resources/js/components/buttons/button-ripple.vue',
      'resources/js/components/buttons/primary-ripple.vue',
      'resources/js/components/buttons/success-ripple.vue',
      'resources/js/components/buttons/button-fab-icon.vue',
      'resources/js/components/buttons/primary-fab-icon.vue',
      'resources/js/components/buttons/success-fab-icon.vue',



      /* --------------------------------- 
       |   Fields Components
       | ---------------------------------
       |
       | . Form.vue (Create & Update)
       | . Detail.vue (Show, Edit, & Cards)
       | . Index.vue (Tables Ex: Sort, Search, Filter)
       |
      */
      'resources/js/components/fields/date/form.vue',
      'resources/js/components/fields/date/index.vue',
      'resources/js/components/fields/date/detail.vue',

      /** Then that one component we actually created ;D **/
      'resources/js/components/profile/profile-image.vue',

], 'resources/js/components/bootstrap.js')


.babel([
      /* ------------------------------------------------------------------
       | Mounting Vue & Using "Babel" (Vanilla JS For Every Browsers)  
       | ------------------------------------------------------------------
       |
       | . Our Components are compiled
       | . Our Last File Being Added Will Mount Vue
       | . We'll Use ".babel()" While Adding This File
       | . "Babel" Simply Transforms All Javascript Into Vanilla JS
       |
      */
        'resources/js/components/bootstrap.js', 
        'resources/js/bootstrap/mount-vue.js'

], 'public/js/app.js')


/*------------------------------*/
/* Optimization Minification   
/*------------------------------*/
.minify('public/js/app.js');

/*------------------------------*/
/* Cache Busting Versioning   
/*------------------------------*/
if (mix.inProduction()) {
  mix.version();
}

4)通过Extending Laravel Mix

进一步简化

resources / js / mix-extensions / mix-every-vue-component.js

import upperFirst from 'lodash/upperFirst'
import camelCase from 'lodash/camelCase'

const requireComponent = require.context(
  // The relative path of the components folder
  './components',
  // Whether or not to look in subfolders
  false,
  // The regular expression used to match base component filenames
  /Base[A-Z]\w+\.(vue|js)$/
)

requireComponent.keys().forEach(fileName => {
  // Get component config
  const componentConfig = requireComponent(fileName)

  // Get PascalCase name of component
  const componentName = upperFirst(
    camelCase(
      // Gets the file name regardless of folder depth
      fileName
        .split('/')
        .pop()
        .replace(/\.\w+$/, '')
    )
  )


  // Register component globally
  Vue.component(
    componentName,
    // Look for the component options on `.default`, which will
    // exist if the component was exported with `export default`,
    // otherwise fall back to module's root.
    componentConfig.default || componentConfig
  )
})

webpack.mix.js

const mix = require('laravel-mix');

class LaravelMixEveryVueComponent
{
    public constructor() {

    }

}
mix.autoload({ 
  vue: [
     'Vue', 
     'window.Vue'
  ] 
})
.js([
      /* --------------------------------- 
       |   Card Components
       | ---------------------------------
       |
       | . Card.vue (Original)
       | . IconCard.vue (Topic Contextually Relevant Icon)
       | . DetailCard.vue (Shown On Detail Pages & Used To Summarize Index Tables)
       |
      */
      'resources/js/components/cards/card.vue',
      'resources/js/components/cards/icon-card.vue',
      'resources/js/components/cards/index-card.vue',
      'resources/js/components/cards/detail-card.vue',
      'resources/js/components/cards/organization-card.vue',

      /* --------------------------------- 
       |   Button Components
       | ---------------------------------
       |
       | . Button.vue (Original)
       | . ButtonRipple.vue (Interactive Click Effects)
       | . ButtonFabIcon.vue (Rounded, Material Design Icons)
       |
      */
      'resources/js/components/buttons/button.vue',
      'resources/js/components/buttons/primary.vue',
      'resources/js/components/buttons/success.vue',
      'resources/js/components/buttons/button-ripple.vue',
      'resources/js/components/buttons/primary-ripple.vue',
      'resources/js/components/buttons/success-ripple.vue',
      'resources/js/components/buttons/button-fab-icon.vue',
      'resources/js/components/buttons/primary-fab-icon.vue',
      'resources/js/components/buttons/success-fab-icon.vue',



      /* --------------------------------- 
       |   Fields Components
       | ---------------------------------
       |
       | . Form.vue (Create & Update)
       | . Detail.vue (Show, Edit, & Cards)
       | . Index.vue (Tables Ex: Sort, Search, Filter)
       |
      */
      'resources/js/components/fields/date/form.vue',
      'resources/js/components/fields/date/index.vue',
      'resources/js/components/fields/date/detail.vue',

      /** Then that one component we actually created ;D **/
      'resources/js/components/profile/profile-image.vue',

], 'resources/js/components/bootstrap.js')


.babel([
      /* ------------------------------------------------------------------
       | Mounting Vue & Using "Babel" (Vanilla JS For Every Browsers)  
       | ------------------------------------------------------------------
       |
       | . Our Components are compiled
       | . Our Last File Being Added Will Mount Vue
       | . We'll Use ".babel()" While Adding This File
       | . "Babel" Simply Transforms All Javascript Into Vanilla JS
       |
      */
        'resources/js/components/bootstrap.js', 
        'resources/js/bootstrap/mount-vue.js'

], 'public/js/app.js')


/*------------------------------*/
/* Optimization Minification   
/*------------------------------*/
.minify('public/js/app.js');

/*------------------------------*/
/* Cache Busting Versioning   
/*------------------------------*/
if (mix.inProduction()) {
  mix.version();
}

4.扩展Laravel Mix,删除所有多余的步骤

laravel-mix-autoload-vuejs-extension.js

const mix = require('laravel-mix');


const CollectFiles = (folder, files = []) => {
    const isFolder = to => File(path.resolve(to)).isDirectory();
    const CombineFiles = (Files, Segments = []) => [ ...files, path.join(__dirname, Segments[0], '/', Segments[1])];

    return fs.readdirSync(folder).reduce((filed, file) =>
            isFolder(`${folder}/${file}`)
                ? CollectFiles(`${folder}/${file}`, files)
                : CombineFiles(files, [folder, file]),
        files
    ).map(string => string.replace(__dirname, ''));
};


class LaravelMixAutoloadVue
{
    constructor()
    {
        this.LoadVueComponents = (to, output) => mix.js(CollectFiles(to), output);

        return mix;
    }

    dependencies()
    {
        return ['fs', 'path'];
    }

    name()
    {
        return ['vuejs'];
    }

    register(to, output)
    {
        if (typeof to === 'undefined') {
            return console.log(`Output is undefined for codesplit path ${to}`);
        }

        this.LoadVueComponents(to, output);
    }

    boot()
    {
        console.log("Booting Example");
    }
}

mix.extend('vuejs', new LaravelMixAutoloadVue());

webpack.mix.js webpack.mix.js

const mix = require('laravel-mix');
require('./laravel-mix-autoload-vuejs`);

mix.autoload({ 
  vue: [
     'Vue', 
     'window.Vue'
  ] 
})
      /* -------------------------------------------------------------
       |  Laravel Mix Autoload Vue Extensions Handles All Components
       | -------------------------------------------------------------
      */
.vuejs('resources/js/components/', 'resources/js/components/bootstrap.js') 
.babel([
      /* ------------------------------------------------------------------
       | Mounting Vue & Using "Babel" (Vanilla JS For Every Browsers)  
       | ------------------------------------------------------------------
       |
       | . Our Components are compiled
       | . Our Last File Being Added Will Mount Vue
       | . We'll Use ".babel()" While Adding This File
       | . "Babel" Simply Transforms All Javascript Into Vanilla JS
       |
      */
        'resources/js/components/bootstrap.js', 
        'resources/js/bootstrap/mount-vue.js'

], 'public/js/app.js')


/*------------------------------*/
/* Optimization Minification   
/*------------------------------*/
.minify('public/js/app.js');

/*------------------------------*/
/* Cache Busting Versioning   
/*------------------------------*/
if (mix.inProduction()) {
  mix.version();
}