preface
Attention, ladies and gentlemen.
- This is a technical article
- The technique is only a foil, the most important is the technique. The goal is to make technology more accessible.
- The original title of this article was “Cute New Starter — A Traceless Pull-up Refresh Component.”
I can’t help it. The Nuggets are driving him to hell. In order to be seen by more people, no chi level.
I told him to do it”There is no trace
”
Oh, I’m really blushing. For the Michelin blind date tonight, I wore a very simple pink gauze dress, EMMM, and I put on a little light makeup. 5 minutes, 5 minutes to finish the makeup battle.
Ah. We can’t look down upon blind date, let alone resist it. What if I get lucky? What if it really is Mr.Right?
Blind date, from the first side began to fight. This guy looks really young. What’s his job?
“Little sister, Tiramisu.”
“Sweet puff, little sister.”
“Little sister, coconut water.”
I cracked. What’s the point of a little sister? I’m starving. Are we going to have a snack date for dinner? What is the most expensive Michelin restaurant? What about these meagre snacks? I’m bleeding inside, and I’m poking my choux with a fork.
I was furious. If this goes Dutch, I’m gonna lose my wallet. His cell phone called. He just clicked it off.
“Girl phone?”
“Ah? No, it isn’t.”
“Show me your phone.”
“Ah! This…… Isn’t it appropriate?”
“Am I beautiful?
“Well.. It’s pretty.”
“Am I lovely?”
“But…… Cute.”
“There’s one thing you want to do without a trace, okay?”
“What? What do you mean?”
“Do you sleep at night?”
“Ah…”
“Ah what ah, your ya quick mobile phone to see me.”
A meal of chickens and dogs. I took his phone, opened the Tmall App, select the home page.
“What can this traceless browsing do?”
I looked at the eyes have a full face of meng forced “difficult” children, I smile. I had an interview a few days ago. The interviewer was cruel and asked me such a question.
1. Let’s comb through what is “traceless browsing”
The other day, the interviewer asked me how to make a component that scrolls infinitely, not only smoothly but also so that the user doesn’t feel delayed loading. Oh my God, the interviewer is big, you can not say simple. For example: how to write a List component with high performance pull-up load and pull-down refresh?
But, I can’t. I can’t. I can write a List, I can write a high performance List, but what do you mean the user doesn’t feel lazy loading? It doesn’t sound like lazy loading either! I was confused, the interviewer looked at me poor (cute, innocent eyes. Because that’s what my girlfriends say. 😂), another way to ask me.
Q: Add page to render 10000 data, and the interface returns a limited amount of data, not more than 30 data. Do you do?
Oh, I kind of get it. In other words, the user can’t see more loading and loading, and then it just keeps sliding down.
Easy to say, understood, but still not…
“Hello, hello, little sister, you like to eat sweet crisp puffs, it happens to be sold on Tmall.”
It’s getting awkward. My mind was also pulled back, the blind date when the distraction. It’s okay. Good looks are good, cute is good, thick skin is unbeatable.
“Little brother, I see you are not old, as long as you tell me how to do no trace, I will give you one condition. What do you say, front brother?”
Alas. These days, you sell your dignity for work.
Listen to the sound of some front penis breaking his heart.
2. Where is the bottleneck
- User gesture interaction, because the user can quickly slide without thinking
- Visual area content changes frequently, can not use skeleton screen, at least not with ordinary skeleton screen. There can only be a first load from the skeleton screen to the actual content of the page.
- Interface request problem. Suppose each request time is
300ms
That should be finished10000
Time bit of an item10000/30 * 300 = 100000ms
. So, if100000ms
The time must be separated and separated into enough fine. I don’t believe users can slip10000
The data. - DOM rendering bottlenecks. As DOM numbers grow, it’s important not to render duplicate or unchanging data, or you’ll get stuck.
Here’s some pseudocode:
import React, { Fragment, useRef, useState,useEffect } from 'react';
import styles from './style.module.less';
let scrollTop = -1;
let touchX = 0;
let touchY = 0;
let time = 0;
let type = ' ';
let pullDownDoneBacking = false; // After the pull-down refresh is complete, the state is bouncing back to the original position
let init = true;
export default ((props) = > {
const [translateY, setTranslateY] = useState(0);
const [pullUpHide, setPullUpHide] = useState(0);
const [pullUpStatus, setPullUpStatus] = useState(0);
const [pullDownStatus, setPullDownStatus] = useState(0);
const wrapperEl = useRef(null);
const innerEl = useRef(null);
useEffect(() = > {
if (init) {
// Solve the ios and Android pages have their own scroll rebound
wrapperEl.current.addEventListener('touchmove', touchMoveHandle, { passive: false });
init = false;
}
// Recalculate pullUpHide when the content changes
const pullUpHide = innerEl.clientHeight < wrapperEl.current.clientHeight;
setPullUpHide(pullUpHide);
})
const scrollHandle = (e) = >{};const touchStartHandle = (e) = >{};const touchMoveHandle = (e) = >{};const touchEndHandle = (e) = >{};/* * This method can be called in the parent component via ref, and the component passing in the custom asynchronous function will handle the pull-down state based on the state of the asynchronous function, and automatically refresh * */
// Drop refresh
const pullDownRefresh = async (customAsyncFn) => {
};
// Pull up load
const pullUpLoad = async () => {
};
const { pullDownRefresh, pullUpLoad, children, noMore, backTop, noMoreTip = 'I'm at the end.' } = props;
return (
<Fragment>
<div className={styles.wrapper}
ref={wrapperEl}
onScroll={scrollHandle}
onTouchStart={touchStartHandle}
onTouchEnd={touchEndHandle}
>
<div
style={{
transform: `translateY(${translateY}px) `,transition: 'transform .3s ease'}} >
{
<div className={styles.pullDownTip}>PullDownStatus === 1 && 'refresh '} {pullDownStatus === 2 &&' refresh succeeded '} {pullDownStatus === 3 && 'refresh failed '}</div>
}
<div ref={innerEl}>
<Items />
</div>
<div>I'm really over it</div>
</div>
</div>
</Fragment>)})Copy the code
Let’s first consider the component schema
- Pull down refresh, animation is still needed.
(leaving tears that can’t make GIF 😭😭😭😭)
- The core, the Items
// We want to repeat data not repeat render
const Item = React.memo((info) = >{
return <div>
{info.price}
....
</div>
});
const Items = ((list) = >{
return list.map((item,index) = > <Item info={item}/>)})Copy the code
- Drop-down refresh does not change the list length. Modify only the data on the first page or the first 1-3 pages.
const pullDownRefresh = async() = > {// Do not delete any DOM from the previous 1-3 pages
const freshData = await API();
list[0] = freshData[0];
list[1] = freshData[1];
list[2] = freshData[2];
setList(list);
}
Copy the code
-
The API returns the number of pages, overwriting the array corresponding to the index data.
-
Call the interface API to retrieve data and leave it to the browser to do so at idle time. Never block user operations.
requestIdleCallback
requestIdleCallback(myWork); / / such as window requestIdleCallback is undefined, you can use the setTimeout simulation.
// A task queue
let tasks = [
function task1() {
// get data from page 1
API.fetchData(1);
console.log('Call interface API1')},function task2() {
// get the data on page 2
API.fetchData(2);
console.log('Call interface API2')},function task3() {
// get the data on page 3
API.fetchData(3);
console.log('Call interface API3')},... .function taskN(){
// get data from page N
API.fetchData(N);
console.log('Call interface API(N)')}]// Deadline is an object returned by requestIdleCallback
function myWork(deadline) {
console.log('Remaining time of current frame:${deadline.timeRemaining()}`)
// Check whether the remaining time of the current frame is greater than 0 && if there are any remaining tasks
if (deadline.timeRemaining() > 0 && tasks.length) {
// Do something here
const task = tasks.shift()
task()
}
// If there are still tasks that have not been executed, it is put into the next frame schedule to continue execution, similar to recursion
if (tasks.length) {
requestIdleCallback(myWork)
}
}
Copy the code
So, do we just need to hand over our task stack to requestIdleCallback?
- Finally, optimize your rendering components and remember to cache images.
END
“Little sister, how did you know I was a front-end?”
‘I don’t know!
“Then why do you ask me such a question?”
“The answer does not come up can happily end the meal!”
The atmosphere was once again deeply awkward.
“Oh, yes. Who knows you are really front-end, and then really spicy yao dishes.”
“That…… Can we still keep a wechat account?”
“How much is the meal? Go Dutch.”
“Little sister, I still can afford a meal…”
I moved the bill with my eyes. 3780.
So wow, it’s easy to love someone when you’re young, but don’t love too much. If you are a boy, please do not fall in love with me such an “old man”. Why, you ask? Well, I’ll give you a sentimental answer.
Young or don’t meet too amazing people, miss life.