首頁 web前端 js教程 如何使用v-model與promise兩種方式實作vue彈窗組件

如何使用v-model與promise兩種方式實作vue彈窗組件

May 28, 2018 pm 03:00 PM
promise v-model

這次為大家帶來如何使用v-model與promise兩種方式實現vue彈窗組件,使用v-model與promise兩種方式實現vue彈窗組件的注意事項有哪些,下面就是實戰案例,一起來看一下。

最近公司有一個後台業務雖然也是寫在了現有的後台系統中,但是之後要為這個業務單獨拉出來新建一個後台系統,所以現有的後台系統中的vue組件庫,就不能用了(因為不知道將來的系統要基於什麼組件庫,以防給未來移植項目帶來麻煩),這次業務中又遇到了彈窗的功能,所以只能手動寫一個了(雖然說彈跳窗組件很簡單,也是想自己總結一下,有不對的地方也請指出),一開始用傳統的props,$emit但是覺得要接兩個取消與確認的回調這塊的邏輯分散了所以就用了promise兩個回調的方式把兩個回調寫在了一起,並不一定好,算是提供一種思路吧。

一.概覽

先看最後的呼叫方式

props $emit方式

<chat-modal ref="chat-modal" v-model="showModal" cancelText="取消" sureText="确认" title="弹窗标题" small @on-ok="onOK" @on-cancel="onCancel">
  <p>slot的东西,想向弹窗中添加自定义的内容</p>
</chat-modal>
methods: {
  display() {
   this.showModal = true;//交互点击手动触发显示弹窗 
  },
  onOK() {},//点击确认的回调
  onCancel() {}//点击取消的回调
}
登入後複製

promise的回呼方式

<chat-modal ref="chat-modal"></chat-modal>
methods: {
  display() {
    this.$refs["chat-modal"].openModal({
      title: "弹窗标题",
      sureText: "确认",
      cancelText: "取消"
    }).then(res => {
      //点击确认的回调
    }, res => {
      //点击取消的回调
    })
  }
}
登入後複製

第二種方式的好處就是把所有的邏輯都集中到了一個方法裡。

二.看下元件的原始碼

tip:樣式有些爛...

<template>
  <p>
    <p class="shadow" v-show="showModal"></p>
    <p class="modal" :class="{&#39;smSize&#39;: otherText.small || small}" v-show="showModal">
      <p class="header">{{ otherText.title || title}}</p>
      <p class="body">
        <slot></slot>
      </p>
      <p class="footer">
        <p class="item success" id="sure" ref="sure" @click="makeSure" v-show="otherText.sureText || sureText">{{ otherText.sureText || sureText }}</p>
        <p class="item red" id="cancel" ref="cancel" @click="makeCancel" v-show="otherText.cancelText || cancelText">{{ otherText.cancelText || cancelText }}</p>
      </p>
    </p>
  </p>
</template>
<script>
//此组件提供两种调用方法,可以在组件上v-model一个表示是否显示弹窗的对话框,然后需要的一些值通过props传入,然后$emit在组件上@监听做回调
//第二中方法所有的传值回调都只需要在组件内部的一个方法调用然后在组件外部this.$refs[xxx].open调用然后.then触发回调,比上一种方便些
var initOtherText = {
  sureText: "",
  cancelText: "",
  title: "",
  small: false
};
export default {
  props: {
    title: {
      type: String
    },
    sureText: {
      type: String
    },
    cancelText: {
      type: String
    },
    value: {
      type: Boolean
    },
    small: {
      type: Boolean
    }
  },
  watch: {
    value(newVal) {
      this.showModal = newVal;
    }
  },
  data() {
    return {
      otherText: JSON.parse(JSON.stringify(initOtherText)),
      showModal: this.value
    };
  },
  methods: {
    makeSure() {
      this.$emit("on-ok");
      this.$emit("input", false);
    },
    makeCancel() {
      this.$emit("on-cancel");
      this.$emit("input", false);
    },
    openModal(otherText) {
      this.otherText = { ...otherText };
      this.showModal = true;
      var pms = new Promise((resolve, reject) => {
        this.$refs["sure"].addEventListener("click", () => {
          this.showModal = false;
          resolve("点击了确定");
        });
        this.$refs["cancel"].addEventListener("click", () => {
          this.showModal = false;
          reject("点击了取消");
        });
      });
      return pms;
    }
  }
};
</script>
<style lang="scss" scoped>
.shadow {
  background-color: rgba(0, 0, 0, 0.5);
  display: table;
  height: 100%;
  left: 0;
  position: fixed;
  top: 0;
  transition: opacity 0.3s ease;
  width: 100%;
  z-index: 50;
}
.modal {
  display: table-cell;
  vertical-align: middle;
  overflow-x: hidden;
  position: fixed;
  background-color: white;
  box-shadow: rgba(0, 0, 0, 0.33) 0px 2px 8px;
  border-radius: 5px;
  outline: 0px;
  overflow: hidden;
  transition: all 0.3s ease;
  width: 600px;
  height: 400px;
  top: 50%;
  left: 50%;
  margin-top: -200px;
  margin-left: -300px;
}
.header {
  align-items: center;
  background-color: #62a39e;
  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.16);
  color: #fff;
  font-weight: bold;
  display: -ms-flexbox;
  display: flex;
  height: 3.5rem;
  padding: 0 1.5rem;
  position: relative;
  z-index: 1;
}
.body {
  align-items: center;
  padding: 1.5rem;
}
.footer {
  justify-content: flex-end;
  padding: 1.5rem;
  position: absolute;
  bottom: 0;
  width: 100%;
  float: right;
}
.item {
  color: white;
  text-align: center;
  border-radius: 5px;
  padding: 10px;
  cursor: pointer;
  display: inline-block;
}
.info {
  background-color: #2196f3;
}
.success {
  background-color: #62a39e;
}
.red {
  background-color: #e95358;
}
.smSize {
  height: 200px;
}
</style>
登入後複製

