使用VueJS的动态组件

根据名称,字符串或配置加载和创建VueJS组件。

首先,如果您刚开始使用VueJS,这对您来说可能有点太高级了,我强烈建议您阅读VueJS上的文档,尤其是组件。

前言

根据用户输入交换组件,甚至只是通过json文件设置表单,这是一个非常有用的方法,可以在整个大项目中保持较低的理智水平,因为通常有数百个组件/表单/页面/等,所以进行更改在代码中,它可能会导致涟漪效应,并打破其他地方的东西。

由于VueJS将处理DOM的所有脏细节,因此我们可以专注于解决业务问题。

我将介绍按名称加载组件,创建动态和异步组件。

组件的“神奇”

如果没有<component v-bind:is="dynComponent"></component>检查动态和异步组件以获取更多详细信息,那么动态操作就不那么容易了。基本上,组件将呈现组件,异步功能或组件名称。

按名称加载组件

使用<component/>将允许您按名称访问全局和本地组件。

在Codepen上试试吧

// add some different components globaly
Vue.component("test-comp0", {
  template: `<p>comp0</p>`
});

Vue.component("test-comp1", {
  template: `<p>comp1</p>`
});

Vue.component("test-comp2", {
  template: `<p>comp2</p>`
});

// sample app
new Vue({
  el: "#app",

  components: {
    // add a local component
    // check https://vuejs.org/v2/guide/components-registration.html#Component-Names
    TestComp3: {
      template: `<p>comp3 locally registered component</p>`
    }
    // you can also add some components from other files, using ES6 import or required.
  },

  data() {
    return {
      componentIndex: 0
    };
  },

  computed: {
    componentName() {
      return "test-comp" + this.componentIndex;
    }
  },

  template: `
      <div>
        Component: {{componentIndex}} <button @click="componentIndex=(++componentIndex)%4">change</button>
        <component :is="componentName"></component>
      </div>`
});

组件之间的动态循环

组件之间的循环很有用,但在现实世界中,你会传递一些道具。要添加道具,我们可以更改组件test-comp0和应用模板。

Vue.component("test-comp0", {
  props: ["name"], // please use the object props for production
  template: `<p>Hello {{name}}</p>`
});

...

// add name prop
<component :is="componentName" name="pikax"></component>

在动态组件上使用prop

这会将prop名称传递给每个组件。为了解决这个问题,我们可以有一个计算属性并将其绑定到组件。

// app becomes

new Vue({
  el: "#app",

  components: {
    // add a local component
    // check https://vuejs.org/v2/guide/components-registration.html#Component-Names
    TestComp3: {
      template: `<p>comp3 locally registered component</p>`
    }
    // you can also add some components from other files, using ES6 import or required.
  },

  data() {
    return {
      componentIndex: 0,
      name: "pikax"
    };
  },

  computed: {
    componentName() {
      return "test-comp" + this.componentIndex;
    },
    componentProps() {
      if (this.componentIndex == 0) {
        return {
          name: this.name
        };
      }
      return {}; // return empty object
    }
  },

  template: `
      <div>
        Component: {{componentIndex}} <button @click="componentIndex=(++componentIndex)%4">change</button>
        <component :is="componentName" v-bind="componentProps"></component>
      </div>`
});

根据组件传递道具

即时组件

即时组件是我们使用javascript生成的组件,<component></component>这显示了它的强大功能,一些用例场景将构建小部件。

我们可以根据用户输入生成和测试组件。

注意:要非常小心,这可能允许攻击者攻击您的应用程序,请确保源是可信的!

在Codepen上试试吧

new Vue({
  el: "#app",

  data() {
    return {
      componentDefinition: `{ template: "<div>Hello</div>" }`
    };
  },

  computed: {
    myComponent() {
      return eval(`(${this.componentDefinition})`);
    }
  },

  template: `<div>
    <p>Change me</p>
    <textarea v-model="componentDefinition" rows="4" cols="50"></textarea>
    <component v-if="myComponent" :is="myComponent"></component>
</div>
`
});

使用textarea的完全动态组件

您可以在更改textarea时看到,组件应该立即渲染。我不建议使用它,但我认为这是一个很好的例子<component></component>

导入异步组件

这对我来说是组件最有用的用例。我非常推荐阅读官方指南

Vue.component(
  "async-webpack-example",
  // The `import` function returns a Promise.
  () => import("./my-async-component")
);

导入异步webpack

真实世界的问题

在我的上一个项目中,我们遇到了一个问题,我们想收集用户信息,但字段会根据旅程而改变,有些旅程需要电子邮件,其他人需要电子邮件和电话。

解决方案是将旅程定义放在JSON文件中,每次用户启动旅程时我们都会加载该文件并加载字段。策略是使用名称加载组件按名称动态加载组件,但我们最终加载了所有可能的编辑器Vue.Component,这工作...但在启动时加载它们意味着启动时间和应用程序大小更大比需要的。

解决方法

使用AsyncDynamic组件和Webpack的混合。

// returning equivalent of webpack : import(name)
const getComponent = async path => {
  /* I recomend having an switch with the possible components you will load, this
   *   will allow you only load specific components.
   */
  if (path == 1) {
    return async () => {
      template: `<p>component 0</p>`;
    };
  } else {
    return async () => {
      template: `<p>${path}</p>`;
    };
  }
};

Vue.component("component-fallback", {
  template: `<div>This is not the component you're looking for</div>`
});

new Vue({
  el: "#app",
  data() {
    return {
      componentIndex: 0,
      component: "component-fallback"
    };
  },

  methods: {
    changeComponent() {
      const newIndex = ++this.componentIndex;
      this.loadComponent(newIndex);
    },

    // returns the component
    loadComponent(name) {
      const componentFunc = getComponent(name)
        .then(x => {
          this.component = x;
        })
        .catch(e => {
          this.component = "component-fallback";
        });
    }
  },

  template: `
        <div>
            Component: {{componentIndex}} <button @click="changeComponent">change</button>
            <component :is="component"></component>
        </div>
        `
});

使用回退加载动态组件

希望我的第一篇文章对你有用,我发现它有多么强大和灵活<component></component>

如果您有任何更多用例,请<component></component>在评论中告诉我。

转:https://medium.com/@pikax.dev/dynamic-components-using-vuejs-9a633cbc0ad0

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,245评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,749评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,960评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,575评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,668评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,670评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,664评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,422评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,864评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,178评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,340评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,015评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,646评论 3 323
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,265评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,494评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,261评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,206评论 2 352

推荐阅读更多精彩内容

  • 基于Vue的一些资料 内容 UI组件 开发框架 实用库 服务端 辅助工具 应用实例 Demo示例 element★...
    尝了又尝阅读 1,147评论 0 1
  • UI组件 element - 饿了么出品的Vue2的web UI工具套件 Vux - 基于Vue和WeUI的组...
    鲁大师666阅读 43,386评论 5 97
  • UI组件 element- 饿了么出品的Vue2的web UI工具套件 Vux- 基于Vue和WeUI的组件库 m...
    小姜先森o0O阅读 9,459评论 0 72
  • UI组件 element- 饿了么出品的Vue2的web UI工具套件 Vux- 基于Vue和WeUI的组件库 m...
    王喂马_阅读 6,452评论 1 77
  • UI组件 element - 饿了么出品的Vue2的web UI工具套件 Vux - 基于Vue和WeUI的组件库...
    卞卞村长L阅读 1,704评论 0 8