Maison >interface Web >js tutoriel >Partage de composants qui charge le code distant de vue

Partage de composants qui charge le code distant de vue

小云云
小云云original
2018-01-16 10:46:392523parcourir

Dans notre projet vue (en particulier le système backend), il y aura toujours des scénarios qui nécessiteront que plusieurs secteurs d'activité développent conjointement le même projet si chaque équipe commerciale fournit des composants d'affichage privés au framework, mais ces composants ne le sont pas. Il ne peut pas être empaqueté avec le framework, car celui-ci ne peut pas être construit et publié à plusieurs reprises en raison de changements fréquents dans un module privé. Dans ce scénario, nous avons besoin d'un composant qui charge le code asynchrone à distance pour terminer le chargement de ces composants dans le framework.

vue-cli est l'échafaudage de construction de projet officiellement recommandé pour Vue. Il fournit des fonctions couramment utilisées dans le processus de développement, telles que le rechargement à chaud, la construction, le débogage, les tests unitaires, la détection de code et d'autres fonctions. Notre composant distant asynchrone sera cette fois développé sur la base de vue-cli.

Analyse des exigences

  1. Comment charger le code à distance ?

  2. Comment enregistrer le code chargé dans le framework.

  3. Comment le composant parent communique avec le composant importé à distance.

  4. Comment le code distant réutilise les bibliothèques introduites dans le framework.

  5. Évitez les requêtes inutiles causées par l'appel répété du code à distance comme v-for.

Charger le code à distance

Le code à distance doit être stocké sur une URL accessible, afin que nous puissions demander ce lien via un client HTTP comme Axios vers le code source.

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;
 }
};

Ce qui précède est le code de base Pour plus de commodité, j'omettra les parties de code répétées dans les exemples suivants.

Enregistrement du code dans le framework

Cette partie est un peu lourde et implique plusieurs problèmes :

Le navigateur ne prend pas en charge les modèles .vue ou la syntaxe ES.next, ainsi que les modules require Il peut être utilisé après la compilation.

Il est relativement simple de gérer cette partie. Nous définissons nous-mêmes un fichier de configuration webpack pour packager ces modèles.

// 在 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
   }
  })
 ]
};

À ce stade, notre module a été compilé dans un fichier que le framework peut reconnaître.

1. Comment convertir une chaîne en objet 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. L'objet js converti ne peut pas être reconnu par vue.

Il y a deux possibilités qui peuvent causer ce problème :

// 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
})

À ce stade, le composant distant a été introduit dans le framework.

Comment le composant parent communique-t-il avec le composant introduit à distance ?

Il y a un problème ici. Il existe trois couches de communication entre le composant de vue et le composant de chargement asynchrone distant. le composant métier réel. La couche intermédiaire En tant que composant public, le composant asynchrone distant ne peut pas être modifié et nécessite que le composant vue communique directement avec le composant métier réel. Les solutions vuex et eventBus sont trop lourdes. Ici, nous utilisons $attrs et $listeners (vue v2.4+) pour réaliser un "fallthrough" (communication inter-niveaux des composants vue).

// 修改 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
 ... 以下省略千军万码
}

Comment le code distant réutilise les bibliothèques qui ont été introduites dans le framework

Nous ne voulons pas voir l'introduction répétée de bibliothèques ou de plug-ins plus volumineux dans les composants et frameworks distants. Cette partie du contenu est encore au stade pratique. L'idée principale est de monter la bibliothèque publique sur la chaîne de prototypes Vue pour réaliser la réutilisation publique des composants Vue.prototype.$xxx.

// 全局添加 axios 对象
import axios from 'axios';
Vue.prototype.$http = axios;

Le composant distant introduit peut accéder au package public dans le framework À ce stade, webpack doit être configuré de manière à ce que le code du package public ne soit pas inclus lors de l'empaquetage du composant distant.

// webpack.sync-components.prod.conf.js 添加
externals: {
 vue: 'vue',
 'element-ui': 'element-ui',
 axios: 'axios'
}

Évitez les requêtes inutiles causées par l'appel répété du code à distance comme v-for.

Dans cette partie, nous utilisons directement une variable globale comme dictionnaire pour stocker un tableau avec l'adresse de requête : data comme sous-élément.

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);
}

À ce stade, le composant distant asynchrone peut être chargé et communiqué avec le framework.

Veuillez visiter github pour obtenir le code source dans cet article. Les composants ont été publiés sur NPM et peuvent être installés directement.

Recommandations associées :

Explication détaillée de la façon de lire ou de récupérer des instances de code distantes en PHP

Ajax pour réaliser une implémentation à distance Communication

Exemple de partage de PHP jugeant de l'existence de fichiers distants

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn