热门标签 | HotTags
当前位置:  开发笔记 > 前端 > 正文

加载vue远程代码的组件实例详解

vue-cli作为Vue官方推荐的项目构建脚手架,它提供了开发过程中常用的,热重载,构建,调试,单元测试,代码检测等功能。我们本次的异步远端组件将基于vue-cli开发

在我们的 vue 项目中(特别是后台系统),总会出现一些需要多业务线共同开发同一个项目的场景,如果各业务团队向框架中提供一些私有的展示组件,但是这些组件并不能和框架一起打包,因为框架不能因为某个私有模块的频繁变更而重复构建发布。在这种场景下我们需要一个加载远程异步代码的组件来完成将这些组件加载到框架中。

vue-cli 作为 Vue 官方推荐的项目构建脚手架,它提供了开发过程中常用的,热重载,构建,调试,单元测试,代码检测等功能。我们本次的异步远端组件将基于 vue-cli 开发。

需求分析

  1. 如何加载远端的代码?
  2. 如何注册加载后的代码到框架中。
  3. 父组件如何和远端引入的组件通信。
  4. 远端代码如何复用框架中已引入的库。
  5. 避免因远端代码被类似 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
})

至此 远程组件就被引入到框架中了。

父组件如何和远端引入的组件通信

这里有一个问题,从 view组件 到 远程异步加载组件 再到 实际业务组件 通信一共三层,中间层 远程异步组件 作为公共组件不可被修改,需要 view组件 直接向 实际业务组件 通信。vuex 和 eventBus 方案都过于繁琐,这里我们采用 $attrs 和 $listeners(vue v2.4+), 来实现 “fallthrough”(vue组件跨层级通信)。

// 修改 sync-component.vue 组件
// 新增 v-bind="$attrs" v-on="$listeners"


// inheritAttrs: true
export default {
 name: 'SyncComponent',
 props: {
  // 父组件提供请求地址
  url: {
   type: String,
   default: ''
  }
 },
 inheritAttrs: true
 ... 以下省略千军万码
}

远端代码如何复用框架中已引入的库

我们不希望看到远端组件和框架中存在较大库或插件的重复的引入,这部分内容尚处在实践阶段,主要思路是把公共库挂载到Vue原型链上实现组件公共复用 Vue.prototype.$xxx。

// 全局添加 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 远程代码的组件,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!


推荐阅读
  • 深入理解 Oracle 存储函数:计算员工年收入
    本文介绍如何使用 Oracle 存储函数查询特定员工的年收入。我们将详细解释存储函数的创建过程,并提供完整的代码示例。 ... [详细]
  • Linux 系统启动故障排除指南:MBR 和 GRUB 问题
    本文详细介绍了 Linux 系统启动过程中常见的 MBR 扇区和 GRUB 引导程序故障及其解决方案,涵盖从备份、模拟故障到恢复的具体步骤。 ... [详细]
  • 本文详细介绍了如何使用 Yii2 的 GridView 组件在列表页面实现数据的直接编辑功能。通过具体的代码示例和步骤,帮助开发者快速掌握这一实用技巧。 ... [详细]
  • 前言--页数多了以后需要指定到某一页(只做了功能,样式没有细调)html ... [详细]
  • 本章将深入探讨移动 UI 设计的核心原则,帮助开发者构建简洁、高效且用户友好的界面。通过学习设计规则和用户体验优化技巧,您将能够创建出既美观又实用的移动应用。 ... [详细]
  • 本文介绍如何通过SQL查询从JDE(JD Edwards)系统中提取所有字典数据,涵盖关键表的关联和字段选择。具体包括F0004和F0005系列表的数据提取方法。 ... [详细]
  • 如何高效创建和使用字体图标
    在Web和移动开发中,为什么选择字体图标?主要原因是其卓越的性能,可以显著减少HTTP请求并优化页面加载速度。本文详细介绍了从设计到应用的字体图标制作流程,并提供了专业建议。 ... [详细]
  • 本文详细介绍了如何通过命令行启动MySQL服务,包括打开命令提示符窗口、进入MySQL的bin目录、输入正确的连接命令以及注意事项。文中还提供了更多相关命令的资源链接。 ... [详细]
  • 扫描线三巨头 hdu1928hdu 1255  hdu 1542 [POJ 1151]
    学习链接:http:blog.csdn.netlwt36articledetails48908031学习扫描线主要学习的是一种扫描的思想,后期可以求解很 ... [详细]
  • 本文介绍如何使用 NSTimer 实现倒计时功能,详细讲解了初始化方法、参数配置以及具体实现步骤。通过示例代码展示如何创建和管理定时器,确保在指定时间间隔内执行特定任务。 ... [详细]
  • 本文介绍了在Windows环境下使用pydoc工具的方法,并详细解释了如何通过命令行和浏览器查看Python内置函数的文档。此外,还提供了关于raw_input和open函数的具体用法和功能说明。 ... [详细]
  • 题目Link题目学习link1题目学习link2题目学习link3%%%受益匪浅!-----&# ... [详细]
  • 网络运维工程师负责确保企业IT基础设施的稳定运行,保障业务连续性和数据安全。他们需要具备多种技能,包括搭建和维护网络环境、监控系统性能、处理突发事件等。本文将探讨网络运维工程师的职业前景及其平均薪酬水平。 ... [详细]
  • 高效解决应用崩溃问题!友盟新版错误分析工具全面升级
    友盟推出的最新版错误分析工具,专为移动开发者设计,提供强大的Crash收集与分析功能。该工具能够实时监控App运行状态,快速发现并修复错误,显著提升应用的稳定性和用户体验。 ... [详细]
  • 从零开始构建完整手机站:Vue CLI 3 实战指南(第一部分)
    本系列教程将引导您使用 Vue CLI 3 构建一个功能齐全的移动应用。我们将深入探讨项目中涉及的每一个知识点,并确保这些内容与实际工作中的需求紧密结合。 ... [详细]
author-avatar
一鳞半爪恋歌
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有