如何在特定事件之后渲染/创建 Vue 组件(例如 @click @change)

Posted

技术标签:

【中文标题】如何在特定事件之后渲染/创建 Vue 组件(例如 @click @change)【英文标题】:How to render/create a Vue component after an specific event (e.g. @click @change) 【发布时间】:2019-01-14 10:53:03 【问题描述】:

我是 Vue JS 的新手,现在面临一个问题,这似乎应该很容易,但我找不到解决方法。

这就是我想做的事情和原因: - 我想首先从服务器/本地加载一些数据,编辑数据,并将数据显示给用户。但是要加载哪些数据是由用户决定的(通过按钮,例如点击事件)

因为显示数据的方式有点过于复杂(我指的是html代码,UI),所以我决定创建一个全局组件来处理它,这样我的Vue实例就不会乱了。

我已经做了部分组件,但问题是,每次我刷新页面时,都会出现警告,说某些参数未定义。

当然一开始就没有定义,因为用户还没有选择加载哪些数据。

有这方面经验的可以告诉我。如何告诉 Vue 在单击事件之后渲染组件?

我将尝试在下面做一个简化的代码示例,以便您更好地理解:

- main.js 文件的一部分(简化)

// the global Vue component
var infoBox = Vue.component('info-box', 
    props:['infos'],
    template:`
        <div>
            <li> infos.name </li>
            <li> infos.id </li>
            <li> infos.title </li>
            <li> infos.whatever </li> // continues..also simplified, actually I need to edit the infos first
        </div>
    `


// the Vue instance
var app = new Vue (
    el: '#app',
    data: 
        data: '',
    ,
    methods: 
        loadData: function() 
            // load the needed data from the server
            this.data = $.getJSON(/*....*/) // just for example that I loaded some data and push it to the instance


        
    
)

- HTML 文件的一部分

<div id="app">
    <button @click="loadData"></button> // also simplified, the real project has different kinds of buttons, the user can decide which data should be loaded
    <info-box :infos="data"></info-box> // get the data from the Vue instance, which does not exist until the button was clicked the the data was loaded
</div>

有关我的问题的更多详细信息: - 工作流程实际上还可以,因为我已经在 Vue 实例中定义了一个空的“数据”。真正的问题是在组件内部,当我想编辑和处理一些数据时,因为在点击之前,数据是空的,所以我得到了很多“XXX未定义”的警告,因为我使用的一些功能没有允许未定义的道具。

我想要的完美方式:有什么方法可以对 Vue 说:好的,现在单击按钮,让我们看看,数据已加载,现在请渲染/创建组件。

如果没有,我唯一能做的就是在创建 Vue 实例时先加载所有数据。但显然数据太多,会出问题。

我尝试理解Vue官方文档“异步组件”,这似乎是对我来说最好的解决方案:

https://vuejs.org/v2/guide/components-dynamic-async.html

但我不能再进一步了,因为我根本无法理解这一点,也无法在我的项目中使用它(我认为这段代码是告诉 Vue 的关键,即他现在可以渲染/创建组件):

require(['./my-async-component'], resolve)
另外,setTimeOut不是我想要的,因为如果用户不点击按钮,我们可以等到世界末日,数据总是空的。

【问题讨论】:

v-if 似乎是适合您的最佳解决方案。 【参考方案1】:

有很多方法可以解决这个问题。

您可以简单地在您的组件上设置一个v-if="data",它只会在您的数据加载时加载整个组件。通常我会在下面放另一个元素 v-else 并有一个加载微调器组件或类似的东西。

如果你想拥有组件的布局,你可以在 info-box 组件的模板中做同样的事情。

<div>
    <div class="wrapper" v-if="infos">
        <li> infos.name </li>
        <li> infos.id </li>
        <li> infos.title </li>
        <li> infos.whatever </li>
    </div>

    <div class="spinner-loading">
        Put your loading animation here
    </div>
</div>

异步组件对您没有帮助,因为异步组件可能在您的 AJAX 请求实际完成之前实际加载。您误解了异步组件的工作原理。

您还可以为每个信息属性创建计算属性,并在未设置时放入占位符,以便您可以单独管理它们。这里有很多选项,但您需要确保在显示模板之前有数据或至少有一个占位符。

【讨论】:

以上是关于如何在特定事件之后渲染/创建 Vue 组件(例如 @click @change)的主要内容,如果未能解决你的问题,请参考以下文章

vue利用渲染函数创建弹窗组件,完美支持传值和事件监听

vue组件生命周期

如何在使用 Vue.js 触发任何事件时创建新组件?

vue生命周期详解

Vue的生命周期

vue 图片加载完成事件