欧美一级特黄大片做受成人-亚洲成人一区二区电影-激情熟女一区二区三区-日韩专区欧美专区国产专区

Vue如何實現(xiàn)彈窗Modal

這篇文章給大家分享的是有關(guān)Vue如何實現(xiàn)彈窗Modal的內(nèi)容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。

10余年的宜春網(wǎng)站建設(shè)經(jīng)驗,針對設(shè)計、前端、開發(fā)、售后、文案、推廣等六對一服務(wù),響應(yīng)快,48小時及時工作處理。營銷型網(wǎng)站的優(yōu)勢是能夠根據(jù)用戶設(shè)備顯示端的尺寸不同,自動調(diào)整宜春建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設(shè)計,從而大程度地提升瀏覽體驗。創(chuàng)新互聯(lián)從事“宜春網(wǎng)站設(shè)計”,“宜春網(wǎng)站推廣”以來,每個客戶項目都認(rèn)真落實執(zhí)行。

Vue作為最近最炙手可熱的前端框架,其簡單的入門方式和功能強(qiáng)大的API是其優(yōu)點。而同時因為其API的多樣性和豐富性,所以他的很多開發(fā)方式就和一切基于組件的React不同,如果沒有對Vue的API(有一些甚至文檔都沒提到)有一個全面的了解,那么在開發(fā)和設(shè)計一個組件的時候有可能就會繞一個大圈子,所以我非常推薦各位在學(xué)習(xí)Vue的時候先要對Vue核心的所有API都有一個了解。這篇文章我會從實踐出發(fā),遇到一些知識點會順帶總結(jié)一下。文章很長,一次看不完可以先收藏,如果你剛?cè)腴Tvue,那么相信這篇文章對你以后的提升絕對有幫助

進(jìn)入正題,我相信不論什么項目幾乎都會有一個必不可少的功能,就是用戶操作反饋、或者提醒.像這樣(簡單的一個demo)

Vue如何實現(xiàn)彈窗Modal

Vue如何實現(xiàn)彈窗Modal

其實在vue的中大型項目中,這些類似的小功能會更加豐富以及嚴(yán)謹(jǐn),而在以Vue作為核心框架的前端項目中,因為Vue本身是一個組件化和虛擬Dom的框架,要實現(xiàn)一個通知組件的展示當(dāng)然是非常簡單的。但因為通知組件的使用特性,直接在模板當(dāng)中書寫組件并通過v-show或者props控制通知組件的顯示顯然是非常不方便的并且這樣意味著你的代碼結(jié)構(gòu)要變,當(dāng)各種各樣的彈層變多的時候,我們都將其掛載到APP或者一個組件下顯然不太合理,而且如果要在action或者其他非組件場景中要用到通知,那么純組件模式的用法也無法實現(xiàn)。那么有沒有辦法即用到Vue組件化特性方便得實現(xiàn)一個通知組件的展現(xiàn),那么我們可否用一個方法來控制彈層組件的顯示和隱藏呢?

目標(biāo)一

實現(xiàn)一個簡單的反饋通知,可以通過方法在組件內(nèi)直接調(diào)用。比如Vue.$confirm({...obj})

首先,我們來實現(xiàn)通知組件,相信這個大部分人都能寫出來一個像模像樣的組件,不啰嗦,直接上代碼

<template>
  <div
    :class="type"
    class="eqc-notifier">
    <i
      :class="iconClass"
      class="icon fl"/>
    <span>{{ msg }}</span>
  <!-- <span class="close fr eqf-no" @click="close"></span> -->
  </div>
</template>

<script>
export default {
  name: 'Notification',
  props: {
    type: {
      type: String,
      default: ''
    },
    msg: {
      type: String,
      default: ''
    }
  },
  computed: {
    iconClass() {
      switch (this.type) {
        case 'success':
          return 'eqf-info-f'
        case 'fail':
          return 'eqf-no-f'
        case 'info':
          return 'eqf-info-f'
        case 'warn':
          return 'eqf-alert-f'
      }
    }
  },
  mounted() {
    setTimeout(() => this.close(), 4000)
  },
  methods: {
    close() {
    }
  }
}
</script>