先分析第一種方式: 呼叫者需要在元件外部v-model上綁定一個變數(例中為showModal)來指示彈窗是否顯示,顯示的時候需要在元件外部手動設定 this.showModal = true ,元件內部props定義一個屬性來接這個值為value: {type: Boolean} ,同時在元件內部在用聲明一個變數用來同步外部傳進來的props值預設值為showModal: this.value (內部聲明的值也叫了showModal),在watch中監聽進行同步 watch: { value(newVal) { this.showModal = newVal } } ;然後把組件內部的這個showModal值綁定在需要顯示或者隱藏的DOM元素上。向外拋出事件的時候是在點擊組件內部的確定與關閉按鈕時候

makeSure() {
      this.$emit("on-ok");
      this.$emit("input", false);
    },
makeCancel() {
      this.$emit("on-cancel");
      this.$emit("input", false);
    }
登入後複製

this.$emit("on-ok");this.$emit("on-cancel" ); 這兩句的是向外拋出事件在元件外部@接一下然後寫自己需要的回呼函數。這時就可以實現彈跳窗的顯示與隱藏了,你可能發現並沒有一句程式碼去設定this.showModal = false;彈跳窗就隱藏了。主要是因為這幾句程式碼 v-model = 'showModal' 和 元件內部的 props: {value: {type: Boolean}} this.$emit("input", false) 。 v-model其實是vue的語法糖, <chat-modal v-model="showModal"> 其實可以寫成<chat-modal :value="showModal" @input ="showModal = arguments[0]"> 所以要求我們在元件內部必須規定props的名字必須為value, 然後在元件內部觸發確定或取消的時候在元件內部觸發this.$emit ("input", false) 這樣實現了直接隱藏彈跳窗而不必打擾使用者讓使用者在元件外部在手動將showModal置為false.

然後來看promise的方式: 第一種方式傳進來的值都透過props來接的,這種方式透過在元件內部定義了另一個物件來接傳進來的值,

var initOtherText = {
  sureText: "",
  cancelText: "",
  title: "",
  small: false
};
otherText: JSON.parse(JSON.stringify(initOtherText)),
登入後複製

然後在menthods裡定義了一個名為openModal的方法,然後把傳進來的一系列參數賦值給組件內部的物件this.otherText = { ...otherText }; this.showModal = true; 並且將showModal置為true,然後每次觸發的時候新建一個promise對象,裡面的非同步事件為點擊確定和取消的兩個點擊事件,這裡要操作DOM了

this.$refs["sure"].addEventListener("click", () => {
  this.showModal = false;
  resolve("点击了确定");
});
登入後複製

取得確定按鈕的DOM元素綁定點擊事件,回調裡將showModal置為false並且resolve,

this.$refs["cancel"].addEventListener("click", () => {
  this.showModal = false;
  reject("点击了取消");
});
登入後複製

取得取消按鈕的DOM綁定點擊事件,回調裡reject.

遇到的坑

#這之前遇到了一個坑,因為第一次已經綁定了點擊事件,第二次resolve和reject就會失敗,本想取消一下綁定事件,但是因為將整個彈窗v- show="showModal"的原因整個DOM被display:none;了就不需要手動解綁了。第二個是關於用v-if還是v-show來隱藏彈跳窗,一開始用的是v-if但是發現在這步時

this.showModal = true;
var pms = new Promise((resolve, reject) => {
  this.$refs["sure"].addEventListener.xxx//省略
});
return pms;
登入後複製

将showModal置为true时然后就去绑定事件这时候还没有DOM还没有解析玩DOM树上还没有,要不就得用this.$nextTick增加了复杂度,最后采用了v-show;

关于优先级问题

如果既在组件上用prop传了值(title,sureText之类的)如 <chat-modal" title="xx" sureText="xxx"></chat-modal> 也在方法里传了

this.$refs["chat-modal"].openModal({
  title: "服务小结",
  sureText: "提交并结束",
  cancelText: "取消"
  }).then();
