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

微信小程序純文本實(shí)現(xiàn)@功能

 更新時(shí)間:2020年04月08日 15:57:42   作者:Macoo  
這篇文章主要介紹了ZZ需求小程序純文本實(shí)現(xiàn)@功能,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

前言

大家肯定對(duì)@功能不陌生,在如今的各大社交軟件中它是一種不可或缺的功能。實(shí)現(xiàn)@人的功能并不復(fù)雜,只需將@人員的id傳給后端,后端下發(fā)通知即可。主要的復(fù)雜點(diǎn)在于一鍵刪除功能與變色功能,web端可以使用現(xiàn)成庫(kù) caret.js 或者 At.js 來(lái)實(shí)現(xiàn)。但筆者需要在小程序中實(shí)現(xiàn)這個(gè)功能,而且在 textarea 標(biāo)簽里實(shí)現(xiàn),當(dāng)然@人名的變色功能自然而然就砍掉了。

準(zhǔn)備工作

怎么來(lái)實(shí)現(xiàn)一鍵刪除呢?首先想到對(duì)@人名前后用特殊符號(hào)標(biāo)記+正則來(lái)實(shí)現(xiàn),但結(jié)果不是很理想,擴(kuò)展性也比較差,如果還要匹配話題之類的就得多寫(xiě)一套代碼,所以就試著找其他方法解決。發(fā)現(xiàn) wx.getSelectedTextRange 可以獲取文本框聚焦時(shí)的光標(biāo),這樣就可以將@人員插入文本指定位置。文本框事件 @input 的可以獲取到變化的數(shù)據(jù)與位置,那就可以根據(jù)變化的位置與變化的數(shù)據(jù)來(lái)判斷是否命中@人員,@人員的位置可以通過(guò)計(jì)算獲取。

// bindinput事件返回值 
// value為變化后的值 cursor為變化的位置 keyCode為觸發(fā)的鍵值 
const {value, cursor, keyCode} = event.detail 
// 獲取光標(biāo)位置,聚焦時(shí)生效 
wx.getSelectedTextRange({
  complete: res => {
    console.log('光標(biāo)位置:', res.start, res.end)
  }
})

準(zhǔn)備工作做好了就進(jìn)入實(shí)踐環(huán)節(jié),畢竟實(shí)踐是檢驗(yàn)真理的唯一標(biāo)準(zhǔn)。設(shè)計(jì)圖呈現(xiàn):通過(guò)點(diǎn)擊@按鈕到人員列表頁(yè)面,選擇人員后返回,具體如下圖。這里涉及頁(yè)面之間的通信問(wèn)題,可以通過(guò)狀態(tài)管理器、數(shù)據(jù)緩存、獲取頁(yè)面棧設(shè)置數(shù)據(jù)等來(lái)實(shí)現(xiàn),本例中使用數(shù)據(jù)緩存。

 

數(shù)據(jù)組裝

從人員列表返回用 wx.navigateBack ,會(huì)觸發(fā) onShow 這個(gè)生命周期,所以需要在 onShow 里組裝@數(shù)據(jù)。獲取到的@人員根據(jù)光標(biāo)位置對(duì)文本進(jìn)行字符串截取組裝,若未獲取到光標(biāo)位置則直接將@人員添加到文本末尾。然后對(duì)@人員數(shù)據(jù)、文本數(shù)據(jù)等進(jìn)行備份,用于后續(xù)的計(jì)算。

initAtFn() {
    // 獲取@人員數(shù)據(jù)
    const me = this
    const initMemberList = wx.getStorageSync('atMemberList')
    const atMemberArr = initMemberList ? initMemberList : []
    // 賦值后清除@人員數(shù)據(jù)
    wx.removeStorageSync('atMemberList')
    // 獲取上一次光標(biāo)的位置
    const preCursor = wx.getStorageSync('blurCursor') ? parseInt(wx.getStorageSync('blurCursor')) : me.content.length
    // 將 @人員數(shù)據(jù) 并入內(nèi)容區(qū)域
    if (atMemberArr.length > 0) {
     // 獲取人員名稱
     const atMemberName = `@${atMemberArr[0].name}`
     // 如果上次光標(biāo)有記錄 就根據(jù)光標(biāo)分割字符串 并入@人員名稱
     if (preCursor.toString().length !== me.content.length) {
      const start = me.content.substring(0, preCursor)
      const end = me.content.substring(preCursor)
      me.content = `${start}${atMemberName}${end}`
     } else {
      me.content += `${atMemberName}`
     }
     me.atArr = me.atArr.concat(atMemberArr) // 合并人員
     wx.setStorageSync('blurCursor', preCursor + atMemberName.length)
    }else {
     wx.setStorageSync('blurCursor', me.content.length)
    }
    me.focus = true
    me.copyContent = me.content
    me.executeArr = me.getAtMemberPosFn() // 獲取@人員位置
   }