<style lang="scss">
  .eqc-notifier {
    position: fixed;
    top: 68px;
    left: 50%;
    height: 36px;
    padding-right: 10px;
    line-height: 36px;
    box-shadow: 0 0 16px 0 rgba(0, 0, 0, 0.16);
    border-radius: 3px;
    background: #fff;
    z-index: 100; // 層級最高
    transform: translateX(-50%);
    animation: fade-in 0.3s;
  .icon {
    margin: 10px;
    font-size: 16px;
  }
  .close {
    margin: 8px;
    font-size: 20px;
    color: #666;
    transition: all 0.3s;
    cursor: pointer;
    &:hover {
      color: #ff296a;
    }
  }
  &.success {
    color: #1bc7b1;
  }
  &.fail {
    color: #ff296a;
  }
  &.info {
    color: #1593ff;
  }
  &.warn {
    color: #f89300;
  }
  &.close {
    animation: fade-out 0.3s;
  }
  }
</style>

在這里需要注意,我們定義了一個close方法,但內(nèi)容是空的,雖然在模板上有用到,但是似乎沒什么意義,在后面我們要擴(kuò)展組件的時候我會講到為什么要這么做。

創(chuàng)建完這個組件之后,我們就可以在模板中使用了<notification type="xxx" msg="xxx" />

實現(xiàn)通過方法調(diào)用該通知組件

其實在實現(xiàn)通過方法調(diào)用之前,我們需要擴(kuò)展一下這個組件,因為僅僅這些屬性,并不夠我們使用。在使用方法調(diào)用的時候,我們需要考慮一下幾個問題:

  • 顯示反饋的定位

  • 組件的出現(xiàn)和自動消失控制

  • 連續(xù)多次調(diào)用通知方法,如何排版多個通知

在這個前提下,我們需要擴(kuò)展該組件,但是擴(kuò)展的這些屬性不能直接放在原組件內(nèi),因為這些可能會影響組件在模板內(nèi)的使用,那怎么辦呢?這時候我們就要用到Vue里面非常好用的一個API,extend,通過他去繼承原組件的屬性并擴(kuò)展他。

來看代碼

import Notifier from './Notifier.vue'

function install(Vue) {
  Vue.notifier = Vue.prototype.notifier = {
    success,
    fail,
    info,
    warn
  }
}

function open(type, msg) {
  let UiNotifier = Vue.extend(Notifier)
  let vm = new UiNotifier({
    propsData: { type, msg },
    methods: {
      close: function () {
        let dialog = this.$el
        dialog.addEventListener('animationend', () => {
          document.body.removeChild(dialog)
          this.$destroy()
        })
        dialog.className = `${this.type} eqc-notifier close`
        dialog = null
      }
    }
  }).$mount()
  document.body.appendChild(vm.$el)
}

function success(msg) {
  open('success', msg)
}

function fail(msg) {
  open('fail', msg)
}

function info(msg) {
  open('info', msg)
}

function warn(msg) {
  open('warn', msg)
}

Vue.use(install)

export default install

可以看到close方法在這里被實現(xiàn)了,那么為什么要在原組件上面加上那些方法的定義呢?因為需要在模板上綁定,而模板是無法extend的,只能覆蓋,如果要覆蓋重新實現(xiàn),那擴(kuò)展的意義就不是很大了。其實這里只是一個消息彈窗組件,是可以在模板中就被實現(xiàn),還有插件怎么注入,大家都可以自己抉擇。

同時在使用extend的時候要注意:

  1. 方法和屬性的定義是直接覆蓋的

  2. 生命周期方法類似余mixin,會合并,也就是原組件和繼承之后的組件都會被調(diào)用,原組件先調(diào)用

首先通過 let UiNotifier = Vue.extend(Notifier),我們得到了一個類似于Vue的子類,接著就可以通過new UiNotifier({...options})的方式去創(chuàng)建Vue的實例了,同時通過該方式創(chuàng)建的實例,會有組件定義里面的所有屬性。

在創(chuàng)建實例之后,vm.$mount()手動將組件掛載到DOM上面,這樣我們可以不依賴Vue組件樹來輸出DOM片段,達(dá)到自由顯示通知的效果。

擴(kuò)展:

說一下$mount,我們也許很多項目的主文件是這樣的

new Vue({
  router,
  store,
  el: '#app',
  render: h => h(App)
})

其實el與$mount在使用效果上沒有任何區(qū)別,都是為了將實例化后的vue掛載到指定的dom元素中。如果在實例化vue的時候指定el,則該vue將會渲染在此el對應(yīng)的dom中,反之,若沒有指定el,則vue實例會處于一種“未掛載”的狀態(tài),此時可以通過$mount來手動執(zhí)行掛載。值得注意的是如果$mount沒有提供參數(shù),模板將被渲染為文檔之外的的元素,并且你必須使用原生DOM API把它插入文檔中,所以我上面寫的你應(yīng)該明白了吧!

Vue如何實現(xiàn)彈窗Modal

這是$mount的一個源碼片段,其實$mount的方法支持傳入2個參數(shù)的,第一個是 el,它表示掛載的元素,可以是字符串,也可以是 DOM 對象,如果是字符串在瀏覽器環(huán)境下會調(diào)用 query 方法轉(zhuǎn)換成 DOM 對象的。第二個參數(shù)是和服務(wù)端渲染相關(guān),在瀏覽器環(huán)境下不需要傳第二個參數(shù)。

好了,我們現(xiàn)在其實就可以在組件中:

this.notifier[state](msg)來調(diào)用了,是不是很方便?

進(jìn)階

我們剛才實現(xiàn)了在Vue中通過方法來進(jìn)行用戶反饋的提醒,再增加一個難度:

我們vue項目中應(yīng)該也遇到過這種情況,彈出一個對話框或是選擇框?不但要求用方法彈出,并且能接收到對話框交互所返回的結(jié)果。

這里就不詳細(xì)的分析了直接上代碼說(之前的代碼,用render來寫的組件,懶得改了,直接拿來用...),先創(chuàng)建一個對話框組件---Confirm.vue

<script>
  let __this = null
  export default {
    name: 'Confirm',
    data() {
      return {
        config: {
          msg: '',
          ifBtn: '',
          top: null
        }
      }
    },
    created() {
      __this = this
    },
    methods: {
      createBox(h) {
        let config = {}
        config.attrs = {
          id: '__confirm'
        }
        let children = []
        children.push(this.createContainer(h))
        children.push(this.createBg(h))
        return h('div', config, children)
      },
      createBg(h) {
        return h('div', {
          class: 'bg',
          on: {
            click: __this.$cancel
          }
        })
      },
      createContainer(h) {
        let config = {}
        config.class = {
          'box-container': true
        }
        if (__this.config.top) {
          config.style = {
            'top': __this.config.top + 'px',
            'transform': 'translate(-50%, 0)'
          }
        }
        let children = []
        children.push(this.createContentBox(h))
        children.push(this.createClose(h))
        if (__this.config.ifBtn) {
          children.push(__this.createBtnBox(h))
        }
        return h('div', config, children)
      },
      createContentBox(h) {
        let config = {}
        config.class = {
          'content-box': true
        }
        return h('div', config, [__this.createContent(h)])
      },
      createContent(h) {
        let config = {}
        config.domProps = {
          innerHTML: __this.config.msg
        }
        return h('p', config)
      },
      createClose(h) {
        return h('i', {
          class: 'eqf-no pointer close-btn',
          on: {
            click: __this.$cancel
          }
        })
      },
      createBtnBox(h) {
        return h(
          'div', {
            class: {
              'btn-box': true
            }
          }, [
            __this.createBtn(h, 'btn-cancel middle mr10', '取消', __this.$cancel),
            __this.createBtn(h, 'btn-primary middle mr10', '確定', __this.$confirm)
          ])
      },
      createBtn(h, styles, content, callBack) {
        return h('button', {
          class: styles,
          on: {
            click: callBack
          }
        }, content)
      }
    },
    render(h) {
      return this.createBox(h)
    }
  }
  </script>
  
  <style scoped>
  #__confirm {
    position: fixed;
    top: 0;
    left: 0;
    z-index: 10;
    width: 100%;
    height: 100%;
  }
  #__confirm .bg {
    position: fixed;
    top: 0;
    left: 0;
    z-index: 0;
    width: 100%;
    height: 100%;
  }
  #__confirm .box-container {
    position: absolute;
    width: 500px;
    padding: 20px;
    padding-top: 30px;
    border-radius: 3px;
    background: #fff;
    z-index: 1;
    box-shadow: 2px 2px 10px rgba(0,0,0,0.4);
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
  }
  #__confirm .content-box {
    font-size: 14px;
    line-height: 20px;
    margin-bottom: 10px;
  }
  #__confirm .btn-box {
    margin-top: 20px;
    text-align: right;
  }
  #__confirm .close-btn {
    position: absolute;
    top: 15px;
    right: 20px;
    font-size: 16px;
    color: #666666;
  }
  #__confirm .close-btn:hover {
    color: #1593FF;
  }
    #__confirm .bg {
      position: fixed;
    }
  </style>

然后創(chuàng)建confirm.js

'use strict'
import Confirm from './Confirm.vue'
const confirmConstructor = Vue.extend(Confirm)

const ConfirmViewStyle = config => {
  const confirmInstance = new confirmConstructor({
    data() {
      return {
        config
      }
    }
  })
  confirmInstance.vm = confirmInstance.$mount()
  confirmInstance.dom = confirmInstance.vm.$el
  document.body.appendChild(confirmInstance.dom)
}

const close = () => {
  let dom = document.querySelector('body .modelServe-container')
  dom && dom.remove()
  Vue.prototype.$receive = null
}

const closeConfirm = () => {
  let dom = document.getElementById('__confirm')
  dom && dom.remove()
  Vue.prototype.$confirm = null
}

function install(Vue) {
  Vue.prototype.modelServe = {
    confirm: (obj) => {
      return new Promise(resolve => {
        Vue.prototype.$confirm = (data) => {
          resolve(data)
          closeConfirm()
        }
        ConfirmViewStyle(obj)
      })
    }
  }
  Vue.prototype.$dismiss = close
  Vue.prototype.$cancel = closeConfirm
}
Vue.use(install)
export default install

思路很簡單,在我們創(chuàng)建的時候同時返回一個promise,同時將resolve通行證暴露給vue的一個全局方法也就是將控制權(quán)暴露給外部,這樣我們就可以向這樣,我上面的confiram.vue是直接把取消綁定成了$cancel,把確定綁定成了$confirm,所以點擊確定會進(jìn)入full,也就是.then中,當(dāng)然你也可以傳參數(shù)

this.modelServe.confirm({
  msg: '返回后數(shù)據(jù)不會被保存,確認(rèn)?',
  ifBtn: true
}).then(_ => {
  this.goBack()
}).catch()

寫的有點多,其實還可以擴(kuò)展出好多技巧,比如模態(tài)框中傳一個完整的組件,并展示出來,簡單地寫一下,其實只需改動一點

import Model from './Model.vue'
const modelConstructor = Vue.extend(Model)
const modelViewStyle = (obj) => {
let component = obj.component
const modelViewInstance = new modelConstructor({
  data() {
    return {
      disabledClick: obj.stopClick // 是否禁止點擊遮罩層關(guān)閉
    }
  }
})
let app = document.getElementById('container')
modelViewInstance.vm = modelViewInstance.$mount()
modelViewInstance.dom = modelViewInstance.vm.$el
app.appendChild(modelViewInstance.dom)
new Vue({
  el: '#__model__',
  mixins: [component],
  data() {
    return {
      serveObj: obj.obj
    }
  }
})
}

...

