【问题标题】:How do i dynamically generate vue components from wordpress custom fields如何从 wordpress 自定义字段动态生成 vue 组件
【发布时间】:2020-08-04 22:32:24
【问题描述】:

我正在使用带有nuxt的vue构建一个网站,通过rest api从wordress站点加载数据。

我想让客户端能够使用自定义字段修改页面模板,因此我需要使用根据放置在 wordpress 页面编辑器中的自定义字段生成的 vue 组件动态创建我的 vue 模板。

这是简化的,但例如,如果客户构建一个包含三个自定义字段的页面:

[custom-field type='hero']
[custom-field type='slider']
[custom-field type='testimonial']

我可以通过json对象中的rest api获取字段信息,如下所示:

page: {
  acf: [
    {field 1: {
      {type: 'hero'},
      {content: '...'} 
    },
    {field 2: {
      {type:'slider'},
      {content: '...'} 
    },
    {field 3: {
      {type:'testimonial'},
      {content: '...'} 
    }
  }
}

我将把它带入我的 vue 应用程序,然后我将模板从映射到自定义字段类型的可能组件列表中动态生成。以上将输出:

<template>
  <Hero ... />
  <Slider ... />
  <Testimonial ... />
</template>

这是否可以使用 v-is 指令 (https://vuejs.org/v2/guide/components-dynamic-async.html) 来完成,例如:

<component v-for="field in custom-fields" v-is="field.type" :data="field.data"/>? 

这可能吗?任何帮助将不胜感激。

【问题讨论】:

    标签: javascript wordpress vue.js advanced-custom-fields wordpress-rest-api


    【解决方案1】:

    您可以在 Nuxt 中动态注册和显示组件,但有一些注意事项。

    方法 1 - SSR 和 SSG 支持

    此方法将动态注册您的组件并保持服务器端渲染/静态站点生成的完整性。

    这里唯一的权衡是您需要列出所有潜在导入组件的名称和文件位置。这对您的用例来说应该不会太麻烦(我不认为您有太多 ACF 字段),但如果您打算从中构建整个组件库,这可能是一项冗长的工作。

    <template>
      <div>
        <div v-for="field in page.acf" :key="field.uniqueId">
          <component :is="field.type" :my-prop="field.content" />
        </div>
      </div>
    </template>
    
    <script>
    export default {
      components: {
        hero: () => import('~/components/hero.vue'),
        slider: () => import('~/components/slider.vue'),
        testimonial: () => import('~/components/testimonial.vue')
      },
      data() {
        return {
          page: {
            acf: [
              {
                uniqueId: 1,
                type: 'hero',
                content: '...'
              },
              {
                uniqueId: 2,
                type: 'slider',
                content: '...'
              },
              {
                uniqueId: 3,
                type: 'testimonial',
                content: '...'
              }
            ]
          }
        }
      }
    }
    </script>
    

    方法 2 - 仅客户端渲染

    此方法允许您以编程方式注册组件的名称和文件位置。这使您不必逐个写出每个组件,但代价是没有 SSR 或 SSG 支持。但是,如果您要走 SPA 路线,这可能更可取。

    <template>
      <div>
        <div v-for="field in page.acf" :key="field.uniqueId">
          <no-ssr>
            <component :is="field.type" :my-prop="field.content" />
          </no-ssr>
        </div>
      </div>
    </template>
    
    <script>
    import Vue from 'vue'
    
    export default {
      data() {
        return {
          page: {
            acf: [
              {
                uniqueId: 1,
                type: 'hero',
                content: '...'
              },
              {
                uniqueId: 2,
                type: 'slider',
                content: '...'
              },
              {
                uniqueId: 3,
                type: 'testimonial',
                content: '...'
              }
            ]
          }
        }
      },
      mounted() {
        const sections = this.page.acf
        for (let i = 0; i < sections.length; i++) {
          Vue.component(sections[i].type, () =>
            import(`~/components/${sections[i].type}.vue`)
          )
        }
      }
    }
    </script>
    

    请注意,&lt;no-ssr&gt; 标记已被弃用,如果您在 v2.9.0 之上使用 Nuxt,则应改用 &lt;client-only&gt;

    问题说明

    1. 我了解您已尝试简化数据架构,但您的 JSON 对象将很难循环通过,因为数组中每个对象的键都发生了变化。数据结构中还有不必要的对象。我已经简化了数据方法中的结构,以便您理解这个概念。

    2. 要使 v-for 循环正常工作,您需要将组件嵌套在具有 v-for 属性的 HTML 标记中(如上所示)。

    3. 您可能希望通过确保 WordPress 不向您提供与组件不对应的模块来清理从 WordPress API 获得的数据。如果 API 提供的类型与组件不对应,则整个构建将失败。

    希望这会有所帮助!

    P.S 如果有人知道允许您在维护 SSG 的同时以编程方式设置组件名称和组件文件位置的方法 - 请告诉我!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-12-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多