亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Vue實(shí)現(xiàn)輸入框回車(chē)發(fā)送和粘貼文本與圖片功能

 更新時(shí)間:2022年05月06日 10:50:22   作者:諸葛小愚  
這篇文章主要為大家詳細(xì)介紹了Vue如何實(shí)現(xiàn)聊天輸入框回車(chē)發(fā)送、粘貼文本(包括HTML)、粘貼圖片等功能,文中的實(shí)現(xiàn)方法講解詳細(xì),需要的可以參考一下

上一篇中,我們初步新建了一個(gè)可“雙向綁定”的聊天輸入框,結(jié)合實(shí)際使用的場(chǎng)景,如果僅僅只是實(shí)現(xiàn)了“雙向綁定”還不夠,還必須處理粘貼文字、圖片等功能。本文就在此基礎(chǔ)上,繼續(xù)探討如何實(shí)現(xiàn)回車(chē)發(fā)送、粘貼文本(包括HTML)、粘貼圖片等功能。話不多說(shuō),咱們開(kāi)整。contenteditable的元素如何實(shí)現(xiàn)“雙向綁定”?

實(shí)現(xiàn)回車(chē)發(fā)送

在一個(gè)可編輯元素中,默認(rèn)回車(chē)就是換行。但是如果我們要實(shí)現(xiàn)回車(chē)是“發(fā)送”的功能,需要怎么處理呢?

思路:監(jiān)聽(tīng)鍵盤(pán)事件,如果判斷用戶(hù)按下的是回車(chē)鍵,則執(zhí)行發(fā)送邏輯,并阻止瀏覽器的默認(rèn)行為。

實(shí)現(xiàn)起來(lái)也可以有兩種方式:

event

<div class="input-box" contenteditable @keydown="handleKeydown"></div>
...
handleKeydown(event) {
    if (event.shiftKey && event.keyCode === 13) {
        document.execCommand('insertLineBreak'); // 換行
    } else if (event.keyCode === 13) { // 回車(chē)鍵
        console.log("回車(chē)發(fā)送");
        event.preventDefault();
        return false;
    }
}

這樣就可以實(shí)現(xiàn)回車(chē)發(fā)送。但是這種方式是有問(wèn)題的,具體如下:

  • 如果持續(xù)按下回車(chē)鍵,將會(huì)一直觸發(fā)
  • 其他鍵 + 回車(chē)鍵也會(huì)觸發(fā)此判斷
  • 需要額外增加邏輯,否則輸入框?qū)⒉豢蓳Q行

那有沒(méi)有什么辦法是可以解決的呢,對(duì)于Vue項(xiàng)目來(lái)說(shuō),可以借助按鍵修飾符

按鍵修飾符

<div class="input-box" contenteditable @keyup.enter.exact="submit" @keydown.enter.exact="handleKeydown"></div>
...
},
submit() {
    console.log('回車(chē)發(fā)送');
},
handleKeydown(event) {
    event.preventDefault();
    return false;
},

按鍵修飾符的具體文檔可參考官網(wǎng):事件處理 — Vue.js (vuejs.org),本處只重點(diǎn)說(shuō)明.extra修飾符。.extra可以精確控制按鍵組合,結(jié)合keyupkeydown,上述代碼翻譯過(guò)來(lái)就是:只有一個(gè)回車(chē)鍵時(shí),并且回彈起來(lái)才會(huì)觸發(fā)“回車(chē)發(fā)送”;如果只有一個(gè)回車(chē)鍵,并且按下,則阻止瀏覽器默認(rèn)事件。這樣就可以實(shí)現(xiàn)“回車(chē)發(fā)送”。也許有人會(huì)問(wèn),換行怎么辦。答案就是使用shift + enter,這也是默認(rèn)的換行。如果不喜歡shift+enter就需要自己處理?yè)Q行了。

優(yōu)點(diǎn)

  • 使用方式簡(jiǎn)單
  • 可使用默認(rèn)的方式換行

粘貼文本

粘貼文本不是直接使用ctrl + v嘛,這都不知道?話是這么說(shuō),但是如果我們相對(duì)粘貼的文本做些處理,直接使用ctrl + v就不合適了,而且后面還會(huì)用來(lái)粘貼圖片。想要直接粘貼圖片并顯示,還沒(méi)有原生輸入框可做到吧。本處需要使用paste事件,也就是專(zhuān)門(mén)處理粘貼的。由于我們是要手動(dòng)插入數(shù)據(jù),因此需要阻止默認(rèn)操作,需要借助prevent事件修飾符。

paste.prevent

<div class="input-box" contenteditable @paste.prevent="onPaste"></div>
...
import onPaste from '@/utils/onPaste.js'; // 引入專(zhuān)門(mén)處理粘貼的方法
...
// 注意是異步處理
async onPaste(event) {
    const result = await onPaste(event); // 傳入粘貼事件
    console.log('處理后的數(shù)據(jù)', result);
    // 插入文本
    document.execCommand('insertText', false, result.data);
}

重點(diǎn)來(lái)了

新建onPaste.js,用來(lái)處理文本和圖片的粘貼

