使用 Promise 渲染一个 Vue 应用程序,并等待用户输入

Posted

技术标签:

【中文标题】使用 Promise 渲染一个 Vue 应用程序,并等待用户输入【英文标题】:Render a Vue app using a promise, and await user input 【发布时间】:2018-10-22 16:36:51 【问题描述】:

我有一个设计问题,我目前有一个逻辑繁重的 JS 脚本,我将其编写为各种 Promise,并创建了如下结构:

init()
    .then(result => doSomethingA(result)) 
    .then(result => doSomethingB(result))
    .then(result => loadVueApp(result))

现在loadVueApp() 函数调用执行以下操作:

new Vue(
  el : '#app',
  render : h => h(App)
);

它会呈现我的 Vue 应用程序,然后用户可以与应用程序交互,转到各个屏幕,进行选择,这些选择我存储在全局 EventBus 类型组件中。

现在我的问题是,我应该如何将用户的选择传递回我的承诺之塔?我应该这样做吗?

我可以根据出现的应用程序立即解决loadVueApp,然后再对逻辑繁重的脚本进行函数调用 - 但这感觉不那么干净。

有什么想法吗?

提前致谢。

【问题讨论】:

为什么要将数据传回 promise 链,除非 loadVueApp 仅在做出选择并销毁 Vue 组件后才解析? (是这样吗?否则你为什么要像这样串联承诺?) 是的,这就是我想做的——在用户做出选择并关闭应用程序之前保持承诺未解决。 【参考方案1】:

这是一个简单的示例,它执行以下操作:

Vue 组件从模板实例化并附加到 <body> 元素,而不是从现有 DOM 元素(以防您不希望 UI 最初可见)。 只有在单击提交按钮时,才会使用输入的文本解析承诺。组件实例被销毁并从 DOM 中移除。

const InputUI = 
  template: '#input-ui',
  data() 
    return 
      value: '',
    ;
  ,
;

function getInput() 
  return new Promise(resolve => 
    const inputUI = new Vue(InputUI);
    
    inputUI.$once('submit', value => 
      inputUI.$destroy();
      inputUI.$el.remove();
      resolve(value);
    );
    
    inputUI.$mount();
    document.body.appendChild(inputUI.$el);
  );


getInput().then(value => alert(value));
<script src="https://rawgit.com/vuejs/vue/dev/dist/vue.js"></script>

<template id="input-ui">
  <div>
    <input v-model="value">
    <button @click="$emit('submit', value)">Submit</button>
  </div>
</template>

如果您使用单个文件组件,您的代码结构应该类似于:

InputUI.vue

<template>
  <div>
    <input v-model="value">
    <button @click="$emit('submit', value)">Submit</button>
  </div>
</template>

<script>

export default 
  data() 
    return 
      value: '',
    ;
  ,
;

</script>

ma​​in.js

import Vue from 'vue';
import InputUI from './InputUI.vue';

function getInput() 
  return new Promise(resolve => 
    const InputUIVue = Vue.extend(InputUI);
    const inputUI = new InputUIVue();

    inputUI.$once('submit', value => 
      inputUI.$destroy();
      inputUI.$el.remove();
      resolve(value);
    );

    inputUI.$mount();
    document.body.appendChild(inputUI.$el);
  );


getInput().then(value => alert(value));

【讨论】:

感谢这个解决方案,它看起来不错 - 但这需要手动编译或使用渲染功能。我正在使用单个文件组件。 我没有使用渲染函数,我的示例中没有任何内容不能转换为单个文件组件。 来自文档:However, if you are relying on mounting to an element with existing content as template (using the el option), you will still be subject to those limitations. 我想尽可能避免添加编译器,还是我遗漏了什么? 我的答案以这种方式编写的唯一原因是让它可以在线运行。要使其成为单个文件组件,您所要做的就是将&lt;template&gt; 和组件定义代码照常放入.vue 文件中(并删除template: '#input-ui')。其他一切都保持不变。 嗯,对不起@Decade Moon,不确定我做错了什么:- Component template requires a root element, rather than just text. 但如果我删除对template 的引用,那么对new Vue() 的调用将如何知道从哪里得到html 来自?

以上是关于使用 Promise 渲染一个 Vue 应用程序,并等待用户输入的主要内容,如果未能解决你的问题,请参考以下文章

setTimeout与Promise的区别

vue promise.all使用

React 帮助:在映射数组中使用 Promise 进行条件渲染 [关闭]

vue开发的网页打包后在IE浏览器下显示promise未定义怎么解决?

在 forEach 之后使用 Promise.all() 渲染 NodeJS 页面之前等待 Firebase 数据加载

在vue中使用Promise