【问题标题】:How to add Vue 3 components programmatically?如何以编程方式添加 Vue 3 组件?
【发布时间】:2021-05-16 02:36:31
【问题描述】:

Vue 3 没有 Vue.extend() 方法,所以这里的例子不起作用: https://css-tricks.com/creating-vue-js-component-instances-programmatically/

我已经尝试过这个解决方案: https://jsfiddle.net/jamesbrndwgn/fsoe7cuy/

但它会在控制台中引起警告:

Vue 收到了一个组件,该组件被制成反应性对象。这可能会导致不必要的性能开销,应通过使用markRaw 标记组件或使用shallowRef 而不是ref 来避免。

enter image description here

那么,在 Vue 3 中动态(以编程方式)添加组件的正确方法是什么?

上传任务标签管理器.vue

<template>
    <button @click="addTag()" type="button">Add new tag</button>
    <br>
    <div>
        <div v-for="child in children" :key="child.name">
            <component :is="child"></component>
        </div>
    </div>
</template>

<script>
    import UploadTaskTag from "./UploadTaskTag";

    export default {
        name: "UploadTaskTagManager",
        components: {UploadTaskTag},

        data() {
            return {
                children: []
            }
        },

        methods: {
            addTag() {
                this.children.push(UploadTaskTag);
            },
        }
    }
</script>

UploadTaskTag.vue

<template>
    <div>
        <select @change="onChangeTag($event)" v-model="currentTag">
            <option v-for="tag in getAllTags()" :key="tag.tag_name" :value="tag">{{tag.tag_name}}</option>
        </select>
        <input maxlength="16" class="tag-input" ref="inputField"/>
        <button @click="removeTag($event)" type="button">-</button>
        <br>
    </div>
</template>

<script>
    export default {
        name: "UploadTaskTag",

        data() {
            return {
                tags: [],
                currentTag: {}
            }
        },

        methods: {
            onChangeTag(event) {
                this.$refs.inputField.value = this.currentTag.tag_name;
            },

            getAllTags() {
                return this.$store.state.allTags;
            },

            removeTag() {
                this.$el.parentElement.removeChild(this.$el)
            },

            getValue(fieldIndex) {
                let tag = this.tags[fieldIndex];
                return tag ? tag.tag_name : "";
            },
        }
    }
</script>

【问题讨论】:

    标签: vue.js vue-component vuejs3


    【解决方案1】:

    只需使用createApp 而不是Vue.extend 这是一个以编程方式的简单 vue3 组件示例

    import Button from 'Button.vue'
    import { createApp } from "vue"
    // Creating the Instance
    // use createApp https://v3.vuejs.org/api/global-api.html#createapp
    var ComponentApp = createApp(Button)
    import Button from "./Button.vue"
    
    // inserting to dom
    const wrapper = document.createElement("div")
    ComponentApp.mount(wrapper)
    document.body.appendChild(wrapper)
    

    使用hhttps://v3.vuejs.org/api/global-api.html#h,设置道具或插槽略有不同

    import Button from 'Button.vue'
    import { createApp, h } from "vue"
    
    var ComponentApp = createApp({ 
      setup () {
        return () => h(Button, {type: "primary"}, "default slot as children")
      }
    })
    

    【讨论】:

    • 不知何故,使用 createApp() 以编程方式添加一个小的 Vue 组件感觉不对。它让我想起了臃肿和头顶的景象。不过我必须把它交给你,你的回答就可以了。
    • 我面临着类似的问题。我只想动态创建一个组件并将其附加到 Vue 3 中的 DOM 中,这似乎不必要地困难。为什么要创建一个新的 Vue 实例?我不明白。没有更简单的方法吗?
    【解决方案2】:

    如果我理解正确,那么解决方案将是这样的

    您可以在官网https://v3.vuejs.org/api/global-api.html#defineasynccomponent了解更多关于'defineAsyncComponent'的信息

    <template>
        <button @click="addTag()" type="button">Add new tag</button>
        <br>
        <div>
            <div v-for="child in children" :key="child.name">
                <component :is="child"></component>
            </div>
        </div>
    </template>
    
    <script>
    
    import { defineAsyncComponent, defineComponent, ref } from "vue"
    
    export default defineComponent({
    components: {     
          UploadTaskTag: defineAsyncComponent(() => import("./UploadTaskTag"))
        },
     setup() {
          const children = ref([])
    
          const addTag = () => {
            children.value.push('UploadTaskTag')
            console.log(children.value)
          }
    return {
            addTag,
            children        
          }
        },
      })
    </script>
    

    【讨论】:

      猜你喜欢
      • 2021-12-12
      • 1970-01-01
      • 2013-12-23
      • 2014-08-16
      • 2015-03-11
      • 2015-05-01
      • 2016-11-23
      • 2012-09-16
      • 2014-07-03
      相关资源
      最近更新 更多