【问题标题】:Launch a Vue modal component outside of a SPA context在 SPA 上下文之外启动 Vue 模态组件
【发布时间】:2018-08-08 14:24:27
【问题描述】:

我们正在用一些更新的表格改造一个成熟的网站。我们正在用 SPA 完全替换一些系统,而有些系统只是不保证这样做。

但是,我们需要提供一些系统全局模式屏幕。其中一些已移植到 Vue 并在 SPA 中运行良好,我们希望从非 SPA 页面中增强的交互性中获益。

所以之前我们会像这样绑定我们的事件:

$('a.newBooking').on('click', function(ev){
    // code to open bootstrap modal screen, download HTML, etc.
});

我们如何启动组件?

我知道我在这里没有包含任何严肃的代码,但我们的模态基本上只是 documented example modal component 的修饰版本。不同的是我们没有按钮。我们希望能够从页面各处启动这些模式。

【问题讨论】:

  • 可以通过传递给所有 vue 组件并附加到 window 的消息总线来完成。在遗留代码中,您将引导代码替换为window.bus.$emit("open-model-a"),然后在定义模型可行性的 Vue 组件中,您可以监听总线并相应地对显示/隐藏模型做出反应。如果您想通过 Vuex 传递状态更改,同样的原则也适用。如果你真的想在应用程序的其余部分之外启动一个 Vue 组件,你可以创建一个实例并将其挂载到任何地方;无论如何,这正是您在主 SPA 根目录中所做的事情
  • 类似Vue Single instance Modal 的东西?您可以在应用的任何位置访问模式。
  • 你是如何展示这个模态的?当你没有按钮?有显示:无 |显示:阻止?还是?
  • 在我看来,您寻求帮助的目的并不完全清楚。我的理解是你已经有一个提供模态的Vue组件;您在 SPA 中使用它,但您想在非 SPA 中按原样重新使用它。在这种情况下,第一步是在您的非 SPA 中发送 process your Vue component so that it can be easily consumed;那么如何设置你的非SPA(你可能对converting your component into a Custom Element感兴趣);最后如何配置您的侦听器以打开模式。

标签: vue.js


【解决方案1】:

我的看法:

对于您的模态组件:

  1. 对你的modal使用单例模式(因为基本上我们只允许同时弹出一个modal popup),这样逻辑会更简单。

  2. 自定义一个安装函数以将您的 Modals 的 Vue 实例添加到 Vue.prototype,例如 _Vue.prototype.$my = yourModals

  3. 然后根据需要注册您的插件,例如Vue.use(installFunc, {plugins: [SModal, AModal, BModal]})

在您的 JQuery(或其他非 Vue)应用程序中:

  1. 将Modal注册到Vue,然后创建Vue实例

  2. 显示或隐藏您的模态框,例如 vueInstance.$my.SModal.show

下面是一个简单的演示

Vue.config.productionTip = false

/*---Modal Plugin---*/
let vm = null // the instance for your Vue modal
let timeout = null //async/delay popup

const SModal = {
  isActive: false,

  show ({
    delay = 500,
    message = '',
    customClass = 'my-modal-class'
  } = {}) {
    if (this.isActive) {
      vm && vm.$forceUpdate()
      return
    }

    timeout = setTimeout(() => {
      timeout = null

      const node = document.createElement('div')
      document.body.appendChild(node)
      let staticClass = ''
      vm = new this.__Vue({
        name: 's-modal',
        el: node,
        render (h) { // uses render() which is a closer-to-the-compiler alternative to templates
          return h('div', {
            staticClass,
            'class': customClass,
            domProps: {
              innerHTML: message
            }
          })
        }
      })
    }, delay)

    this.isActive = true
  },
  hide () {
    if (!this.isActive) {
      return
    }

    if (timeout) {
      clearTimeout(timeout)
      timeout = null
    } else {
      vm.$destroy()
      document.body.removeChild(vm.$el)
      vm = null
    }

    this.isActive = false
  },

  __Vue: null,
  __installed: false,
  install ({ $my, Vue }) {
    if (this.__installed) { return }
    this.__installed = true
    $my.SModal = SModal // added your SModal object to $my
    this.__Vue = Vue //get the Vue constructor
  }
}

/*---Modal Plugin End---*/

/*---Custom Install Function in order to manage all modals---*/
let installFunc = function (_Vue, opts = {}) {
  if (this.__installed) {
    return
  }
  this.__installed = true
  const $my = {
    'memo': 'I am a plugin management.'
  }
  if (opts.plugins) {
    Object.keys(opts.plugins).forEach(key => {
      const p = opts.plugins[key]
      if (typeof p.install === 'function') {
        p.install({ $my, Vue: _Vue })
      }
    })
  }
  _Vue.prototype.$my = $my
}

/*---Install Plugins---*/
Vue.use(installFunc, {
  plugins: [SModal]
})

let globalVue = new Vue({
  el: '#vue-app'
})

$('#test').on('click', 'span', function () {
  globalVue.$my.SModal.isActive ? globalVue.$my.SModal.hide() :  globalVue.$my.SModal.show({'message':'test', 'delay':100})
})
span {
  cursor:pointer;
  color:red;
}

.my-modal-class {
  position:absolute;
  top:50px;
  left:150px;
  width:200px;
  height:200px;
  background-color:red;
  z-index:9999;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<div id="vue-app">
</div>
<div id="test">
  <h3>One Example</h3>
  <p><span>Hello</span>, how are you?</p>
  <p>Me? I'm <span>good</span>.</p>
</div>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-03-20
    • 1970-01-01
    • 1970-01-01
    • 2020-08-25
    • 2017-09-19
    • 1970-01-01
    • 2017-06-15
    • 1970-01-01
    相关资源
    最近更新 更多