// onPaste.js
// 定義粘貼函數(shù)
const onPaste = (event) => {
  // 剪貼板沒(méi)數(shù)據(jù),則直接返回
  if (!event.clipboardData || !event.clipboardData.items) {
    return;
  }
  // 封裝Promise
  return new Promise((resovle, reject) => {
    // 遍歷剪貼板
    for(let i = 0, len = event.clipboardData.items.length; i < len; i++) {
      const item = event.clipboardData.items[i];
      if (item.kind === 'string') {
        // 方式一,直接返回粘貼的文本數(shù)據(jù)
        // let str = event.clipboardData.getData('text');
        // resovle({
        //   data: str
        // });
        // 方式二,過(guò)濾掉粘貼的文本中存在的html標(biāo)簽和換行等字符
        let reg = /</?.+?/?>/g; // 匹配粘貼文本中的html標(biāo)簽
        // 處理字符串類(lèi)型,參數(shù)為回調(diào)函數(shù)
        item.getAsString(str => {
          resovle({
            data: str.replace(reg, '').replace(/(\r\n)|(\n)/g, '') // 去掉換行符
          })
        })
      } else {
        reject(new Error('不支持粘貼該類(lèi)型'));
      }
    }
  })
}
export default onPaste; // 默認(rèn)導(dǎo)出方法

關(guān)于剪貼板,由幾個(gè)概念需要提前了解:clipboardDataDataTransfer、DataTransferItem,具體可參考clipboardData。運(yùn)行結(jié)果如下:

注:本次復(fù)制的是<div data-v-66ea8951="">父組件修改子組件的值</div>

粘貼圖片

粘貼圖片和粘貼問(wèn)題有相同之處,也有所不同。最大的不同是顯示圖片,需要獲取圖片的src。在寫(xiě)代碼前先想幾個(gè)問(wèn)題:

  • 圖片展示需要提供src,那么如何獲取src
  • 圖片可大可小,如何限制圖片的尺寸,避免超出輸入框范圍
  • 圖片像素很高,是否需要壓縮

有了這些問(wèn)題,就需要一一解決。

  • 圖片的壓縮,采用canvas繪制指定尺寸的圖片
  • base64就由canvas的toDataURL方法獲得
  • 壓縮時(shí),維持圖片的寬高比

話不多說(shuō),先看代碼:

// DivEditable.vue
async onPaste(event) {
      const result = await onPaste(event);
      console.log('處理后的粘貼數(shù)據(jù)', result);
      const imgRegx = /^data:image/png|jpg|jpeg|gif|svg|bmp|tif/; // 支持的圖片格式
      if (imgRegx.test(result.compressedDataUrl)) {
        // document.execCommand('insertImage', false, result.compressedDataUrl);
        const sel = window.getSelection(); // 獲取當(dāng)前光標(biāo)位置
        if (sel && sel.rangeCount === 1 && sel.isCollapsed) {
          const range = sel.getRangeAt(0);
          const img = new Image();
          img.src = result.compressedDataUrl; // 使用壓縮后的圖片
          range.insertNode(img);
          range.collapse(false);
          sel.removeAllRanges();
          sel.addRange(range);
        }
      }
}
// onPaste.js
// 定義粘貼函數(shù)
const onPaste = (event) => {
  ...
  return new Promise((resovle, reject) => {
    for(let i = 0, len = event.clipboardData.items.length; i < len; i++) {
      const item = event.clipboardData.items[i];
      if (item.kind === 'file') {
        const file = item.getAsFile();
        if (item.type.match('^image/')) {
          // 處理圖片
          handleImage(file, (data) => {
            resovle(data)
          })
        } else {
          // 其他文件直接返回
          resovle({
            data: file,
            type: 'file'
          })
        }
      } else {
        reject(new Error('不支持粘貼該類(lèi)型'));
      }
    }
  })
}
function handleImage(file, callback, maxWidth = 200) {
  console.log('粘貼的圖片', file);
  if (!file || !//(?:png|jpg|jpeg|gif)/i.test(file.type)) {
    console.log('圖片格式不支持');
    return;
  }
  const reader = new FileReader();
  reader.onload = function () {
    const result = this.result;
    console.log('compressedDataUrl', result);
    let img = new Image();
    img.onload = function() {
      let compressedDataUrl = compress(img, file.type, maxWidth, true);
      let url = compress(img, file.type, maxWidth, false);
      img = null;
      callback({
        data: file,
        compressedDataUrl,
        url,
        type: 'image'
      })
    }
    img.src = result;
  };
  reader.readAsDataURL(file);
}
function compress(img, type, maxWidth, flag) {
  let canvas = document.createElement('canvas');
  let ctx2 = canvas.getContext('2d');
?
  let ratio = img.width / img.height;
  let width = img.width, height = img.height;
  // 根據(jù)flag判斷是否壓縮圖片
  if (flag) {
    // 壓縮后的圖片展示在輸入框
    width  = maxWidth;
    height = maxWidth / ratio; // 維持圖片寬高比
  }
  canvas.width = width;
  canvas.height = height;
?
  ctx2.fillStyle = '#fff';
  ctx2.fillRect(0, 0, canvas.width, canvas.height);
  ctx2.drawImage(img, 0, 0, width, height);
?
  let base64Data = canvas.toDataURL(type, 0.75);
?
  if (type === 'image/gif') {
    let regx = /(?<=data:image).*?(?=;base64)/; // 正則表示時(shí)在用于replace時(shí),根據(jù)瀏覽器的不同,有的需要為字符串
    base64Data = base64Data.replace(regx, '/gif');
  }
  canvas = null;
  ctx2 = null;
  return base64Data;
}
export default onPaste;

