簡體   English   中英

可以從 vue 組件外部打開模態

[英]Possible to open modal from outside the vue component

是否可以從組件外部調用方法以使組件可重用?

現在我添加我的按鈕以在模板槽中打開模式:

index.php

<modal>
    <template slot="button">
        <button class="btn">Open modal</button>
    </template>
    Some modal text
</modal>

Modal.vue

<template>
    <div>
        <div @click="showModal"><slot name="button"></slot></div>
        <div v-if="showingModal"><slot></slot></div>
    </div>
</template>

<script>
    export default {

        data () {
            return {
                showingModal: false,
            }
        },

        methods: {
            showModal() {
                this.showingModal = true;
            },
        }
    }
</script>

我覺得有更好的選擇,但我無法弄清楚。

是的,您可以從組件外部調用方法!

父組件

<template>
 <div>
   <modal ref="modal"></modal>
   <button @click="openModal">Open Modal</button>
 </div>
</template>

<script>
  import modal from './child.vue'
  export default {
    components: { modal }
    methods: {
     openModal() { this.$refs.modal.show() }//executing the show method of child
    }
  }
</script>

子組件

<template>
  <div v-if="showModal">
    <div id="modal">
      <p>Hello i am a modal
      </p>
      <button @click="hide">Close</button>
    </div> 
  </div>
</template>

<script>
 export default {
   data() {
     return {
      showModal: false
     }
   },
   methods: {
     show() {
      this.showModal = true
     },
     hide(){
      this.showModal = false
     }
   }
 }
</script>

在此處查看實際操作

modal組件實例放入Vue.prototype中,然后在可以訪問Vue實例上下文的任何地方調用show/hide

下面是一個演示:

 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 } } 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 } Vue.use(installFunc, { plugins: [SModal] }) app = new Vue({ el: "#app", data: { 'test 1': 'Cat in Boots' }, methods: { openModal: function () { this.$my.SModal.show({'message':'test', 'delay':1000}) }, closeModal: function () { this.$my.SModal.hide() } } })
 .my-modal-class { position:absolute; top:50px; left:20px; width:100px; height:100px; background-color:red; z-index:9999; }
 <script src="https://unpkg.com/vue@2.5.16/dist/vue.js"></script> <div id="app"> <button @click="openModal()">Open Modal!!!</button> <button @click="closeModal()">Close Modal!!!</button> </div>

vue-cli 項目的粗略步驟:

在 ./plugins/SModal.js 中(按照官方文檔中的教程創建一個 vue 實例,然后將其添加到document.body中):

let vm = null // the instance for your Vue modal
let timeout = null //async/delay popup

const SModal = {
  isActive: false,

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

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

      const node = document.createElement('div')
      document.body.appendChild(node)

      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': props.customClass
          })
        }
      })
    }, 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
  }
}

export default SModal

正如官方文檔所說,一個 Vue.js 插件應該暴露一個 install 方法。 該方法將使用 Vue 構造函數作為第一個參數以及可能的選項來調用

在 install.js 中(您也可以根據您的設計將此方法移動到 main.js 中):

// loop all plugins under the folder ./plugins/, then install it.
export default 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
}

在 main.js 中(最終使用您的插件):

import install from './install'
import * as plugins from './plugins'

Vue.use({ install }, {
  plugins
})

最后在您的視圖/組件中,您可以像這樣顯示/隱藏您的模式:

this.$my.SModal.show()
this.$my.SModal.hide()

當然,接受模態組件的屬性:

 props: ['open']

然后傳入:

<modal :open="boolToOpenModal"> ... </modal>

然后:

<div v-if="showingModal || open"><slot></slot></div>

沒有(簡單的,受支持的)方法來調用組件中的方法,但是您可以修改子中的屬性(例如show )(請參閱使用 Props 將數據傳遞給子組件)或使用事件(請參閱自定義事件$emit$refs )。 使用事件,您也可以使用事件總線 基於事件的解決方案當然更適合更復雜的交互。

我只是將v-on="$listeners"添加到子組件(modal.vue)中:

// modal.vue
<template>
   <div :show="show" v-on="$listeners">
     ...
   </div>
</template>

<script>

export default {
    props: {
        show: {
            type: Boolean,
            default: false
        }
    },
    ...

現在您可以輕松地從其父模式打開或關閉模式:

//parent.vue
<modal @close="showModal = false" :show="showModal" />

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM