Vue动态组件与异步组件实例详解


Posted in Javascript onFebruary 23, 2019

本文实例讲述了Vue动态组件与异步组件。分享给大家供大家参考,具体如下:

1 在动态组件上使用 keep-alive

我们之前曾经在一个多标签的界面中使用 is 特性来切换不同的组件:

<component v-bind:is="currentTabComponent"></component>

当在这些组件之间切换的时候,你有时会想保持这些组件的状态,以避免反复重渲染导致的性能问题。例如我们来展开说一说这个多标签界面:

Vue动态组件与异步组件实例详解

你会注意到,如果你选择了一篇文章,切换到 Archive 标签,然后再切换回 Posts,是不会继续展示你之前选择的文章的。这是因为你每次切换新标签的时候,Vue 都创建了一个新的 currentTabComponent 实例。

重新创建动态组件的行为通常是非常有用的,但是在这个案例中,我们更希望那些标签的组件实例能够被在它们第一次被创建的时候缓存下来。为了解决这个问题,我们可以用一个 <keep-alive> 元素将其动态组件包裹起来。

<!-- 失活的组件将会被缓存!-->
<keep-alive>
 <component v-bind:is="currentTabComponent"></component>
</keep-alive>

现在这个 Posts 标签保持了它的状态 (被选中的文章) 甚至当它未被渲染时也是如此。

html:

<div id="dynamic-component-demo">
  <button
      v-for="tab in tabs"
      v-bind:key="tab"
      v-bind:class="['tab-button',{active:currentTab === tab}]"
      v-on:click="currentTab = tab"
      >{{ tab }}
  </button>
  <keep-alive>
    <component
        v-bind:is="currentTabComponent"
        class="tab"></component>
  </keep-alive>
</div>

js:

Vue.component('tab-posts', {
  data: function () {
    return {
      posts: [
        {
          id: 1,
          title: '赶在618前夕,微信更新了两个支付与电商功能',
          content: '本周末,中国消费者即将迎来上半年最大的消费网购峰值,6月17日父亲节,6月18日端午节,也是京东、天猫等电商的618购物节。略微出人意料但又在情理之中的是,中国最大的社交平台微信,近日密集上线了两个与支付和电商相关的功能。'
        },
        {
          id: 2,
          title: '腾讯要花32亿收购《绝地求生》开发商10%股份',
          content: '目前腾讯和蓝洞已经接近达成协议,如果交易成功,腾讯将成为蓝洞的第二大股东。'
        },
        {
          id: 3,
          title: '这两个地球之眼是真的吗?形成原因至今仍是谜团',
          content: '一名俄罗斯男子乘坐直升机游览时,经过俄罗斯萨哈林岛(库页岛)时,看到一个巨大的坑洞。地球上坑坑洞洞很多,本该不用大惊小怪。但当飞机离得更近,换了个角度看这个坑时,他震惊了,这分明就是“地球的眼睛”。'
        }
      ],
      selectedPost: null
    }
  },
  template: `
    <div class="posts-tab">
      <ul class="posts-sidebar">
        <li
          v-for="post in posts"
          v-bind:key="post.id"
          v-bind:class="{selected:post === selectedPost}"
          v-on:click="selectedPost = post">
          {{ post.title }}
        </li>
      </ul>
      <div class="selected-post-container">
        <div
          v-if="selectedPost"
          class="selected-post">
          <h3>{{ selectedPost.title }}</h3>
          <div v-html="selectedPost.content"></div>
        </div>
        <strong v-else>
          请点击某个标签页
        </strong>
      </div>
    </div>
  `
});
Vue.component('tab-archive', {
  template: '<div>archive 页面</div>'
});
new Vue({
  el: '#dynamic-component-demo',
  data: {
    currentTab: 'Posts',
    tabs: ['Posts', 'Archive']
  },
  computed: {
    currentTabComponent: function () {
      return 'tab-' + this.currentTab.toLowerCase();
    }
  }
});

css:

