精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

小程序實現 ChatGPT 聊天打字兼自動滾動效果

人工智能
本質上不需要在每次 showText 之后都通過 createSelectorQuery 異步獲取元素 scroll-top 并再次渲染,這無疑是性能的浪費,實際可以控制 createSelectorQuery 到 setData 設置 scroll-top 值的頻率來提升性能。

一 前言

ChatGPT 已經長時間大火,未來將會是AI的天下。人們需要更多地學習和掌握AI,而不是被AI所取代。

目前市面上已經有很多類似 chatGPT 的智能應用,應用有可能是 web h5 應用,也有可能是小程序或者是 Native 應用。隨著 ChatGPT 深入,移動端也會再次火爆起來。

在 ChatGPT 的背景下,我們今天來聊聊在小程序中怎么實現類似 chatGPT 的聊天打字效果,并且實現滾動效果,具體如下:

圖片

這篇文章將深入一下內容:

  • 小程序怎么樣實現動態打字效果。
  • 怎么實現隨打字效果滾動。
  • 請求分片知識點。
  • scroll-view 細節處理等。

二 實現打字效果

1.預熱內容—數據請求與接收

開發者可以接入 openAi 提供的接口,實現自定義的問答流程。在聊天會話中,我們問 chatGPT 一句話:

介紹一下跨端開發

那么和平常的請求不同的是,數據并不是一次性返回的,而是采用 stream 流式返回的。我們可以在 Network 中看到 response 的大體結構:

圖片

如上可以看到返回的 text 是分片處理的,每次會返回一小段內容,只要前端根據返回這一小段內容就可以了,也就自然形成了打字的效果。

可能會有同學好奇,這種分片的數據結構,前端應該怎么接收呢?實際很簡單,我們拿 axios 為例子,開發者可以通過監聽onDownloadProgress 事件來接受服務端返回的文本片段。具體例子如下:

axios({
  method: 'post',
  url: 'https:xxx.xxx,
  onDownloadProgress: function({ event  }) {
    const xhr = event.target
    const { responseText } = xhr
    /* 獲取返回的內容,本質上是 json 字符串 */
    let chunk = responseText
    try{
        /* 序列化返回的內容 */
       const data = JSON.parse(chunk)
       /* chatGPT 返回的內容 */
       console.log(data.text)
    }catch(e){

    }
  }
})

這里描述請求的流程,通過 onDownloadProgress 來監聽返回的內容,然后獲取到返回的內容,JSON.parse 解析內容,這里有一個注意事項,就是對于 JSON.parse 應該加上 try catch ,防止解析的失敗。

2.小程序中接口處理

小程序沒有如上 axios 里面監聽 stream 流式響應數據的能力,也沒有處理 onDownloadProgress 的回調函數。簡單來說 onDownloadProgress 的實現,本質上是 axios 在瀏覽器發起 http 請求,會創建一個 XHR 對象,其用于發送請求和接收響應,在創建 XHR 對象后,axios 會注冊一個 progress 事件監聽器到 XHR 對象上,用于獲取下載的進度信息。

那么小程序中如何實現分片流式下載呢?在小程序中,統一收口到 request 中,在 request 中可以用 RequestTask 的 onChunkReceived 來接收服務端的分片數據。這個方法可以監聽 Transfer-Encoding Chunk Received 事件。當接收到新的 chunk 時觸發。

我們來看看具體怎么使用:

const requestTask = wx.request({ 
    enableChunked:true,  // 開啟分片模式
    ...
})
requestTask.onChunkReceived((res)=>{
    // 接收分片的數據
})

這樣就可以通過分片來實現打字的效果。

3.打字效果實現

接下來我們看一下小程序是如何實現打字效果的,先不考慮返回的數據是 stream 流式結構,先認為返回的數據格式是整個文本,那么應該怎么樣處理文本呢。

首先我們聊天的內容如下所示:

圖片

如上, 每一個消息都是一個 message-item ,所有的 message 保存到了 messageList 列表中,在 wxml 中如下所示:

<view wx:for="{{messageList}}" wx:key="id" id="item-{{item.id}}">
    <message-item 
        data-index="{{index}}" 
        role="{{item.role}}" 
        content="{{item.content}}"
        finished="{{item.finished}}" 
        bind:share="handleMessageShare" 
    />
</view>

如上,可以看到 message-item 保存了一條會話內容。

當我們發一條信息的時候,產生一條 message-item 。接下來 chatGPT 返回內容后,也會產生一條 message-item ,要實現打字效果就是這條 message-item 。

我們只需要將這條 message-item 的內容,通過 setData 方式分片渲染就可以了。比如我們想打字實現 ‘您好GPT’,那么分五次 setData 渲染就可以了,比如如下:

  • 您好
  • 您好G
  • 您好GP
  • 您好GPT

如上就是分五次渲染,每一次渲染的結果。接下來就是代碼的實現。

this.handleRequestResolve(data.text)

比如 chatGPT 每次返回一條內容,都用 handleRequestResolve 函數處理返回的內容。看一下 handleRequestResolve 的核心實現。

handleRequestResolve(result){
    const timestamp = Date.now();
    const index = this.data.messageList.length
    const newMessageList = `messageList[${index}]`
    const contentCharArr = result.trim().split("")
    const content_key = `messageList[${index}].content`
    const finished_key = `messageList[${index}].finished`
    this.setData({
        thinking: false,
        [newMessageList]: {
            id: timestamp,
            role: 'assistant',
            finished: false
        }
    })
    currentContent = ''
    this.showText(0, content_key, finished_key, contentCharArr);
}

在 handleRequestResolve 中會構建一條新的 message-item ,然后就是 showText 展示內容,來看一下 showText 怎么處理內容。

showText(key = 0, content_key, finished_key, value) {
     /* 所有內容展示完成 */
    if (key >= value.length) {
        this.setData({
            loading: false,
            [finished_key]: true
        })
        wx.vibrateShort()
        return;
    }
    currentContent = currentContent + value[key]
    /* 渲染回話內容 */
    this.setData({
        [content_key]: currentContent,
    })
    setTimeout(() => {
        /* 遞歸渲染內容 */
        this.showText(key + 1, content_key, finished_key, value);
    }, 50);
},

這樣用遞歸就實現了打字效果。我們來看一下效果:

圖片

通過上面可以看到,在文字打印的過程中,列表不能跟隨一起滾動,當文字內容超出一屏幕之后,視圖就停止了(本質上數據在后面追加),這是一個很不好的效果。

接下來,我們進行優化處理,讓視圖可以根據內容自動滾動。

三 如何實現視圖跟隨內容滾動

3.1 實現原理

實現視圖跟隨內容滾動實際很簡單,因為 message-item 的容器本質上就是一個 scroll-view , 那么想要 scroll-view 視圖跟隨返回內容變化,只需要動態設置 scroll-view 的 scroll-top 值就可以了。

視圖跟隨內容滾動,本質上就是讓 scroll-view 一直自動滾動到底部, 如何要讓 scroll-view 一直滾動到底部呢?先看一下如下示意圖:

圖片

如上可以看到,想讓 scroll-view 一直滾動到底部,只需要讓 scroll-top 等于 scroll-view 內容高度減去 scroll-view 容器本身高度就可以了。

所以需要我們給 scroll-view 里面的內容,用一個 view 包裹如下:

圖片

如上 scroll-view 的類名為 content, scroll-view 內部元素的類名為 scroll-view-content,接下來可以通過如下代碼設置 scroll-top 值了。

handleScollTop() {
        return new Promise((resolve) => {
            const query = wx.createSelectorQuery()
            query.select('.content').boundingClientRect()
            query.select('.scroll-view-content').boundingClientRect()
            query.exec((res) => {
                const scrollViewHeight = res[0].height
                const scrollContentHeight = res[1].height
                if (scrollContentHeight > scrollViewHeight) {
                    const scrollTop = scrollContentHeight - scrollViewHeight
                    this.setData({
                        scrollTop
                    }, () => {
                        resolve()
                    })
                }else{
                    resolve()
                }
            })
        })
    },

如上通過 createSelectorQuery 分別獲取 scroll-view 和 scroll-view 內部元素的高度,兩者的差值就是 scroll-top 值。

接下里在渲染會話內容的時候,渲染之后,調用 handleScollTop 來動態設置 scroll-top 就可以了。

showText(key = 0, content_key, finished_key, value) {
    if (key >= value.length) {
        this.setData({
            loading: false,
            [finished_key]: true
        })
        wx.vibrateShort()
        return;
    }
    currentContent = currentContent + value[key]
    this.setData({
        [content_key]: currentContent,
    },()=>{
        this.handleScollTop().then(()=>{
            setTimeout(() => {
                this.showText(key + 1, content_key, finished_key, value);
            }, 20);
        })
    })
},

這里有一個小細節,就是在渲染上一次文本內容之后,需要先校驗一下 scroll-top 值,然后再次調用 showText 來渲染會話內容。

我們來看一下效果。

圖片

后續優化: 本質上不需要在每次 showText 之后都通過 createSelectorQuery 異步獲取元素 scroll-top 并再次渲染,這無疑是性能的浪費,實際可以控制 createSelectorQuery 到 setData 設置 scroll-top 值的頻率來提升性能。

四 總結

感興趣的同學可以自己實現一個會話打字效果,其中還有很多小細節這里就不講了。

責任編輯:武曉燕 來源: 前端Sharing
相關推薦

2023-03-28 08:05:37

2022-07-26 08:02:33

Android微信程序

2023-11-22 07:47:34

2024-05-28 09:21:25

2025-06-17 09:21:13

2011-06-27 13:57:42

JavaScript

2011-09-01 13:17:46

JQuery滾動

2022-06-15 22:15:47

CSS視覺還原

2011-09-15 10:05:09

Android應用iTriage健康顧問

2022-06-23 06:42:06

CSSJS 監聽

2022-07-05 08:26:10

Python報表自動化郵箱

2023-03-03 00:08:36

微軟機器人聊天

2017-01-09 10:42:56

微信小程序

2024-04-15 09:22:48

CSS鎖定overflow

2013-11-11 09:26:50

編程思考

2024-04-03 15:20:08

2023-04-01 10:16:57

ChatGPT-4程序員失業

2020-12-09 07:54:17

Vue插件鼠標

2023-10-12 07:40:54

Minium自動化框架

2011-09-02 10:14:10

JQuery滾動Xslider
點贊
收藏

51CTO技術棧公眾號

黄色一区二区在线观看| 日本午夜一本久久久综合| 91精品久久久久久蜜臀| 国产xxxx振车| 国产高清一级毛片在线不卡| 久久爱另类一区二区小说| 欧美高清在线视频观看不卡| 国产中年熟女高潮大集合| 九九99久久精品在免费线bt| 亚洲成av人片在线观看| 亚洲区一区二区三区| www.亚洲黄色| 日本欧美韩国一区三区| 欧美乱妇40p| 免费看黄色的视频| 91精品久久久久久综合五月天| 一本到不卡免费一区二区| 一区二区三区四区免费观看| 邻居大乳一区二区三区| 国产成人99久久亚洲综合精品| 欧洲成人在线观看| 91视频综合网| 成人羞羞动漫| 日韩成人在线电影网| 无套内谢丰满少妇中文字幕| 自拍偷自拍亚洲精品被多人伦好爽| 亚洲精品成人悠悠色影视| 日本一区二区精品| 无码精品在线观看| 国产一区二区三区精品欧美日韩一区二区三区 | 国产精品青草久久久久福利99| 中文字幕欧美人与畜| 色婷婷在线视频| 国产在线精品一区二区| 国产成人综合av| 欧美三级韩国三级日本三斤在线观看| 99久久.com| 国产一区二区三区三区在线观看| 国产精品无码永久免费不卡| 超碰地址久久| 日韩精品在线看片z| 中文字幕第22页| 123成人网| 色视频欧美一区二区三区| 欧美午夜性视频| 五月婷婷视频在线观看| 中文字幕日韩一区二区| 亚洲不卡1区| 污视频在线免费观看| 国产精品亚洲第一区在线暖暖韩国| 国产日韩欧美在线观看| 中国一级特黄视频| 热久久久久久久| 国产精品黄色影片导航在线观看| 亚洲欧美偷拍一区| 美女视频一区免费观看| 欧美有码在线观看| 精品免费囯产一区二区三区| 国产亚洲激情| 国产成人a亚洲精品| 中文字幕亚洲乱码熟女1区2区| 国产农村妇女精品一区二区| …久久精品99久久香蕉国产| 亚洲婷婷综合网| 美女国产一区| 国产美女精彩久久| 国产精品怡红院| 国产精品99久久久| 俄罗斯精品一区二区| 高潮毛片7777777毛片| 99精品久久99久久久久| 欧美精品123| jizz在线观看视频| 国产精品成人免费在线| 欧美一级黄色录像片| 俺来也官网欧美久久精品| 亚洲大片精品永久免费| 干日本少妇首页| 日本在线中文字幕一区二区三区| 欧美色综合网站| 91亚洲一区二区| 日本免费一区二区三区视频| 亚洲国产精品成人va在线观看| 大地资源二中文在线影视观看 | 亚洲午夜女主播在线直播| 日韩丰满少妇无码内射| 图片区亚洲欧美小说区| 欧美黑人xxxⅹ高潮交| 天天干天天干天天干天天| 捆绑变态av一区二区三区| 7777精品伊久久久大香线蕉语言 | 日韩在线视频网| 妺妺窝人体色www婷婷| 国产欧美一级| 成人性生交大片免费看视频直播| 国产 欧美 精品| 国产日韩高清在线| 欧洲金发美女大战黑人| 人人草在线视频| 欧美精品v国产精品v日韩精品| 性生交大片免费看l| 精品久久久久久久| 久久久爽爽爽美女图片| 姑娘第5集在线观看免费好剧| 国产精品99久久久久久久vr| 日本亚洲自拍| 久久五月精品中文字幕| 欧美午夜精品免费| xfplay5566色资源网站| 日韩在线欧美| 91高清免费视频| www.国产视频| 国产精品久久久久久亚洲毛片| 久久综合久久网| 亚洲91在线| 亚洲欧美一区二区三区久久| 久草视频在线资源站| 男女性色大片免费观看一区二区 | 欧美一区影院| 国产精品老女人视频| 日韩在线观看视频一区| 亚洲丝袜美腿综合| 少妇人妻互换不带套| 菁菁伊人国产精品| 久操成人在线视频| 在线观看色网站| 国产欧美一区在线| 能在线观看的av| 给我免费播放日韩视频| 久久久国产精品一区| 毛片在线免费播放| 久久先锋影音av| 国产一线二线三线女| 精品一区二区三区中文字幕| 日韩网站免费观看高清| 久久午夜鲁丝片| 久久久影视传媒| 国产免费观看高清视频| 美国成人xxx| 久久久久久久久久久成人| www.色视频| 一区二区欧美国产| 成人啪啪18免费游戏链接| 亚洲天堂免费| 成人在线精品视频| 国产高清一区二区三区视频 | 亚洲免费黄色片| 亚洲激情男女视频| 男人添女人荫蒂国产| 欧美1区2区3区| 春色成人在线视频| 黄网站在线观| 亚洲国产精品va在线看黑人动漫 | 亚洲毛片在线| 久久riav| 美女100%一区| 国产一区二区三区视频免费| 欧美一级片免费在线观看| 国产a区久久久| 老太脱裤子让老头玩xxxxx| 大陆精大陆国产国语精品| 国内精品久久久久伊人av| 午夜视频1000| 日韩欧美国产视频| 天堂网av2018| 狠狠色丁香婷综合久久| 国产对白在线播放| silk一区二区三区精品视频| 久久久久久久一区二区三区| 色窝窝无码一区二区三区成人网站| 午夜精品一区在线观看| 欧美成人午夜精品免费| 日韩主播视频在线| 青少年xxxxx性开放hg| 精品亚洲a∨一区二区三区18| 欧美极品美女电影一区| 性感美女福利视频| 91成人网在线| 我家有个日本女人| 99久久精品免费| 日本老熟妇毛茸茸| 五月综合激情| 国产一区二区三区四区hd| 日本免费一区二区三区四区| 中文字幕在线亚洲| 亚洲成人一级片| 欧美视频在线观看免费| 成年人免费视频播放| 成人深夜在线观看| 久久精品影视大全| 欧美精品一卡| 视频在线精品一区| 亚洲综合影院| 国产精品白嫩初高中害羞小美女| 污污的网站在线免费观看| 亚洲欧洲一区二区三区久久| 国产露脸91国语对白| 欧美午夜激情视频| 三级在线观看免费大全| 91最新地址在线播放| 天堂在线一区二区三区| 国产精品一级| 国产青草视频在线观看| 欧美色图一区| 国产色综合一区二区三区| 日韩三级一区| 欧美在线视频免费播放| 图片区小说区亚洲| 国产一区二区三区视频免费| 日本激情一区二区| 欧美精品视频www在线观看| 久久国产黄色片| 亚洲精品水蜜桃| 亚洲精品视频久久久| 国产成人精品一区二区三区网站观看| 国产又粗又长又大的视频| 1024日韩| 欧美日韩激情四射| 日韩片欧美片| 青娱乐一区二区| 欧美久久精品| 高清一区二区三区视频| 成人国产在线| 欧美又大又粗又长| 高清电影在线观看免费| 久久精品国产精品亚洲| 国产大学生校花援交在线播放| 亚洲第一黄色网| 亚洲AV无码国产精品午夜字幕 | 亚洲精品18p| 91麻豆精品国产无毒不卡在线观看| 日韩 欧美 中文| 亚洲成人综合在线| 中文字幕av免费在线观看| 国产精品福利电影一区二区三区四区| 88久久精品无码一区二区毛片| www.亚洲精品| 中国免费黄色片| 国产成人免费在线观看| 日本少妇xxx| 国产精品香蕉一区二区三区| 成人av毛片在线观看| 紧缚捆绑精品一区二区| 一本色道久久亚洲综合精品蜜桃| 天堂久久久久va久久久久| 伊人婷婷久久| 日韩精品91| 亚洲精品一区二区三区四区五区| 精品一区二区三区在线| 欧美日韩精品免费观看视频| 裸体大乳女做爰69| 97精品国产福利一区二区三区| 色之综合天天综合色天天棕色| 国产欧美一区| 你懂的网址一区二区三区| 日韩欧美影院| 欧美午夜欧美| 第一sis亚洲原创| 最新黄色av网站| 欧洲杯足球赛直播| 亚洲欧洲精品一区二区| 66视频精品| 欧美久久久久久久久久久久久久| 亚洲欧美综合| 成人在线观看你懂的| 亚洲自拍另类| av污在线观看| 国产一区二区导航在线播放| 制服丝袜在线第一页| 2021中文字幕一区亚洲| 亚洲av毛片基地| 亚洲欧美经典视频| 日韩av电影网| 在线观看网站黄不卡| 国产精品热久久| 精品国产乱码久久久久久老虎 | 在线观看亚洲精品福利片| 91久久国产婷婷一区二区| julia中文字幕一区二区99在线| 免费日韩av电影| 先锋资源久久| 青青青在线视频播放| 日韩激情一二三区| 欧美色图校园春色| 92精品国产成人观看免费| 国产精品视频在| 亚洲国产成人va在线观看天堂| www.国产一区二区| 在线观看91av| 亚洲 美腿 欧美 偷拍| 中文字幕无线精品亚洲乱码一区 | av色图一区| 欧美激情欧美激情在线五月| 日本高清不卡一区二区三区视频 | 亚洲三级在线看| 你懂的国产视频| 欧美一区日韩一区| 深夜福利视频在线免费观看| 欧美性色19p| 一区二区三区精彩视频| 日韩成人在线播放| 国产在线看片| 懂色av一区二区在线播放| 国产精品久久久久久久久久久久午夜片 | 法国伦理少妇愉情| 国产成人午夜电影网| 最新中文字幕视频| 亚洲欧美另类小说| 天天干在线播放| 日韩欧美激情四射| 在线看免费av| 青青精品视频播放| 91麻豆精品| 欧美一区二区三区成人久久片| 国产精品久久| 欧美日韩在线成人| 粉嫩久久99精品久久久久久夜| 91ts人妖另类精品系列| 日韩欧美成人网| 免费av网站观看| 久久夜色精品国产欧美乱| 在线成人视屏| 久99久在线| 激情欧美丁香| 超碰人人cao| 亚洲色图丝袜美腿| 中文字幕视频二区| 亚洲人精品午夜在线观看| 电影k8一区二区三区久久| 亚洲va欧美va国产综合剧情| 日韩系列欧美系列| 一区二区三区国产免费| 26uuu亚洲综合色| 成人毛片18女人毛片| 亚洲大胆人体在线| 黄色污污视频在线观看| 亚洲一区二区三区视频| 亚洲国产一成人久久精品| 日本黄色的视频| 国产精品国产三级国产aⅴ中文 | 91麻豆精品久久毛片一级| 色婷婷av久久久久久久| 日本在线一二三| 欧美亚洲第一页| 美女久久久久| 国产成人精品无码播放| 国产欧美一区二区在线观看| 69视频免费看| 中文字幕日韩在线观看| 福利一区在线| 宅男一区二区三区| 国产中文字幕精品| 九九九免费视频| 欧美videos中文字幕| av影院在线| 久久爱av电影| 免费看欧美女人艹b| 蜜桃av免费在线观看| 欧美电影在线免费观看| 日本动漫同人动漫在线观看| 国产九色91| 久久久精品午夜少妇| www.99热| 日韩一区二区三区免费看| 日本大片在线播放| 精品日本一区二区| 日韩激情一二三区| 成人欧美一区二区三区黑人一| 欧美一区永久视频免费观看| 92久久精品| 日本欧美精品久久久| 久久精品久久久精品美女| 欧美日韩大片在线观看| 亚洲国产精久久久久久| 免费观看欧美大片| 亚洲欧美日韩国产yyy| 国产一区二区三区视频在线播放| 日本少妇全体裸体洗澡| 国产亚洲精品91在线| 国产95亚洲| 欧美v在线观看| 亚洲欧美综合色| 日本黄视频在线观看| 国产精品成人播放| 欧美日韩国产欧| 巨胸大乳www视频免费观看| 911精品国产一区二区在线| 国产青青在线视频| www激情久久| 国产一区二区网站| 午夜精品视频在线| 日韩精品水蜜桃| 色婷婷久久久久swag精品| 国产私拍精品| av在线不卡一区| 日本强好片久久久久久aaa| 久久精品国产亚洲av无码娇色| 亚洲人成电影在线播放| 国产精一区二区| 国产精品igao|