写本篇文章之前其实也关注过 vue 中的一个关于加载动态组件 is 的 API, 最开始研究它只是用来实现一个 tab 切换的功能, 使用起来也蛮不错的.
is
预期: string | Object (组件的选项对象)
用于动态组件且基于 DOM 内模板的限制来工作.
示例:
- <!-- 当 `currentView` 改变时, 组件也跟着改变 -->
- <component v-bind:is="currentView">
- </component>
详见 vue API 中关于 is 的定义和用法 https://cn.vuejs.org/v2/api/#is
至于用在 tab 切换中, 大概就是:
- <template>
- <div>
- <div># 动态组件实现 tab 切换效果 #</div><br><br><br>
- <nav>
- <a href="javascript:void(0);" @click="toggleTabs(first);">{{first}}</a>
- <a href="javascript:void(0);" @click="toggleTabs(second);">{{second}}</a>
- <a href="javascript:void(0);" @click="toggleTabs(third);">{{third}}</a>
- </nav>
- <first :is="currentView" keep-alive></first>
- </div>
- </template>
- <script>
- import first from 'components/first';
- import second from 'components/second';
- import third from 'components/third';
- export default {
- data () {
- return {
- first: "first",
- second: "second",
- third: "third",
- currentView: 'first',
- };
- },
- components: {
- first,
- second,
- third
- },
- methods: {
- toggleTabs (tabText) {
- this.currentView = tabText;
- }
- }
- }
- </script>
但是今天, 一个前端同行在群里问我 "如果当前页面是根据传进来的参数的不同而显示不同的组件, 而且当前页面中可能会 import 进来几十个子组件, 而我又不想挨个去 import 这些组件, 同时这些组件又是按需加载的, 该咋实现?" 说实话, 一开始我也懵了.
我在想, 实在不行就用 const demo = () => import ( './demo.vue'), 或者在组件的 components: 中按需引入:
- components: {
- demo: () => import ( './demo.vue')
- }
但是我一想, 也不对啊, 这样虽然能实现按需加载, 但是还是要挨个 import 这些组件, 还是没有解决实际的问题.
经过查阅资料发现, vue 有一个 extend 的方法可以实现. 那么这个 extend 方法到底是干嘛的?
Vue.extend( options )
Vue.extend 返回的是一个 "扩展实例构造器", 也就是预设了部分选项的 Vue 实例构造器. 经常服务于 Vue.component 用来生成组件, 可以简单理解为当在模板中遇到该组件名称作为标签的自定义元素时, 会自动调用 "扩展实例构造器" 来生成组件实例, 并挂载到自定义元素上.
只是, extend 创建的是一个组件构造器, 而不是一个具体的组件实例, 所以他不能直接在 new Vue 中这样使用.
使用 Vue.extend 创建的组件构造器最终是可以通过 Vue.components 注册成全局组件或 new 实例化后注册为局部组件.
接下来就来实现以下使用 Vue.extend 和 Vue.components 注册全局组件:
- import Vue from 'vue';
- const globalComponent = Vue.extend({
- template:"<p><a :href='url'>{{nama}}</a></p>",
- data:function(){
- return{
- nama:'某度',
- url:'http://www.moudu.com'
- }
- }
- });
- Vue.component('globalComponent', globalComponent);
使用这个全局注册的组件:
- <template>
- <globalComponent />
- </template>
注册全局组件还是很简单的, 接下来就来实现根据传参的不同加载不同组件的方法:
- <template>
- <button type="button" @click="toggle('test')"> 动态注册组件 < button>
- <p><div ref="currentView"></div>
- </template>
- <script>
- import Vue from 'vue'
- export default {
- data(){
- return {}
- },
- methods: {
- toggle(componentName){
- this.registerComponent(componentName).then(Component => {
- // new Component().$mount(this.$refs.currentView)
- new Component({
- el: this.$refs.currentView
- })
- })
- },
- registerComponent(componentName) {
- return import(`@/views/${componentName}.vue`).then(component => {
- return Vue.extend(component.default);
- });
- }
- },
- }
- </script>
这样, 我们就可以根据动态传入的参数, 通过 import(@/views/${componentName}.vue) 来加载不同的组件, 注意 import 有一个回调的方法, 在该回调中就可以使用 Vue.extend(component.default) 来创建一个组件的构造器, 然后通过 new 关键字就可以实现局部注册组件了.
本文参考:
Vue2.0 - 构造器的延伸 Vue.extend
vue extend 的基本使用
来源: https://www.cnblogs.com/tnnyang/p/10945399.html