Vue动态注册异步组件(非同一个工程的组件)

  前言:最近在掘金逛的时候,无意中看到前滴滴前端架构黄轶大佬,看到了大佬分享的一篇博客 滴滴 webapp 5.0 Vue 2.0 重构经验分享 ,对于其中第5个问题(异步加载的业务线组件,如何动态注册?)的解决办法深为震撼。

  滴滴的首屏展示的同步业务线组件,对于一些业务线(比如顺风车,出租车,快车),这些业务线其实都可以成为单独spa应用,由于种种原因(我感觉组件化应该是很大的一个原因,构建包很小只打核心和初始化给用户显示的,剩下的业务线通过Vue异步组件注册引入)。Vue2提供的有异步注册组件

  我们注意到,官方提供的demo是异步引入本工程下的组件,对于滴滴(每个业务线是一个工程,在不同的git仓库存储)。滴滴的做法是将不同的业务线单独构建,构建的每个业务线是一个Vue实例(不知道这块是否理解有错,欢迎指正),然后将其传递给resolve函数(我感觉滴滴在这块的处理特别秒:比如全局的Vue,Vuex,公共业务组件的共享,异步业务组件的全局挂载,动态路由注册很是妙哉,希望大家去原地址查看,我这里就不赘述了)。下面是我自己的一个尝试:

  首先,在一个目录下运行 vue init webpack-simple async-component , 新建一个工程,用来开发需要异步注册的组件,在src下新建component目录,并创建index.js和async-component.vue文件,完整目录结构如下

  

  

// async-component.vue
<template>
  <div class="async-component">
    <h1 class="name">{{name}}</h1>
    <div class="age">{{age}}</div>
  </div>
</template>

<script>
  export default {
    name: 'async-component',
    data () {
      return {

      }
    },
    props: {
      name: {
        type: String,
        default: '张三'
      },
      age: {
        type: Number,
        default: 18
      }
    }
  }
</script>

<style lang="scss" scoped>
  .async-component {
    .name {
      color: red;
    }
    .age {
      color: green;
    }
  }
</style>
// index.js
/**
 * Created by hs on 2019/7/15
 */
import AsyncComponent from './async-component'
if (typeof window !== 'undefined' && window.Vue) {
  // 跟滴滴一样,将业务线异步组件存到window.modules下
  window.modules = {
    'async-component': AsyncComponent
  }
}
// webpack.config.js 修改入口和出口文件
entry: process.NODE_ENV === 'development' ? './src/main.js' : './src/component/index.js',
output: {
    path: path.resolve(__dirname, './dist'),
    publicPath: '/dist/',
    filename: 'async-component.js'
},

  在 async-component 项目根目录运行 npm run build,然后dist生成了 async-component.js 文件,然后我们进入到dist文件夹下,运行 puer (一个web服务器,如果提示没有这个命令),用npm或者yarn全局安装下,puer启动后默认地址为 http://localhost:8000 , 在浏览器测试下http://localhost:8000/async-component.js , 能成功访问即可。然后启动下我的Vue测试项目,地址为 http://localhost:8080 ,Vue测试项目代码如下:

  

// App.vue
<template>
  <div id="app">
    <el-button type="primary" @click="changeComponent">加载异步组件</el-button>
    <component :is="componentName" name="小明" :age="50"></component>
  </div>
</template>

<script>
export default {
  name: 'App',
  data() {
    return {
    };
  },
  methods: {
    changeComponent () {
      this.componentName = this.name
    },
    loadAsyncComponent () {
      Vue.component(this.name, (resolve, reject) => {
        this.loadScript('http://localhost:8000/async-component.js')
          .then(() => {
            resolve(window.modules['async-component'])
          }).catch((e) => {
            reject(e)
          })
      })
    },
    loadScript (url){
      return new Promise((resolve, reject) => {
            var script = document.createElement ("script")
            script.type = "text/javascript";
            if (script.readyState){ //IE
              script.onreadystatechange = function(){
                if (script.readyState == "loaded" || script.readyState == "complete"){
                  script.onreadystatechange = null;
                  resolve()
                }
              };
            } else { //Others
              script.onload = function(){
                console.log('complete')
                resolve()
              };
              script.onerror = function (e) {
                reject(e)
              }
            }
            script.src = url;
            document.getElementsByTagName("body")[0].appendChild(script);
      })
    }
  },
  mounted() {
    this.loadAsyncComponent()
  }

}
</script>

<style lang="scss">
* {
  margin: 0;
  padding: 0;
  font-family: Microsoft YaHei;
}
#app {
  background: #f1f1f5;
}
</style>

  浏览访问 http://localhost:8080,如下

 

点击按钮后如下

  

  个人感觉滴滴这个解决方法真的很精妙,但是细细想了一下,在公司的项目中好像用不到...这个方案是滴滴结合自身业务想出来的,技术还是要结合实际项目最好。最后引用下大佬对此相关的回复:滴滴这个场景是不适合用 webpack.ensure 的,因为是动态加载其它业务线的代码,压根代码就不在一个仓库下,只能通过 loadscript 方式加载,所以也有动态注册路由的需求。技术重构往往伴随着产品重构,单纯的技术重构不太现实,除非特别闲。。所以慢慢来吧,新项目可以用 vue2 了~

 

  

  

 

转载于:https://www.cnblogs.com/hanshuai/p/11196151.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值