国产成人精品18p,天天干成人网,无码专区狠狠躁天天躁,美女脱精光隐私扒开免费观看

Vue3實(shí)現Message消息組件示例

發(fā)布時(shí)間:2021-08-17 12:16 來(lái)源: 閱讀:0 作者:itsSam 欄目: JavaScript 歡迎投稿:712375056

目錄

    在大多數 web 產(chǎn)品中,全局的 Message 組件占有較大的使用場(chǎng)景,它常出現在給與用戶(hù)反饋、信息提示和與系統的對話(huà)場(chǎng)景中。如果使用傳統的組件寫(xiě)法,則需要引入組件并在 components 中注冊,然后再去模板中以標簽的形式調用,傳入自定義 props 屬性并通過(guò) emit 觸發(fā)事件,這類(lèi)的組件往往有以下缺點(diǎn):

    • 需要頻繁引入并注冊
    • 需要在模板中以標簽的形式使用組件
    • 需要額外的參數控制組件的屬性和狀態(tài)
    • 不能友好的自定義組件的掛載位置,會(huì )被其他組件影響

    因此對于 Message 這類(lèi)的組件,我們希望可以在 JavaScript 中調用,可以傳入自定義參數控制組件狀態(tài),并且無(wú)需在調用的時(shí)候手動(dòng)掛載組件到 body 尾部。如果你使用過(guò)主流第三方庫,例如 ElementUI plus 或 Ant Design for Vue, 那么你肯定熟悉他們的消息組件 API,接下來(lái)就一起用 Vue3 實(shí)現一個(gè)全局的 Message 組件吧。

    組件最終實(shí)現效果

    組件設計

    定義最終的組件 API

    實(shí)現一個(gè)簡(jiǎn)易的 Message 消息組件,包含類(lèi)型 API 有文本(text)、成功(success)、失?。╡rror),即支持直接傳入一段文本,也支持通過(guò)組件具體的 option 配置,來(lái)自定義消息內容、關(guān)閉延遲、以及是否展示關(guān)閉按鈕等功能。

    // Message 類(lèi)型(type):文本、成功、失敗
    ["text", "success", "error"]
    
    // Message 選項(option)
    [String]: 消息內容
    [Object]: 消息配置
    
    // option 配置
    text [String] "" 消息內容
    duration [Number] 0 自動(dòng)關(guān)閉延遲毫秒數,0為不自動(dòng)關(guān)閉
    close [Boolean] false 是否展示關(guān)閉按鈕
    
    // 調用方式
    Message[type](option);
    
    

    調用示例

    Message.text("這是一條消息提示");
    Message.error({
        text: "網(wǎng)絡(luò )錯誤,請稍后再試",
        duration: 3000,
        close: true
    });
    

    定義組件結構

    建立 Message 文件夾存儲組件的整體結構,其中 src 中包含組件的模板、樣式和實(shí)例文件,同級下,建立 index.js 將整個(gè)組件暴露出去,以便在項目和業(yè)務(wù)組件中引入。

    |--- Message
     |--- src
     | |--- Message.vue // 組件模板
     | |--- Message.less // 提供組件樣式支持
     | |--- Message.js // 讀取配置并渲染組件實(shí)例
     | |--- Instance.js // 組件實(shí)例
     |---index.js // 暴露組件
    

    模板和樣式

    模板 Template

    模板相對來(lái)說(shuō)比較簡(jiǎn)單,外層由動(dòng)畫(huà)組件包裹,通過(guò) v-show 去控制消息顯示和關(guān)閉,內容部分包括圖標、消息文本、以及可配置的手動(dòng)關(guān)閉按鈕。

    <template>
      <!-- 消息列表 -->
      <transition name="slide-fade">
        <div class="message-container" v-show="visibled">
          <!-- 內容 -->
          <div class="message-content">
    
            <!-- 消息類(lèi)型圖標,通過(guò)消息類(lèi)型確定,text類(lèi)型不配置圖標 -->
            <div class="message-icon" v-if="config.icon">
              <i :class="config.icon"></i>
            </div>
    
      <!-- 消息文本 -->
            <span v-text="config.content"></span>
    
            <!-- 手動(dòng)關(guān)閉消息 -->
            <div class="option" v-if="!config.close">
              <i class="ri-close-fill" @click="onClose"></i>
            </div>
    
          </div>
        </div>
      </transition>
    </template>
    
    

    消息圖標

    需要注意的是,圖標是由調用 API 中的類(lèi)型確定,在創(chuàng )建實(shí)例的時(shí)候確定圖標類(lèi)型,這里引用的是開(kāi)源圖標庫 Remix Icon,具體的引用方法這里不多贅述,地址:

    樣式

    在 Message.less 中定義樣式和動(dòng)畫(huà)。

    @radius: 4px;
    @normalHeight: 34px;
    
    .message {
      position: fixed;
      top: 0;
      left: 0;
      width: 100%;
      text-align: center;
      box-sizing: border-box;
      z-index: 9999;
      transform: translateZ(9999px);
      padding-top: 28px;
      transition: top .4s ease;
    
      .message-container {
        margin-bottom: 14px;
    
        .message-icon {
          display: inline-block;
    
          i {
            font-size: 18px;
            font-weight: 400;
            margin-top: -3px;
            margin-right: 6px;
            display: inline-block;
            box-sizing: border-box;
            vertical-align: middle;
          }
    
          .ri-checkbox-circle-fill {
            color: #58c05b;
          }
    
          .ri-close-circle-fill {
            color: #fd4f4d;
          }
    
        .message-content {
          display: inline-block;
          padding: 4px 18px;
          height: @normalHeight;
          text-align: left;
          line-height: @normalHeight;
          font-size: 14px;
          font-weight: 400;
          border-radius: @radius;
          color: #595959;
          box-shadow: 0 4px 12px rgba(0, 0, 0, .15);
          background: #ffffff;
    
          .option {
            display: inline-block;
            pointer-events: all;
            margin-left: 18px;
    
            i {
              font-size: 18px;
              font-weight: 400;
              margin-top: -3px;
              display: inline-block;
              box-sizing: border-box;
              vertical-align: middle;
              cursor: pointer;
              color: #d9d9d9;
              transition: color 0.2s ease;
    
              &:hover {
                color: #ff7c75;
                transition: color 0.2s ease;
              }
            }
          }
        }
      }
    
      .slide-fade-enter-active {
        transition: all .2s ease-out;
      }
    
      .slide-fade-leave-active {
        transition: all .2s ease;
      }
    
      .slide-fade-enter-from,
      .slide-fade-leave-to {
        transform: translateY(-20px);
        opacity: 0;
      }
    }

    組件腳本

    組件中通過(guò)獲取傳入的config配置和remove實(shí)現渲染和取消掛載,通過(guò)onOpen和onClose方法控制消息打開(kāi)和手動(dòng)關(guān)閉,具體代碼如下:

    <script>
    import { reactive, toRefs } from "vue";
    export default {
      props: {
        config: { type: Object, default: () => {} }, // 消息配置項
        remove: { type: Function, default: () => {} }, // 取消掛載回調
      },
      setup(props) {
        const state = reactive({
          visibled: false,
        })
    
        // 打開(kāi)消息
        const onOpen = (config) => {
          setTimeout(() => {
            state.visibled = true;
          }, 10)
    
          // 指定時(shí)間后移除消息
          if (config.duration !== 0) {
            setTimeout(() => {
              onClose();
            }, config.duration);
          }
        }
    
        onOpen(props.config)
    
        // 消息關(guān)閉
        const onClose = () => {
          state.visibled = false;
          setTimeout(() => {
            props.remove()
          }, 200)
        };
    
        return {
          ...toRefs(state),
          onOpen,
          onClose,
        };
      },
    };
    </script>
    
    

    創(chuàng )建組件實(shí)例

    接下來(lái)將在 Instance.js 中編寫(xiě)組件調用時(shí)創(chuàng )建、掛載、銷(xiāo)毀組件等 API,頭部引入 Vue 的創(chuàng )建實(shí)例方法和上面寫(xiě)好的組件模板:

    import { createApp } from 'vue'
    import Message from './Message.vue'
    

    聲明實(shí)例操作方法,接受一個(gè)消息配置參數cfg

    /**
     * Message 實(shí)例操作
     * @param {Object} cfg 實(shí)例配置
     */
    const createInstance = cfg => {
     const config = cfg || {}
     // 1、創(chuàng  )建包裹容器,并設置外層的 Class 屬性、消息計數
    
     // 2、創(chuàng  )建實(shí)例并掛載到 body
     
     // 3、實(shí)現取消掛載方法,和取消掛載后重新計數
    }
    export default createInstance
    
    

    1、創(chuàng )建包裹容器,并設置外層的 Class 屬性

    創(chuàng )建一個(gè) DIV 作為外層容器包裹組件,并設置對應 class 屬性

    let messageNode = document.createElement('div')
    let attr = document.createAttribute("class")
    attr.value = "message"
    messageNode.setAttributeNode(attr)
    

    消息計數,我們定義一個(gè)消息彈框的高度為 54 px,在多個(gè)消息排隊打開(kāi)的時(shí)候,通過(guò)設置 top 值使各組件錯開(kāi)。

    const height = 54 // 單個(gè)消息框高度
    
    const messageList = document.getElementsByClassName('message')
    messageNode.style.top = `${messageList.length * height}px`
    
    

    2、創(chuàng )建實(shí)例并掛載到 body

    const app = createApp(Message, {
      config,
      remove() {
        handleRemove()// 移除元素,消息關(guān)閉后從 Dom 上取消掛載并移除
      }
    })
    
    // 掛載實(shí)例并追加到 body 結尾
    app.vm = app.mount(messageNode)
    document.body.appendChild(messageNode)
    
    app.close = () => {
      handleRemove()
    }
    
    return app
    
    

    3、其中定義取消掛載和重新設置 top 值的方法

    const handleRemove = ()=>{
      app.unmount(messageNode)
      document.body.removeChild(messageNode)
      resetMsgTop()
     }
    
    const resetMsgTop = () => {
      for (let i = 0; i < messageList.length; i++) {
        messageList[i].style.top = `${i * height}px`
      }
    }
    
    

    實(shí)現渲染實(shí)例 API

    通過(guò) Message.js 去讀取配置并渲染。

    import createInstance from './Instance.js'
    
    /**
     * 讀取配置并渲染 Message
     * @param {Object} typeCfg 類(lèi)型配置
     * @param {Object/String} cfg 自定義配置
     */
    function renderMsg(typeCfg = {}, cfg = '') {
      // 允許直接傳入消息內容,因此要判斷傳入的 cfg 類(lèi)型
      const isContent = typeof cfg === 'string'
    
      // 整合自定義配置
      cfg = isContent ? {
        content: cfg
      } : cfg
    
      const config = Object.assign({}, typeCfg, cfg) // 合并配置
    
      const {
        type = 'text', // 消息類(lèi)型
        content = '', // 消息內容
        duration = 3000, // 自動(dòng)關(guān)閉延遲時(shí)間
        close = false // 是否顯示關(guān)閉按鈕
      } = config
    
      // 創(chuàng  )建實(shí)例
      return createInstance({
        type,
        content,
        duration,
        close
      })
    }
    
    

    暴露text、success、error等 API。

    export default {
      // 純文本消息
      text(cfg = "") {
        const textCfg = {
          type: "text",
          icon: ''
        }
    
        return renderMsg(textCfg, cfg);
      },
      // 成功提示
      success(cfg = "") {
        const successCfg = {
          type: "success",
          icon: 'ri-checkbox-circle-fill'
        }
    
        return renderMsg(successCfg, cfg);
      },
      // 錯誤提示
      error(cfg = "") {
        const errorCfg = {
          type: "error",
          icon: 'ri-close-circle-fill'
        }
    
        return renderMsg(errorCfg, cfg);
      },
    }
    
    

    最后,在最外層的index.js中開(kāi)放這個(gè)組件以供調用。

    import Message from './src/Message.js';
    
    export default Message;

    到此這篇關(guān)于 Vue3實(shí)現Message消息組件示例的文章就介紹到這了,更多相關(guān)Vue3 Message消息組件內容請搜索腳本之家以前的文章或繼續瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家! 

    免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自本網(wǎng)站內容采集于網(wǎng)絡(luò )互聯(lián)網(wǎng)轉載等其它媒體和分享為主,內容觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如侵犯了原作者的版權,請告知一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容,聯(lián)系我們QQ:712375056,同時(shí)歡迎投稿傳遞力量。

    亚洲中文字幕久久精品无码VA| 熟女少妇内射日韩亚洲| 日产精品久久久久久久性色| 狠狠色噜噜狠狠狠狠色综合久AV| 国产女人的高潮大叫毛片| 天天做天天爱夜夜爽毛片|