代碼實(shí)現(xiàn)效果圖:

插入圖片可使用insertImage命令插入,也可以使用Selection來(lái)插入。效果都差不多

壓縮圖片,其實(shí)也就是用canvas根據(jù)尺寸比例,重新繪制一張圖片,并獲取圖片的base64

返回?cái)?shù)據(jù)時(shí),需要返回壓縮后和原圖。

如果必須要壓縮圖片,則在handleImage方法中,直接使用FileReader加載圖片后,將base64編碼返回即可。

總結(jié)

本文實(shí)現(xiàn)了回車(chē)發(fā)送、粘貼文本、粘貼圖片的功能

涉及事件修飾符、按鍵修飾符、剪貼板、canvas等知識(shí)

項(xiàng)目地址

以上就是Vue實(shí)現(xiàn)輸入框回車(chē)發(fā)送和粘貼文本與圖片功能的詳細(xì)內(nèi)容,更多關(guān)于Vue輸入框粘貼文本圖片的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • vue props default Array或是Object的正確寫(xiě)法說(shuō)明

    vue props default Array或是Object的正確寫(xiě)法說(shuō)明

    這篇文章主要介紹了vue props default Array或是Object的正確寫(xiě)法說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-07-07
  • vue?懶加載組件chunk相對(duì)路徑混亂問(wèn)題及解決

    vue?懶加載組件chunk相對(duì)路徑混亂問(wèn)題及解決

    這篇文章主要介紹了vue?懶加載組件chunk相對(duì)路徑混亂問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-04-04
  • vue 設(shè)置proxyTable參數(shù)進(jìn)行代理跨域

    vue 設(shè)置proxyTable參數(shù)進(jìn)行代理跨域

    這篇文章主要介紹了vue 設(shè)置proxyTable參數(shù)進(jìn)行代理跨域的相關(guān)資料,及代理跨域的概念原理,需要的朋友可以參考下
    2018-04-04
  • Vue2實(shí)現(xiàn)全局水印效果的示例代碼

    Vue2實(shí)現(xiàn)全局水印效果的示例代碼

    這篇文章主要為大家學(xué)習(xí)介紹了如何利用Vue2實(shí)現(xiàn)全局水印的效果,文中的示例代碼簡(jiǎn)潔易懂,具有一定的借鑒價(jià)值,感興趣的小伙伴可以了解下
    2023-07-07
  • vue?element-plus中el-input修改邊框border的方法

    vue?element-plus中el-input修改邊框border的方法

    element樣式還是蠻好的,只是有時(shí)候我們需要做一些調(diào)整,比如el-input的邊框,下面這篇文章主要給大家介紹了關(guān)于vue?element-plus中el-input修改邊框border的相關(guān)資料,需要的朋友可以參考下
    2022-09-09
  • 如何正確理解vue中的key詳解

    如何正確理解vue中的key詳解

    這篇文章主要給大家介紹了關(guān)于如何正確理解vue中key的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者使用vue具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-11-11
  • vue 使用高德地圖vue-amap組件過(guò)程解析

    vue 使用高德地圖vue-amap組件過(guò)程解析

    這篇文章主要介紹了vue 使用高德地圖vue-amap組件過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-09-09
  • 使用vscode 開(kāi)發(fā)uniapp的方法

    使用vscode 開(kāi)發(fā)uniapp的方法

    本文給大家分享我使用vscode開(kāi)發(fā)的一些配置。其中包括uniapp組件語(yǔ)法提示,uniapp代碼提示,代碼自動(dòng)格式化問(wèn)題,對(duì)vscode 開(kāi)發(fā)uniapp的相關(guān)知識(shí)感興趣的朋友一起看看吧
    2021-08-08
  • 詳解Vue文檔中幾個(gè)易忽視部分的剖析

    詳解Vue文檔中幾個(gè)易忽視部分的剖析

    針對(duì)Vue文檔中部分大家可能不會(huì)去研讀的內(nèi)容,這篇文章主要介紹了詳解Vue文檔中幾個(gè)易忽視部分的剖析,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2018-03-03
  • 關(guān)于vue v-for 循環(huán)問(wèn)題(一行顯示四個(gè),每一行的最右邊那個(gè)計(jì)算屬性)

    關(guān)于vue v-for 循環(huán)問(wèn)題(一行顯示四個(gè),每一行的最右邊那個(gè)計(jì)算屬性)

    這篇文章主要介紹了關(guān)于vue v-for 循環(huán)問(wèn)題(一行顯示四個(gè),每一行的最右邊那個(gè)計(jì)算屬性),需要的朋友可以參考下
    2018-09-09

最新評(píng)論