計(jì)算@人員位置

對(duì)@人員數(shù)組進(jìn)行遍歷,計(jì)算@人員在文本中的位置區(qū)間。通過(guò)indexOf來(lái)獲取起點(diǎn)(這里有一個(gè)缺陷,也是需要優(yōu)化的點(diǎn),當(dāng)手動(dòng)輸入的內(nèi)容中有和@人員名字相同的字段時(shí),那么位置靠前的那一個(gè)將會(huì)生效),終點(diǎn)為起點(diǎn)+名字長(zhǎng)度。這里有個(gè)問(wèn)題:如果重復(fù)@相同的人員,刪除時(shí)怎么區(qū)分呢?筆者想當(dāng)然的使用了時(shí)間戳,結(jié)果發(fā)現(xiàn)在遍歷中使用時(shí)間戳并不準(zhǔn)確,只有規(guī)規(guī)矩矩生成唯一值。

計(jì)算時(shí)收集了人員位置的最值區(qū)間,在這個(gè)范圍之外增減文本不會(huì)影響@人員的完整性。下面是代碼:

getAtMemberPosFn() {
    const me = this
    const [tipArr, left, right] = [ [], [], [] ]
    // 根據(jù)@人員的數(shù)組來(lái)匹配計(jì)算所處位置
    me.atArr.map(item => {
     const name = item.name
     const userId = item.userId
     // 此處有一個(gè)缺陷 如果手輸入的和獲取的@人名字相同 第一個(gè)會(huì)生效 第二個(gè)不會(huì)生效
     let start = me.copyContent.indexOf(name)
     
     if (tipArr.length > 0) {
      const _arr = tipArr.filter(v => v.name.includes(name))
      if (_arr.length > 0) {
       start = me.copyContent.indexOf(name, _arr[_arr.length - 1].end)
      }
     }
     
     const end = name.length + start // end
     left.push(start)
     right.push(end)
     // 獲取唯一標(biāo)識(shí) 是用于重復(fù)@的區(qū)分
     const guid = me.createGuidFn()
     const tipObj = {
      start: start - 1, // @ - 1
      end,
      name,
      atName: `@${name}`,
      type: item.userId, 
      userId: userId,
      code: guid
     }
     tipArr.push(tipObj)
    })
    
    // 獲取區(qū)間左右最值
    right.length > 0 ? me.maxAt = Math.max(...right) : me.maxAt = 0
    left.length > 0 ? me.minAt = Math.min(...left) : me.minAt = 0
    me.atArr = tipArr
    return tipArr
   }

一鍵刪除功能

@人員的位置區(qū)間已經(jīng)計(jì)算出來(lái)了,接下來(lái)監(jiān)聽(tīng)輸入框的內(nèi)容變化實(shí)現(xiàn)一鍵刪除功能,當(dāng)輸入框文本內(nèi)容變化,會(huì)觸發(fā) @input 事件,它會(huì)返回變化后的值 value ,變化的位置 cursor ,我們將利用這兩個(gè)數(shù)據(jù)作為是否 命中@人員的判斷依據(jù) 。將情況分為以下幾種:

變化后的value為空,即清空了輸入框。

數(shù)據(jù)變化的光標(biāo)位置大于@人員位置最值區(qū)間的最大值,即不影響@人員位置。

當(dāng)數(shù)據(jù)變化影響@人員時(shí),這里對(duì)增加減少內(nèi)容做了區(qū)分處理:

