最近はユニアプリが中心ですが、ひとつ言えることは、このフレームワークは端末をまたがって本当にすごいということです.コードのセットをコンパイルして、一度に複数の端末で使用することができます. しかし、その後の互換性の問題も次々と発生しており、APP の最下層での同様の変更も無力です。同時に、uniapp のパフォーマンスの問題は常に人々から批判されてきました.この点では、私たち自身のコーディング能力を改善する必要があり、第二に、dcloud チームに頼ってフレームワークを継続的に最適化する必要があります.
このブログは、uniapp を使用してチャット APP を開発する際のステッピング問題を記録することです。
1. 入力ボックスが文字を飲み込み、カーソルがちらつく
input
コンポーネントでもコンポーネントでも、uniapp での入力ボックスの使用textarea
には問題があります。つまり、コンポーネントがバインドされている場合v-model
、Apple 携帯電話または選択領域を持ついくつかの特殊な入力方法で入力すると、入力ボックスが文字を飲み込み、最後の 2 つのバグにカーソルがちらつくというバグが発生します。テキストの途中から入力する場合。
この問題の解決策は、:value
入力ボックスをバインドし、入力ボックスに 2 つの変数 (1 つの実value
数値と 1 つの一時tempValue
値) を割り当てる場合にのみ使用できます。一時的なtempValue
値は、入力によってトリガーされたイベントでリアルタイムに受信するために使用されます@input
. 実際の値は、最初に値なしから値に変化したときに一度だけ受信され、その後、実際の値を空に設定するだけで済みますvalue
送信時に入力ボックスをクリアします。value
<template>
<textarea :value="value" @input="handleInput"></textarea>
<button @click="handleClickSend">发送</button>
</template>
export default {
data: {
value: '',
tempValue: ''
}
handleInput(event) {
const value = event.detail.value
if(!this.value) {
// 第一次值为空时赋给真实值
this.value = value
}
this.tempValue = value // 临时值用于实时接收
}
async handleClickSend() {
if(!this.value) {
return
}
// 发送时,临时值存储的为当前输入框内的值
// 随后将真实value值设置为空实现清空输入框
// 模拟发送请求
const res = await this.$axios.post({
url: xxxx,
text: this.tempValue
})
this.value = '' // 清空输入框
}
}
2. コンポーネントのキー値の問題
ブロガーは、必要なパラメーターを渡すだけでさまざまなメッセージをレンダリングできるメッセージ バブル レンダリング コンポーネントをカプセル化しましたが、開発プロセス中に、バブル メッセージによってスローされる長押しイベントのパラメーターが正しくないことがわかりました。研究は、key
解決するコンポーネントに価値を追加します。
<template>
<view class="chat-warp" v-for="item of msgList" :key="item.id">
<!-- 注意,需要给组件也给key值 -->
<chat-item :item="item" :key="item.id"></chat-item>
</view>
</template>
vue のコンポーネントの更新メカニズムが異なる可能性があるため、v-for
ループ内のコンポーネントもkey
値を指定する必要があります。
3. メッセージの配置の問題
プロジェクトのチャット ページは、パッケージ化されたscroll-view
リッチ テキスト コンポーネントを使用して、さまざまなメッセージをレンダリングします. プルダウンからさらにメッセージが読み込まれると常に画面のちらつきが発生するため、最後の 2 つのレイヤーが一緒に使用されますscroll-view
.レイヤーはフェイクニュースです。さらに読み込むと、偽のメッセージが表示され、実際のメッセージが非表示になります. メッセージが完全にレンダリングされて配置されると、偽のメッセージが非表示になり、実際のメッセージが表示されます.
(1) 一番下までスクロールできない問題
開発の過程で、メッセージを送信するときにスクロールが下まで届かない、チャット ページに入るとき、スクロールが下まで届かないという問題に遭遇することがよくあります。
これを受けて、最初は常に下を目指してスクロールしていて、goBottom
ページに入るとすぐに機能が7〜8回トリガーされます。最適化後、アイデアを整理し、関数
を実行する前にメッセージが完全にレンダリングされているかどうかを判断するように変更しました。goBottom
メッセージが完全にレンダリングされたかどうかを判断するには、uni.createSelectorQuery()
この API を使用する必要があります。
// 在onReady钩子中调用goBottom
onReady() {
this.$nextTick(() => {
this.goBottom()
})
}
// 滚动到底部函数
goBottom() {
this.scrollView = '' // scrollview瞄点置空
this.$nextTick(async () => {
const res = await this.checkMsgIsRender('btm') // 检测最底部的消息是否完全渲染完毕
if(res) {
this.scrollView = 'bottom' // 瞄点至底部
} else {
this.goBottom()
}
})
}
// 检测消息是否渲染完毕
checkMsgIsRender(position) {
let msgID = ''
if(position === 'btm') {
// 底部
// 找到最底部的消息ID
msgID = xxxx
} else {
// 顶部
// 找到最顶部的消息ID
msgID = yyyy
}
// 返回一个Promise
return new Promise((resolve) => {
const query = uni.createSelectorQuery().in(this)
query.select('#id').boundingClientRect(data => {
// 存在data,且存在宽和高,视为渲染完毕
if(data && data.width && data.height) {
resolve(true)
} else {
resolve(false)
}
}).exec();
})
}
(2) プルダウンして詳細情報を読み込む 不正確な照準位置の問題
同様に、より多くのメッセージをロードするためにプルダウンするときに照準点が不正確になるという問題もあります。最初の解決策は、単純で失礼な 2 秒の遅延であり、ユーザーが長時間待機しすぎるという問題に直接つながります。 .
一番下までスクロールする練習を参照して、ブロガーは 1 つのインスタンスから推測し、メッセージが完全にレンダリングされているかどうかを判断して照準点のタイミングを決定し、照準点の正確な位置を確保します。
// 加载更多
async loadMore() {
await this.getMoreMsg() // 向服务器获取更多消息或者展示本地消息,该函数不展开
let location = async () => {
const res = await this.checkMsgIsRender('top') // 检测最顶部的消息是否完全渲染完毕
if(res) {
// 这里还需要找到需要瞄点过去的消息ID,zzzz
this.scrollView = zzzz // 瞄点到消息zzzz
} else {
location ()
}
}
this.scrollView = '' // scrollview瞄点置空
this.$nextTick(() => {
location ()
})
}
要約する
実際、インターネット上では以前から uniapp を批判する声がありましたが、正直なところ、1 つのコードで複数の端末に対して実行できる技術は非常に素晴らしいものですが、この技術は現時点では成熟していません (パフォーマンスの問題、互換性の問題、問題)。
uniapp がプロジェクトをどこまでリードしてくれるか、期待できます. もちろん、dcloud チームだけに頼ることはできません. 個人的なコードの作成も非常に重要です. がんばってください...