.tab-button {
  padding: 6px 10px;
  border-top-left-radius: 3px;
  border-top-right-radius: 3px;
  border: 1px solid #ccc;
  cursor: pointer;
  background: #f0f0f0;
  margin-bottom: -1px;
  margin-right: -1px;
}
.tab-button:hover {
  background: #e0e0e0;
}
.tab-button.active {
  background: #e0e0e0;
}
.tab {
  border: 1px solid #ccc;
  padding: 10px;
}
.posts-tab {
  display: flex;
}
.posts-sidebar {
  max-width: 40vw;
  margin: 0;
  padding: 0 10px 0 0;
  list-style-type: none;
  border-right: 1px solid #ccc;
}
.posts-sidebar li {
  white-space: nowrap;
  text-overflow: ellipsis;
  overflow: hidden;
  cursor: pointer;
}
.posts-sidebar li:hover {
  background: #eee;
}
.posts-sidebar li.selected {
  background: lightblue;
}
.selected-post-container {
  padding-left: 10px;
}
.selected-post > :first-child {
  margin-top: 0;
  padding-top: 0;
}

效果:

Vue动态组件与异步组件实例详解

2 异步组件

在大型应用中,我们可能需要将应用分割成小一些的代码块,并且只在需要的时候才从服务器加载一个模块。为了简化,Vue 允许你以一个工厂函数的方式定义你的组件,这个工厂函数会异步解析你的组件定义。Vue 只有在这个组件需要被渲染的时候才会被触发,且会把结果缓存起来供未来重渲染。例如:

Vue.component('async-example', function (resolve, reject) {
  setTimeout(function () {
    //在此定义组件
    resolve({
      template: `
        <div>
          我是异步加载的哦
        </div>
      `
    })
  }, 1000);
});

如你所见,这个工厂函数会收到一个 resolve 回调,这个回调函数会在你从服务器得到组件定义的时候被调用。你也可以调用 reject(reason) 来表示加载失败。这里的 setTimeout 是为了演示用的,如何获取组件取决于你自己。一个推荐的做法是将异步组件和 webpack 的 code-splitting 功能 一起配合使用:

Vue.component('async-webpack-example', function (resolve) {
 // 这个特殊的 `require` 语法将会告诉 webpack
 // 自动将你的构建代码切割成多个包,这些包
 // 会通过 Ajax 请求加载
 require(['./my-async-component'], resolve)
})

你也可以在工厂函数中返回一个 Promise,所以把 webpack 2 和 ES2015 语法加在一起,我们可以写成这样:

Vue.component(
 'async-webpack-example',
 // 这个 `import` 函数会返回一个 `Promise` 对象。
 () => import('./my-async-component')
)

当使用局部注册的时候,你也可以直接提供一个返回 Promise 的函数:

new Vue({
 // ...
 components: {
  'my-component': () => import('./my-async-component')
 }
})

如果你是一个 Browserify 用户同时喜欢使用异步组件,很不幸这个工具的作者明确表示异步加载“并不会被 Browserify 支持”,至少官方不会。Browserify 社区已经找到了一些变通方案,这些方案可能会对已存在的复杂应用有帮助。对于其它的场景,我们推荐直接使用 webpack,以拥有内建的被作为第一公民的异步支持。

处理加载状态

2.3.0+ 新增

这里的异步组件工厂函数也可以返回一个如下格式的对象:

const AsyncComponent = () => ({
 // 需要加载的组件 (应该是一个 `Promise` 对象)
 component: import('./MyComponent.vue'),
 // 异步组件加载时使用的组件
 loading: LoadingComponent,
 // 加载失败时使用的组件
 error: ErrorComponent,
 // 展示加载时组件的延时时间。默认值是 200 (毫秒)
 delay: 200,
 // 如果提供了超时时间且组件加载也超时了,
 // 则使用加载失败时使用的组件。默认值是:`Infinity`
 timeout: 3000
})

注意如果你希望在 Vue Router 的路由组件中使用上述语法的话,你必须使用 Vue Router 2.4.0+ 版本。

希望本文所述对大家vue.js程序设计有所帮助。

Javascript 相关文章推荐
解决jquery .ajax 在IE下卡死问题的解决方法
Oct 26 Javascript
JavaScript strike方法入门实例(给字符串加上删除线)
Oct 17 Javascript
javascript中的altKey 和 Event属性大全
Nov 06 Javascript
JavaScript常用基础知识强化学习
Dec 09 Javascript
JavaScript中的各种操作符使用总结
May 26 Javascript
简单的vue-resourse获取json并应用到模板示例
Feb 10 Javascript
vue通过watch对input做字数限定的方法
Jul 13 Javascript
jquery对table做排序操作的实例演示
Aug 10 jQuery
浅谈vue的几种绑定变量的值 防止其改变的方法
Mar 01 Javascript
浅谈Vue内置component组件的应用场景
Mar 27 Javascript
jQuery选择器之基本过滤选择器用法实例分析
Feb 19 jQuery
详解VUE中的插值( Interpolation)语法
Oct 18 Javascript
详解单页面路由工程使用微信分享及二次分享解决方案
Feb 22 #Javascript
详解关于Vuex的action传入多个参数的问题
Feb 22 #Javascript
Vue.js实现开发购物车功能的方法详解
Feb 22 #Javascript
vue组件之间通信方式实例总结【8种方式】
Feb 22 #Javascript
vue2.0中set添加属性后视图不能更新的解决办法
Feb 22 #Javascript
浅谈Node框架接入ELK实践总结
Feb 22 #Javascript
vue工程全局设置ajax的等待动效的方法
Feb 22 #Javascript
You might like
PHP正确配置mysql(apache环境)
2011/08/28 PHP
详解PHP中cookie和session的区别及cookie和session用法小结
2016/06/12 PHP
利用php-cli和任务计划实现刷新token功能的方法
2017/05/03 PHP
浅谈Laravel中的一个后期静态绑定
2017/08/11 PHP
yii2中LinkPager增加总页数和总记录数的实例
2017/08/28 PHP
详解php中生成标准uuid(guid)的方法
2019/04/28 PHP
js中的escape及unescape函数的php实现代码
2007/09/04 Javascript
根据鼠标的位置动态的控制层的位置
2009/11/24 Javascript
Table冻结表头示例代码
2013/08/20 Javascript
js文件Cookie存取值示例代码
2014/02/20 Javascript
js中通过父级进行查找定位元素
2014/06/15 Javascript
Javascript基于AJAX回调函数传递参数实例分析
2015/12/15 Javascript
javascript 数组的定义和数组的长度
2016/06/07 Javascript
深入理解jQuery 事件处理
2016/06/14 Javascript
BootStrap 实现各种样式的进度条效果
2016/12/07 Javascript
js实现Tab选项卡切换效果
2020/07/17 Javascript
Vue2.0仿饿了么webapp单页面应用详细步骤
2018/07/08 Javascript
JavaScript根据json生成html表格的示例代码
2018/10/24 Javascript
通过实例学习React中事件节流防抖
2019/06/17 Javascript
CKeditor4 字体颜色功能配置方法教程
2019/06/26 Javascript
创建nuxt.js项目流程图解
2020/03/13 Javascript
解决vue2中使用elementUi打包报错的问题
2020/09/22 Javascript
原生js实现购物车功能
2020/09/23 Javascript
Python中的闭包实例详解
2014/08/29 Python
python中尾递归用法实例详解
2015/04/28 Python
Python创建xml文件示例
2017/03/22 Python
浅谈Python线程的同步互斥与死锁
2020/03/22 Python
Python检测端口IP字符串是否合法
2020/06/05 Python
Keras SGD 随机梯度下降优化器参数设置方式
2020/06/19 Python
Under Armour安德玛德国官网:美国高端运动科技品牌
2019/03/09 全球购物
非常详细的C#面试题集
2016/07/13 面试题
计算机专业大学生的自我评价
2013/11/14 职场文书
物流毕业生个人的自我评价
2014/02/13 职场文书
委托书格式要求
2015/01/28 职场文书
感恩节寄语2015
2015/03/24 职场文书
MySQL infobright的安装步骤
2021/04/07 MySQL