精品欧美一区二区三区在线观看 _久久久久国色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技術棧公眾號

少妇特黄a一区二区三区| 97香蕉久久超级碰碰高清版 | 国产精品一二三视频| 亚洲AV无码成人精品区明星换面| 日韩av黄色| 亚洲综合在线观看视频| 久久久综合亚洲91久久98| 中文字幕在线观看免费| 午夜精品国产| 亚洲视频在线观看| 69久久精品无码一区二区| 国产三级电影在线播放| 国产精品卡一卡二| 精品国产免费久久久久久尖叫| 中文永久免费观看| 亚洲二区在线| 日韩天堂在线视频| 欧类av怡春院| 国产一精品一av一免费爽爽| 欧美视频精品一区| 男女啪啪的视频| 精品影院一区| 成人黄色777网| 国产色婷婷国产综合在线理论片a| 国产一级生活片| 国产精品99在线观看| 精品亚洲一区二区三区| 4438x全国最大成人| 欧美va在线观看| 性做久久久久久免费观看| 一区二区精品在线观看| 日本一二三区在线视频| 粉嫩av一区二区三区在线播放| 国产精品男女猛烈高潮激情| av大片免费观看| 黄色国产精品| 精品中文字幕在线观看| 最新日韩免费视频| 精品国产中文字幕第一页| 亚洲精品国产综合区久久久久久久| 成人免费在线观看视频网站| 另类激情视频| 欧美性xxxx极品高清hd直播| www.射射射| 欧美寡妇性猛交xxx免费| 亚洲欧美在线视频观看| 无码免费一区二区三区免费播放 | 成人精品国产| 在线观看一区日韩| 苍井空浴缸大战猛男120分钟| 9lporm自拍视频区在线| 一区二区三区欧美亚洲| 色哺乳xxxxhd奶水米仓惠香| а√天堂官网中文在线| 中文字幕在线播放不卡一区| 亚洲一区二区三区免费看| yw视频在线观看| 国产精品―色哟哟| 亚洲一区美女| 黄色在线播放网站| 亚洲精品国产高清久久伦理二区| 男同互操gay射视频在线看| 麻豆传媒免费在线观看| 亚洲天堂免费看| 91精品国产吴梦梦| 午夜影院免费在线| 亚洲午夜精品在线| 国产精品专区在线| 女厕盗摄一区二区三区| 日韩欧美999| 手机看片福利日韩| 日本午夜免费一区二区| 欧美一区二区三区四区视频| 人妻换人妻仑乱| ccyy激情综合| 日韩精品在线观看视频| 免费黄色片网站| 91麻豆精品国产91久久久平台| 久久亚洲精品成人| 国产亚洲成人av| 国产欧美欧美| 国产精品美女午夜av| 一级黄色a视频| 国产精品77777| 久久国产主播精品| a天堂中文在线88| 亚洲欧美中日韩| 免费看黄在线看| 深夜视频一区二区| 欧美一区二区三级| 亚洲观看黄色网| 热久久天天拍国产| 精品中文字幕视频| 亚洲黄色免费观看| 精品一区二区免费| 精品国产乱码久久久久久108| 黄色在线播放| 一区二区三区不卡视频| 成人综合视频在线| 日韩大陆av| 日韩av最新在线| 久久嫩草捆绑紧缚| 在线视频观看日韩| 国产精品免费久久久久久| 国内精品偷拍视频| 久久九九国产精品| 妺妺窝人体色www看人体| 日韩免费va| 日韩女优毛片在线| 娇妻被老王脔到高潮失禁视频| 中文字幕人成人乱码| 欧美做受高潮电影o| av中文字幕免费在线观看| 久久先锋影音av| 久久综合亚洲精品| 日本精品在线一区| 亚洲成人在线网| 波兰性xxxxx极品hd| 亚洲影视综合| 电影午夜精品一区二区三区| 日本视频在线| 在线一区二区三区做爰视频网站| 日本亚洲一区二区三区| 欧美成人自拍| 国产精品扒开腿爽爽爽视频| 日批免费在线观看| 亚洲日穴在线视频| 91极品视频在线观看| 亚洲精品一级二级三级| 久久久久久久久久婷婷| 国产激情无套内精对白视频| 国产精品理论在线观看| 国产三级日本三级在线播放| 蜜臀av一区| 久久久久久噜噜噜久久久精品| 国产精品国产一区二区三区四区| 国产日韩一级二级三级| 欧美亚洲另类色图| 免费看成人人体视频| 国模精品视频一区二区| 黄色av中文字幕| 亚洲制服丝袜av| 成人一区二区三区仙踪林| 91av精品| 97在线资源站| 日本理论中文字幕| 亚洲毛片一区| 国产精品一区而去| 天堂va在线| 精品久久人人做人人爱| avtt天堂在线| 国产乱国产乱300精品| 天天成人综合网| 欧美.com| 久久久久久久色| 污视频在线免费观看| 午夜精品久久久久久久| 狠狠人妻久久久久久综合蜜桃| 亚洲国产二区| 久久福利电影| xx欧美xxx| 中文字幕成人精品久久不卡| 97国产成人无码精品久久久| ...中文天堂在线一区| 五月天婷婷在线观看视频| 中文字幕日韩欧美精品高清在线| 97久久夜色精品国产九色| 四虎av在线| 亚洲国产日韩精品在线| 欧美一区二区三区网站| 国产欧美日本一区视频| www.久久av.com| 欧美91大片| 国产一区二区三区高清视频| 久久久久久久| 久久视频这里只有精品| 性做久久久久久久久久| 大桥未久av一区二区三区| www.av天天| 激情都市一区二区| 日本中文字幕亚洲| 一道本一区二区三区| 国产欧美精品va在线观看| 日韩精品卡一| 亚洲人成网站免费播放| 国产精品一区二区黑人巨大| 亚洲自拍偷拍图区| 高潮毛片无遮挡| 国产一区二区看久久| 9久久9毛片又大又硬又粗| 精品产国自在拍| 亚洲综合中文字幕68页| 涩涩网在线视频| 久热精品视频在线免费观看| 性xxxxbbbb| 欧美精品一卡二卡| 日韩欧美国产亚洲| 国产精品不卡一区二区三区| 国产乱国产乱老熟300部视频| 国产精品久久久久久模特| 一级日韩一区在线观看| 欧美日韩导航| 91人成网站www| 亚洲十八**毛片| 久久成人在线视频| 黄网在线免费| 亚洲国产精品久久久久| 亚洲一区中文字幕在线| 岛国视频午夜一区免费在线观看| 午夜精品一区二区三级视频| 久久看人人爽人人| 国产a级片视频| 久久国产尿小便嘘嘘| 欧美成人高潮一二区在线看| 天天影视欧美综合在线观看| 日韩不卡av| 久久99精品国产自在现线| 成人黄色av网站| 欧亚一区二区| 57pao国产成人免费| av软件在线观看| 最近2019中文免费高清视频观看www99 | www.久久国产| 成人免费精品视频| 日本77777| 日本网站在线观看一区二区三区 | 日本vs亚洲vs韩国一区三区 | 日韩国产精品久久| 久久综合九色综合88i| 欧美黄色免费| 二级片在线观看| 欧美r级电影| 亚洲人成影视在线观看| 国产91一区| 美国av一区二区三区| xvideos.蜜桃一区二区| 亚洲自拍偷拍网址| 欧美午夜三级| 国产精品十八以下禁看| 日韩一区二区三区免费| 庆余年2免费日韩剧观看大牛| 青青青草视频在线| 欧美成人午夜激情| 天使と恶魔の榨精在线播放| 欧美成人黑人xx视频免费观看| 久久五月精品| 久久成人精品视频| 亚洲精品白浆| 久久久影视精品| 黄页网站在线观看免费| 色综合久久88色综合天天看泰| 大地资源网3页在线观看| 俺去啦;欧美日韩| 黄色精品免费看| 欧美日韩高清区| 51漫画成人app入口| 26uuu国产精品视频| 日韩精品极品| 国产97人人超碰caoprom| 精品3atv在线视频| 国产精品久久久久久久美男 | 六月婷婷七月丁香| 久久久综合九色合综国产精品| 波多野吉衣中文字幕| 久久精品在线观看| av手机在线播放| 亚洲欧美日韩一区二区| 麻豆亚洲av熟女国产一区二| 亚洲图片欧美一区| www.毛片.com| 欧美日韩亚洲综合一区| 国产成人精品白浆久久69| 精品成人a区在线观看| 免费在线超碰| 中文字幕亚洲综合久久| av网址在线| 2019国产精品自在线拍国产不卡| 欧美电影免费观看高清完整| 国产日韩欧美在线播放| 欧美电影在线观看一区| 精品国产乱码久久久久久丨区2区| 国产免费久久| 蜜桃网站在线观看| 99国产精品自拍| 最新中文字幕免费视频| 国产精品99久久久久久似苏梦涵| 无码精品一区二区三区在线播放| 国产欧美日韩在线| 青青草原免费观看| 色婷婷av一区二区三区软件| av一级黄色片| 亚洲丝袜av一区| 美女精品视频| 国产啪精品视频| 久久久伦理片| av电影一区二区三区| 亚洲在线观看| 久久久国产精品久久久| 久久久久国产精品麻豆| 深夜福利影院在线观看| 在线免费观看成人短视频| 亚洲国产精品久久久久久久| 一本色道久久88综合日韩精品| 色呦呦在线视频| 国产精品视频在线播放| 国产精品调教| 不卡中文字幕在线| 久久国产精品亚洲77777| 国产高清av片| 国产精品丝袜一区| 国产精品7777777| 日韩一区二区电影网| 黄色片在线看| 2019中文字幕在线观看| 免费看日产一区二区三区| 日韩免费电影一区二区| 亚洲毛片一区| 韩国一区二区三区四区| 国产精品久久久久久福利一牛影视 | 天天av综合网| 欧美二区在线播放| av在线成人| 亚洲精品一卡二卡三卡四卡| 亚欧美中日韩视频| 伊人久久一区二区三区| 亚洲精品视频自拍| 国产一区二区小视频| 国产一区二区成人| 大胆人体一区二区| 国模精品一区二区三区| 国内视频精品| 韩国av中国字幕| 一区二区三区四区亚洲| 国产偷拍一区二区| 久久亚洲成人精品| 亚洲ww精品| 日韩视频在线免费播放| 青青草国产精品97视觉盛宴| 老头老太做爰xxx视频| 色综合视频在线观看| 日韩在线免费看| 2019最新中文字幕| 五月激激激综合网色播| 亚洲熟妇无码另类久久久| 成人午夜视频福利| 激情小说中文字幕| 精品欧美一区二区三区精品久久| 日韩另类在线| 国产伦精品一区二区三区照片| 激情av一区| 国产情侣久久久久aⅴ免费| 亚洲午夜视频在线| 天堂网av2014| 日产精品久久久一区二区福利| 国产一区二区三区四区五区 | 日韩成人免费观看| 日韩国产欧美区| 欧美大胆成人| 亚洲精品国产精品国自产观看| 蜜桃av噜噜一区| 国产一二三区精品| 日韩一区二区精品在线观看| 国产丝袜精品丝袜| 久久偷窥视频| 日本va欧美va瓶| 欧美高清视频一区二区三区| 精品区一区二区| 欧美xxxxxx| 午夜精品一区二区在线观看 | 日韩成人av一区二区| 日韩欧美高清在线视频| se在线电影| 97久久天天综合色天天综合色hd| 亚洲激精日韩激精欧美精品| 扒开jk护士狂揉免费| 精品视频999| 男女免费观看在线爽爽爽视频| 久久涩涩网站| 久久成人免费电影| 国产在线视频在线观看| 亚洲欧美成人精品| 欧美亚洲二区| 阿v天堂2017| 亚洲欧洲精品一区二区精品久久久| 国内精品久久久久久久久久| 欧美亚洲另类在线| 天天射—综合中文网| 性色av蜜臀av浪潮av老女人| 欧美在线观看一二区| 日韩电影免费观看| 欧美日韩在线一二三| 国产一本一道久久香蕉| 99热在线观看免费精品| 日韩中文视频免费在线观看| 国产伦乱精品| 亚洲欧美自拍另类日韩| 亚洲不卡在线观看| 浪潮av一区| 色视频一区二区三区| 高清在线成人网|