登入後複製

相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

推荐阅读:

如何使用Vue内父子组件通讯todolist组件

如何使用Vue整合AdminLTE模板

以上是如何使用v-model與promise兩種方式實作vue彈窗組件的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.聊天命令以及如何使用它們
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

Vue中如何使用v-model.number實現輸入框的資料類型轉換 Vue中如何使用v-model.number實現輸入框的資料類型轉換 Jun 11, 2023 am 08:54 AM

在Vue中,v-model是用來實現雙向綁定的一個重要指令,它可以讓我們很方便地將使用者輸入的內容同步到Vue的data屬性中。但是在某些情況下,我們需要對資料進行轉換,例如將使用者輸入的字串類型轉換成數字類型,這時候就需要使用v-model的.number修飾符來實現。 v-model.number的基本用法v-model.number是v-model的一個修

言出必行:兌現承諾的好處和壞處 言出必行:兌現承諾的好處和壞處 Feb 18, 2024 pm 08:06 PM

在日常生活中,我們常常會遇到承諾與兌現之間的問題。無論是在個人關係中,或是在商業交易中,承諾的兌現都是建立信任的關鍵。然而,承諾的利與弊也常常會引起爭議。本文將探討承諾的利與弊,並給予一些建議,如何做到言出必行。承諾的利是顯而易見的。首先,承諾可以建立信任。當一個人信守承諾時,他會讓別人相信自己是個可信賴的人。信任是人與人之間建立的紐帶,它可以讓人們更加

在Vue應用中遇到Uncaught (in promise) TypeError怎麼辦? 在Vue應用中遇到Uncaught (in promise) TypeError怎麼辦? Jun 25, 2023 pm 06:39 PM

Vue是一款受歡迎的前端框架,在開發應用時經常會遇到各種各樣的錯誤和問題。其中,Uncaught(inpromise)TypeError是常見的一種錯誤型別。在本篇文章中,我們將探討它的產生原因和解決方法。什麼是Uncaught(inpromise)TypeError? Uncaught(inpromise)TypeError錯誤通常出現在

深入了解Promise.resolve() 深入了解Promise.resolve() Feb 18, 2024 pm 07:13 PM

Promise.resolve()詳解,需要具體程式碼範例Promise是JavaScript中一種用來處理非同步操作的機制。在實際開發中,常常需要處理一些需要依序執行的非同步任務,而Promise.resolve()方法就是用來傳回一個已經Fulfilled狀態的Promise物件。 Promise.resolve()是Promise類別的靜態方法,它接受一個

Vue報錯:無法正確使用v-model進行雙向資料綁定,如何解決? Vue報錯:無法正確使用v-model進行雙向資料綁定,如何解決? Aug 19, 2023 pm 08:46 PM

Vue報錯:無法正確使用v-model進行雙向資料綁定,如何解決?引言:在使用Vue進行開發時,雙向資料綁定是一項非常常見且強大的功能。然而,有時候我們可能會遇到一個問題,就是當我們嘗試使用v-model進行雙向資料綁定時,卻遭遇到了報錯。本文將介紹該問題的原因以及解決方案,並透過程式碼範例來示範如何解決該問題。問題描述:當我們在Vue中嘗試使用v-model

Vue中使用v-model的雙向綁定最佳化應用的資料效能 Vue中使用v-model的雙向綁定最佳化應用的資料效能 Jul 17, 2023 pm 07:57 PM

Vue中使用v-model的雙向綁定最佳化應用的資料效能在Vue中,我們經常使用v-model指令來實現表單元素與資料之間的雙向綁定。這種雙向綁定的方式極大地簡化了開發過程,並提高了使用者體驗。然而,由於v-model需要監聽表單元素的input事件,當資料量較大時,這種雙向綁定可能會帶來一定的效能問題。本文將介紹如何最佳化使用v-model時的資料效能,並提供一

解決Vue報錯:無法使用v-model進行雙向資料綁定 解決Vue報錯:無法使用v-model進行雙向資料綁定 Aug 25, 2023 pm 04:49 PM

解決Vue報錯:無法使用v-model進行雙向資料綁定在使用Vue進行開發時,經常會使用v-model指令來實現雙向資料綁定,但有時候我們會遇到一個問題,就是在使用v- model時會報錯,無法正確進行雙向資料綁定。這可能是由於一些常見的錯誤導致的,以下我將介紹幾種常見的情況以及相應的解決方法。組件的props屬性未正確設定當我們在使用組件時,如果需要通過v-

實例解析ES6 Promise的原理與使用 實例解析ES6 Promise的原理與使用 Aug 09, 2022 pm 03:49 PM

利用Promise對象,把普通函數改成返回Promise的形式,解決回調地獄的問題。明白Promise的成功失敗呼叫邏輯,可以靈活的進行調整。理解核心知識,先用起來,慢慢整合吸收知識。

See all articles