vueリモートコードをロードするコンポーネントの実例


私たちのvueプロジェクト(特にバックグランドシステム)では、多くの業務線が同じプロジェクトを共同開発する場面があります。各業務チームがフレームにいくつかの私有の展示コンポーネントを提供しても、これらのコンポーネントはフレームと一緒に包装できません。フレームはある私有モジュールの頻繁な変更によって重複して構築されたリリースされてはいけません。このような場面では、これらのコンポーネントをフレームにロードするために、リモート非同期コードをロードするコンポーネントが必要です。
Vue-cliはVueの公式推奨プロジェクトとして足場を構築し、開発過程でよく使われる熱負荷、構築、調整、ユニットテスト、コード検出などの機能を提供しています。今回の非同期の遠端部品はvue-cliに基づいて開発されます。
需要分析
  • はどうやってリモートコードをロードしますか?
  • は、ロードされたコードをフレームに登録するにはどうすればいいですか?
  • 親コンポーネントは、遠端に導入されたコンポーネントとどのように通信するか。
  • 遠端コードは、フレームに導入されたライブラリをどう多重化するか。
  • は、遠端コードがv−forのように何度も呼び出されることによる不要な要求を回避する。
  • リモートコードを読み込み
    リモートコードは訪問できるURLに保存してください。このようにAxios類似のHTTP clientを通じてソースコードを取得してください。
    
    import Axios from 'axios';
    export default {
     name: 'SyncComponent',
     props: {
      //          
      url: {
       type: String,
       default: ''
      }
     },
     data() {
      return {
       resData: ''
      };
     },
     async mounted() {
      if (!this.url) return;
      const res = await Axios.get(this.url); //           ,           。
      this.resData = res.data;
     }
    };
    以上は基本コードです。例では重複コード部分を省略します。
    フレームに登録コードを入れる
    この部分はやや煩雑で、複数の問題に関連しています。
    ブラウザはサポートされていません。vueテンプレートやES.next文法は、モジュールがコンパイルされてから使用できます。
    この部分を処理するのは簡単です。私たちは自分でwebpackプロファイルを定義して、これらのテンプレートを包装します。
    
    //   build       webpack.sync-components.prod.conf.js   
    const webpack = require('webpack');
    const path = require('path');
    const utils = require('./utils');
    const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
    function resolve(dir) {
     return path.join(__dirname, '..', dir)
    }
    module.exports = {
     //           
     entry: {
      componentA: resolve('/src/views/component-a.vue')
     },
     //         
     output: {
      path: resolve('/static/'),
      filename: '[name].js',
     },
     resolve: {
      extensions: ['.js', '.vue', '.json'],
      alias: {
       'vue$': 'vue/dist/vue.esm.js',
       '@': resolve('src'),
      }
     },
     module: {
      rules: [
       {
        test: /\.vue$/,
        loader: 'vue-loader',
        options: {
         esModule: false, // ****** vue-loader v13         true v12       false,        vue            webpack     
         loaders: utils.cssLoaders({
          sourceMap: true,
          extract: false     // css     
         }),
         transformToRequire: {
          video: 'src',
          source: 'src',
          img: 'src',
          image: 'xlink:href'
         }
        }
       },
       {
        test: /\.js$/,
        loader: 'babel-loader',
        include: [resolve('src'), resolve('test')]
       },
       {
        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
        loader: 'url-loader',
        options: {
         limit: 10000,
         name: utils.assetsPath('img/[name].[hash:7].[ext]')
        }
       },
       {
        test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
        loader: 'url-loader',
        options: {
         limit: 10000,
         name: utils.assetsPath('media/[name].[hash:7].[ext]')
        }
       },
       {
        test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
        loader: 'url-loader',
        options: {
         limit: 10000,
         name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
        }
       }
      ]
     },
     plugins: [
      new webpack.DefinePlugin({
       'process.env.NODE_ENV': '"production"'
      }),
      //   JS
      new webpack.optimize.UglifyJsPlugin({
       compress: false,
       sourceMap: true
      }),
      //   CSS       
      new OptimizeCSSPlugin({
       cssProcessorOptions: {
        safe: true
       }
      })
     ]
    };
    
    これまで私たちのモジュールはフレームで識別できるファイルにコンパイルされました。
    1.文字列をjsオブジェクトに変換する方法。
    
    new Function。
    async mounted() {
     if (!this.url) return;
     const res = await Axios.get(this.url);
     let Fn = Function;
     this.mode = new Fn(`return ${res.data}`)();
    }
    1.変換後のjsオブジェクトはvueでは認識されません。
    この問題につながる可能性が二つあります。
    
    // vue-loader v13 esModule         true, v12       false,        vue            webpack     
    {
     test: /\.vue$/,
     loader: 'vue-loader',
     options: {
      esModule: false
      ...         
     }
    }
    // UglifyJs            ,             
    new webpack.optimize.UglifyJsPlugin({
     compress: false,
     sourceMap: true
    })
    このようにして、リモートコンポーネントはフレームに組み込まれます。
    親コンポーネントはどうやって遠端に導入されたコンポーネントと通信しますか?
    ここでは、1つの問題があります。viewコンポーネントから遠隔非同期ローディングコンポーネントまで、実際のトラフィックコンポーネントと通信するために、3つの層に分けられます。中間層の遠隔非同期コンポーネントは、共通のコンポーネントとして修正されてはいけません。viewコンポーネントは直接に実際のトラフィックコンポーネントと通信する必要があります。vuexとeventBusの方案はくどすぎます。ここでは米ドルatrsとlistenersを採用して、「fallthrough」を実現します。
    
    //    sync-component.vue   
    //    v-bind="$attrs" v-on="$listeners"
    <component
     :is="mode"
     v-bind="$attrs"
     v-on="$listeners">
    </component>
    // inheritAttrs: true
    export default {
     name: 'SyncComponent',
     props: {
      //          
      url: {
       type: String,
       default: ''
      }
     },
     inheritAttrs: true
     ...         
    }
    遠端コードはどのようにフレームに導入されたライブラリを多重化しますか?
    私達は遠端コンポーネントとフレームの中に大きなライブラリやプラグインの重複の導入があることを見たくないです。この部分はまだ実践段階にあります。主な考え方は公共倉庫をVueプロトタイプチェーンにマウントして、コンポーネントの共通多重化Vue.prototypeを実現することです。
    
    //      axios   
    import axios from 'axios';
    Vue.prototype.$http = axios;
    導入されたリモートコンポーネントは、フレーム内の共通パッケージにアクセスできます。この場合は、webpackを配置して、リモートコンポーネントを梱包する際に、共通のパケットのコードを含まないようにする必要があります。
    
    // webpack.sync-components.prod.conf.js   
    externals: {
     vue: 'vue',
     'element-ui': 'element-ui',
     axios: 'axios'
    }
    遠端コードがv-forのように何度も呼び出されることによる不要な要求を避ける。
    この部分は直接に大域変数を辞書に使って、要求アドレス:データはサブ項目の配列として保存します。
    
    async mounted() {
     if (!this.url) return;
     // Cache       url   
     if (!window.SyncComponentCache) {
      window.SyncComponentCache = {};
     }
     let res;
     if (!window.SyncComponentCache[this.url]) {
      window.SyncComponentCache[this.url] = Axios.get(this.url);
      res = await window.SyncComponentCache[this.url];
     } else {
      res = await window.SyncComponentCache[this.url];
     }
     let Fn = Function;
     this.mode = new Fn(`return ${res.data}`)();
     console.log(this.mode);
    }
    ここで、非同期リモートコンポーネントは、ロードしてフレームと通信することができます。
    本文のソースコードはgithubにアクセスして取得してください。コンポーネントはNPMにリリースされました。直接インストールできます。
    締め括りをつける
    以上は小编が皆さんに绍介したvueのリモートコードをロードするコンポーネントです。皆さんに助けてほしいです。もし何か疑问があれば、メッセージをください。小编はすぐに皆さんに返事します。ここでも私たちのサイトを応援してくれてありがとうございます。