Vue.prototype.modelServe = {
  open: (obj) => {
    return new Promise(resolve => {
      modelViewStyle(obj, resolve)
      Vue.prototype.$receive = (data) => {
        resolve(data)
        close()
      }
    })
  }
}

調(diào)用:

sendCallBack() {
  this.modelServe.open({
    component: AddCallback,
    stopClick: true
  }).then(data => 
    if (data === 1) {
      this.addInit()
    } else {
      this.goBack()
    }
  })

這里我們用了mixins,最后最后再簡單地介紹一下mixins,extend,extends的區(qū)別

**- Vue.extend使用基礎(chǔ) Vue 構(gòu)造器,創(chuàng)建一個“子類”。參數(shù)是一個包含組件選項的對象。

mixins 選項接受一個混入對象的數(shù)組。這些混入實例對象可以像正常的實例對象一樣包含選項,他們將在 Vue.extend() 里最終選擇使用相同的選項合并邏輯合并。舉例:如果你的混入包含一個鉤子而創(chuàng)建組件本身也有一個,兩個函數(shù)將被調(diào)用。Mixin 鉤子按照傳入順序依次調(diào)用,并在調(diào)用組件自身的鉤子之前被調(diào)用。

注意(data混入組件數(shù)據(jù)優(yōu)先鉤子函數(shù)將混合為一個數(shù)組,混入對象的鉤子將在組件自身鉤子之前調(diào)用,值為對象的選項,例如 methods, components 和 directives,將被混合為同一個對象。兩個對象鍵名沖突時,取組件對象的鍵值對。)

extends 允許聲明擴(kuò)展另一個組件(可以是一個簡單的選項對象或構(gòu)造函數(shù)),而無需使用 Vue.extend。這主要是為了便于擴(kuò)展單文件組件。這和 mixins 類似。**

概括

extend用于創(chuàng)建vue實例
mixins可以混入多個mixin,extends只能繼承一個
mixins類似于面向切面的編程(AOP),extends類似于面向?qū)ο蟮木幊?
優(yōu)先級Vue.extend>extends>mixins

感謝各位的閱讀!關(guān)于“Vue如何實現(xiàn)彈窗Modal”這篇文章就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,讓大家可以學(xué)到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!

網(wǎng)頁題目:Vue如何實現(xiàn)彈窗Modal
當(dāng)前鏈接:http://aaarwkj.com/article30/godiso.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站建設(shè)、網(wǎng)站設(shè)計、虛擬主機(jī)、用戶體驗、定制開發(fā)、品牌網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

成都網(wǎng)站建設(shè)
欧美日韩视频在线第一页| 日本顶级片一区二区三区| 亚洲精品视频久久免费 | 国产精品久久久天美传媒| 国产一区二区三区在线视频播放| 国产精品久久久久精品爆| 极品大胸美女被啪啪的高潮| 日本免费精品人成视频| 在线一区免费视频播放| 日本东京热加勒比视频| 蜜臀在线免费观看av| 无人码人妻一区二区三区免| 91日韩中文字幕在线观看| 成人激情电影免费在线| 美女在线观看av少妇| 日韩精品欧美成人高清一区二区| 欧美一区二区三区日韩精品| 91欧美精品在线视频| 欧美日韩黄色在线观看| 亚洲一区二区精品免费视频| 麻豆看片高清在线播放| 18禁视频免费无遮挡| 日韩av毛片在线观看| 国产精品传媒成人免费| 国产内射一级一片内射高清视频1 亚洲一区二区三区不卡伦理 | 日韩视频 一区 二区| av影片在线观看不卡| 中文字幕久久熟女蜜桃| 国语对白精品视频在线| 亚洲国产精品va在线香蕉| 国产精品大白屁股视频| 日韩欧美国产综合一区二区| 国产综合永久精品日韩鬼片| 免费观看国产裸体视频| 美腿丝袜清纯唯美亚洲另类| 综合激情网激情五月天| 丝袜啪啪啪麻豆白虎内射| 欧美精品一区二区网站| 一区二区三区熟妇人妻视频 | 久久久久精品激情三级| 午夜精品人妻一区二区|