增加時(shí),如果增加位置小于最值的最小值,則直接重新計(jì)算位置。如果增加值的位置命中@人員位置,則過(guò)濾掉失效人員,再重新計(jì)算。這里需要注意,移動(dòng)端輸入法會(huì)有一次性輸入多個(gè)字符,變化的位置不再是返回的光標(biāo)位置,而是以光標(biāo)位置減去變化前后數(shù)據(jù)的差值。

刪除時(shí),獲取刪除的起始位置 (A,B) ,然后與@人員位置 (start, end) 作比較。 當(dāng) !(A < start || B > end) 時(shí),則為命中,將命中的@人員過(guò)濾掉即可。

changeFn(txt) {
    const me = this
    const { value, cursor, keyCode } = txt.detail // 改變后的值,改變的位置,按鍵
     
    // 如果改變后的值為'', 就直接返回
    if(!value) {
     me.content = value
     me.copyContent = value
     me.atArr = []
     return false
    }
    
    // 判斷值改變的增減
    const changeLen = value.length - me.copyContent.length
    // 值改變的光標(biāo)位置 不影響@人員的則不管
    if (cursor > me.maxAt) {
     me.copyContent = me.content
     return false
    }
  
    // 判斷為 增加值
    if (changeLen > 0) {
     const addCursor = cursor - changeLen // 重新計(jì)算增加位置 防止移動(dòng)端一次性粘貼導(dǎo)致失效問(wèn)題
     me.copyContent = me.content
     // 增加值的位置 小于左區(qū)間最值 則重新計(jì)算位置
     if(addCursor < me.minAt) {
      me.executeArr = me.getAtMemberPosFn()
      return false
     }
     
     me.executeArr.map(item => {
      const { start, end, name, code } = item
      if (addCursor < end && addCursor > start) {
       // 刪除命中人員,則該人員失效
       me.atArr = me.atArr.filter(v => v.code !== code)
      }
     })
     
     // 需要重新計(jì)算位置
     me.executeArr = me.getAtMemberPosFn()
    } else {
     let replaceStr = '' // 應(yīng)被刪除的字段
     const left = [] // 刪除左值集合
     const right = [] // 刪除右值集合
     const delLen = cursor - changeLen // 本身刪除的長(zhǎng)度
     const deleteString = me.copyContent.substring(cursor, delLen) // 本身刪除的字段 [cursor, changeLen)
     // 獲取應(yīng)被刪除的左右位置
     function pushArrEvent(s, e) {
      left.push(s)
      right.push(e)
     }
  
     me.executeArr.map(item => {
      let { start, end, name, code } = item
      // D大 <= B小 || D小 >= B大
      // 命中部分為 刪除部分與@人員的交集
      if (!(delLen <= start || cursor >= end)) {
       // 命中判定,命中位置在名字區(qū)間 左邊/右邊/之間/或者多選中刪除的
       if (delLen <= end && cursor >= start) {
        pushArrEvent(start, end)
       } else {
        if (cursor > start) {
         if (delLen > end) {
          pushArrEvent(start, delLen)
         } else {
          pushArrEvent(start, end)
         }
        } else if (cursor < start) {
         if (delLen > end) {
          pushArrEvent(cursor, delLen)
         } else {
          pushArrEvent(cursor, end)
         }
        } else {
         pushArrEvent(cursor, delLen)
        }
       }
  
       // 獲取一鍵刪除區(qū)間 
       const del_left = Math.min(...left)
       const del_right = Math.max(...right)
       // 根據(jù)區(qū)間獲取一鍵刪除字段
       replaceStr = me.copyContent.substring(del_left, del_right)
       // 刪除后的賦值
       me.content = me.copyContent.substring(0, del_left) + me.copyContent.substring(del_right)
       
       // @人員數(shù)組生成
       me.atArr = me.atArr.filter(v => v.code !== code)
      }
     })
     // 執(zhí)行完后 重新賦值計(jì)算
     me.copyContent = me.content
     me.executeArr = me.getAtMemberPosFn()
    }
   }

添加標(biāo)簽

我們還差最后一步,那就是給@人名添加標(biāo)簽,用于顯示時(shí)與一般文本做區(qū)分。這里踩了一個(gè)坑,用正則替換時(shí),如果名字與名字之間存在包含關(guān)系,則會(huì)失效,所以用記錄位置的方式來(lái)對(duì)文本進(jìn)行截取組裝。

submitTxtFn() {
    const copyTxt = this.content
    const arr = JSON.parse(JSON.stringify(this.atArr))
    const atUserIds = [...new Set(arr.map(v=>v.userId))] // 獲取@人員id
    let targetContent = ''
    let count = 0
    // 給@人員添加wxml標(biāo)簽,此處用了jyf-Parser富文本解析插件,href里面的值用于點(diǎn)擊傳參
    if(arr.length > 0) {
     arr.forEach((item, index)=>{
      let _tip = ''
      const txt = copyTxt.substring(count, item.start)
      // 加空格
      _tip = `${txt}<a class="link" href="${item.name}" rel="external nofollow" >${item.atName} </a>`
      targetContent += _tip
      // 處理最后一個(gè)標(biāo)簽后面的文本
      if(index + 1 === arr.length) {
       if(item.end < copyTxt.length) {
        targetContent += copyTxt.substring(item.end)
       }
      }
      count = item.end
     })
    }else {
     targetContent = this.content
    }
    // 目標(biāo)數(shù)據(jù)
    const targetObj = {
     content: targetContent,
     atIds: atUserIds
    }
    this.submitData = targetObj
    return targetObj
   }

以上就實(shí)現(xiàn)了純文本的@功能,通過(guò)計(jì)算位置來(lái)實(shí)現(xiàn)的優(yōu)點(diǎn)是具有擴(kuò)展性,比如一套代碼可以實(shí)現(xiàn)#話題功能和@功能共存,只需加個(gè)type作為區(qū)分即可。缺點(diǎn)是一鍵刪除時(shí)體驗(yàn)不是很好,并且刪除后不能控制光標(biāo)位置,不能實(shí)現(xiàn)人員名稱變色等。雖然功能比較ZZ,但也比較有趣,所以就分享給大家,如果大家有更好的解決方案,評(píng)論區(qū)有請(qǐng)。

完整代碼請(qǐng)移步 語(yǔ)雀

總結(jié)

到此這篇關(guān)于微信小程序純文本實(shí)現(xiàn)@功能的文章就介紹到這了,更多相關(guān)小程序@功能內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 博客側(cè)邊欄模塊跟隨滾動(dòng)條滑動(dòng)固定效果的實(shí)現(xiàn)方法(js+jquery等)

    博客側(cè)邊欄模塊跟隨滾動(dòng)條滑動(dòng)固定效果的實(shí)現(xiàn)方法(js+jquery等)

    現(xiàn)在很多的獨(dú)立博客和網(wǎng)站如人人網(wǎng)等,都使用了讓側(cè)邊欄模塊隨滾動(dòng)條滑動(dòng)而位置固定的效果
    2013-03-03
  • Javascript highcharts 餅圖顯示數(shù)量和百分比實(shí)例代碼

    Javascript highcharts 餅圖顯示數(shù)量和百分比實(shí)例代碼

    這篇文章主要介紹了Javascript highcharts 餅圖顯示數(shù)量和百分比實(shí)例代碼的相關(guān)資料,這里附有實(shí)例代碼,需要的朋友可以參考下
    2016-12-12
  • JS中封裝axios來(lái)管控api的2種方式

    JS中封裝axios來(lái)管控api的2種方式

    這篇文章主要介紹了封裝axios來(lái)管控api的2種方式,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2019-09-09
  • 解決Layui 表單提交數(shù)據(jù)為空的問(wèn)題

    解決Layui 表單提交數(shù)據(jù)為空的問(wèn)題

    今天小編就為大家分享一篇解決Layui 表單提交數(shù)據(jù)為空的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-08-08
  • 微信小程序12行js代碼自己寫(xiě)個(gè)滑塊功能(推薦)

    微信小程序12行js代碼自己寫(xiě)個(gè)滑塊功能(推薦)

    這篇文章主要介紹了微信小程序12行js代碼自己寫(xiě)個(gè)滑塊功能,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-07-07
  • 最新評(píng)論