站長資訊網(wǎng)
        最全最豐富的資訊網(wǎng)站

        react怎么實現(xiàn)滑動

        react實現(xiàn)滑動的方法:1、在onTouchStart事件找到touches,根據(jù)identifier中記錄新的touch出現(xiàn);2、在onTouchMove事件中根據(jù)identifier來記錄每個touch經(jīng)過的點的坐標;3、在onTouchEnd事件中,找到結(jié)束的touch事件,然后通過結(jié)束的touch事件劃過的點來計算要執(zhí)行的手勢即可。

        react怎么實現(xiàn)滑動

        本教程操作環(huán)境:Windows10系統(tǒng)、react18.0.0版、Dell G3電腦。

        react怎么實現(xiàn)滑動?

        react 實現(xiàn)左右滑動效果

        React 中滑動手勢的實現(xiàn)

        react怎么實現(xiàn)滑動

        最近做了一點關(guān)于react在移動端滑動翻頁的功能。

        開始搜索了一下,發(fā)現(xiàn)居然沒找到合適的庫,唯一找到了名字叫react-touch的庫,一看,前端世界四五百star===自己擼,而且似乎也不是想要的功能,算了自己寫點吧。

        看了下原理,基本就是配合onTouchStart,onTouchMove和onTouchEnd這三個事件,來記錄滑動過的點,然后來計算手勢。

        顯然對于多點觸摸,需要找到每個點觸摸的路徑,所以有如下幾步:

        • 在onTouchStart事件找到touches,根據(jù)identifier中記錄新的touch出現(xiàn)。

        • 在onTouchMove事件中根據(jù)identifier來記錄每個touch經(jīng)過的點的坐標。

        • 在onTouchEnd事件中,找到結(jié)束的touch事件,然后通過結(jié)束的touch事件劃過的點來計算要執(zhí)行的手勢。

        對于我來說我只是想要上下滑動的功能那么我就只關(guān)注單點觸摸的情況。

        接下來準備上代碼。哦,不對,首先要想想要怎么封裝。開始自問自答:

        我想用一個單例模式。

        是不是使用有點太麻煩了,還要先實例化一下?

        那用靜態(tài)類?

        都js了還要啥靜態(tài)類,輸出個字典完事。

        那好吧,開始擼吧。

        數(shù)據(jù)部分

        const touchData = { touching: false, trace: [] }; // 單點觸摸,所以只要當前在觸摸中,就可以把劃過的點記錄到trace中了 function* idGenerator() {   let start = 0;   while (true) {     yield start;     start += 1;   } } //這個生成器用來生成不同事件回調(diào)的id,這樣我們可以注冊不同的回調(diào),然后在不需要的時候刪掉。 const callbacks = {   onSlideUpPage: { generator: idGenerator(), callbacks: {} },   onSlideDownPage: { generator: idGenerator(), callbacks: {} } }; //存儲向上、下?lián)Q頁的回調(diào)函數(shù)
        登錄后復制

        記錄觸摸部分

        這里的事件處理的是react的合成事件,并非原生事件。

        function onTouchStart(evt) {   if (evt.touches.length !== 1) {     touchData.touching = false;     touchData.trace = [];     return;   }   touchData.touching = true;   touchData.trace = [{ x: evt.touches[0].screenX, y: evt.touches[0].screenY }]; } //在onTouchStart事件,如果是多點觸摸直接清空所有數(shù)據(jù)。如果是單點觸摸,記錄第一個點,并設(shè)置狀態(tài) function onTouchMove(evt) {   if (!touchData.touching) return;   touchData.trace.push({     x: evt.touches[0].screenX,     y: evt.touches[0].screenY   }); } //如果在單點觸摸過程中,持續(xù)記錄觸摸的位置。 function onTouchEnd() {   if (!touchData.touching) return;   let trace = touchData.trace;   touchData.touching = false;   touchData.trace = [];   handleTouch(trace);  //判斷touch類型并調(diào)用適當回調(diào) } //在觸摸結(jié)束事件,中調(diào)用handleTouch函數(shù)來處理手勢判斷邏輯并執(zhí)行回調(diào)
        登錄后復制

        handleTouch函數(shù)

        function handleTouch(trace) {   let start = trace[0];   let end = trace[trace.length - 1];   if (end.y - start.y > 200) {     Object.keys(callbacks.onSlideUpPage.callbacks).map(key =>       callbacks.onSlideUpPage.callbacks[key]()     );      // 向上翻頁   } else if (start.y - end.y > 200) {     Object.keys(callbacks.onSlideDownPage.callbacks).map(key =>       callbacks.onSlideDownPage.callbacks[key]()     );     // 向下翻頁   } }
        登錄后復制

        在這里我只判斷了向上向下翻頁兩個事件,如果事件達成,則會調(diào)用所有注冊到該事件的回調(diào)。如果有多個回調(diào)可按照需求對回調(diào)的執(zhí)行順序進行調(diào)整。這里應(yīng)該是無序的。

        接口部分

        function addSlideUpPage(f) {   let key = callbacks.onSlideUpPage.generator.next().value;   callbacks.onSlideUpPage.callbacks[key] = f;   return key; } //注冊向上滑動回調(diào)并返回回調(diào)id function addSlideDownPage(f) {   let key = callbacks.onSlideDownPage.generator.next().value;   callbacks.onSlideDownPage.callbacks[key] = f;   return key; } //注冊向下滑動回調(diào)并返回回調(diào)id function removeSlideUpPage(key) {   delete callbacks.onSlideUpPage.callbacks[key]; } //使用回調(diào)id刪除向上滑動回調(diào) function removeSlideDownPage(key) {   delete callbacks.onSlideDownPage.callbacks[key]; } //使用回調(diào)id刪除向下滑動回調(diào) export default {   onTouchEnd,   onTouchMove,   onTouchStart,   addSlideDownPage,   addSlideUpPage,   removeSlideDownPage,   removeSlideUpPage }; //輸出所有接口函數(shù)
        登錄后復制

        這沒啥說的,就是折麼簡單粗暴。接下來,就在react中使用吧!

        在next.js中使用

        我使用的next.js+create-next-app。在pages目錄下的_app.js文件中綁定所有touch事件。

        //pages/_app.js import App, { Container } from "next/app"; import React from "react"; import withReduxStore from "../redux/with-redux-store"; import { Provider } from "react-redux"; import touch from "../components/touch";  class MyApp extends App {   render() {     const { Component, pageProps, reduxStore } = this.props;     return (       <Container>         <Provider store={reduxStore}>           <div             onTouchEnd={touch.onTouchEnd}             onTouchStart={touch.onTouchStart}             onTouchMove={touch.onTouchMove}           >             <Component {...pageProps} />           </div>  { // 將所有導出的touch事件綁定在最外層的div上 // 這樣就可以全局注冊事件了 }         </Provider>       </Container>     );   } }  export default withReduxStore(MyApp);
        登錄后復制

        接下來看看如何使用。

        import React, {useEffect} from "react"; import touch from "../touch";  const Example = () => {   useEffect(() => {     let key = touch.addSlideDownPage(() => {       console.log("try to slideDownPage!!")     });     return () => {       touch.removeSlideDownPage(key)       // 用完別忘了刪除事件     };   }, []);   return (     <div>This is an example!!</div>   ); };
        登錄后復制

        在原生react中使用

        這個項目使用create-react-app生成的

        //src/App.js import React from 'react'; import logo from './logo.svg'; import './App.css'; import touch from "./components/touch";  function App() {   return (     <div className="App"       onTouchEnd={touch.onTouchEnd}       onTouchStart={touch.onTouchStart}       onTouchMove={touch.onTouchMove}     >       <header className="App-header">         <img src={logo} className="App-logo" alt="logo" />         <p>           Edit <code>src/App.js</code> and save to reload.         </p>         <a           className="App-link"           href="https://reactjs.org"           target="_blank"           rel="noopener noreferrer"         >           Learn React         </a>       </header>     </div>   ); }
        登錄后復制

        結(jié)語

        如果真的有人仔細看了代碼,可能會有個問題,這個touch.js里的內(nèi)容除了使用了react的合成事件,然后就沒react什么事了,好像不太常規(guī)。

        的確是這樣,就沒關(guān)react什么事了。解釋就是這些數(shù)據(jù)不用通過react的state或者redux的state太傳遞,一來是在性能上,一更新redux或者react的state就會觸發(fā)react的重新渲染,沒有必要,二就是希望可以全局使用這些接口,所以就并沒有借助react的機制。其實這就像是react所說的uncontrolled components。

        最后附上完整的touch.js

        //touch.js const touchData = { touching: false, trace: [] };  function* idGenerator() {   let start = 0;   while (true) {     yield start;     start += 1;   } }  const callbacks = {   onSlideUpPage: { generator: idGenerator(), callbacks: {} },   onSlideDownPage: { generator: idGenerator(), callbacks: {} } };  function onTouchStart(evt) {   if (evt.touches.length !== 1) {     touchData.touching = false;     touchData.trace = [];     return;   }   touchData.touching = true;   touchData.trace = [{ x: evt.touches[0].screenX, y: evt.touches[0].screenY }]; } function onTouchMove(evt) {   if (!touchData.touching) return;   touchData.trace.push({     x: evt.touches[0].screenX,     y: evt.touches[0].screenY   }); } function onTouchEnd() {   if (!touchData.touching) return;   let trace = touchData.trace;   touchData.touching = false;   touchData.trace = [];   handleTouch(trace); } function handleTouch(trace) {   let start = trace[0];   let end = trace[trace.length - 1];   if (end.y - start.y > 200) {     Object.keys(callbacks.onSlideUpPage.callbacks).map(key =>       callbacks.onSlideUpPage.callbacks[key]()     );   } else if (start.y - end.y > 200) {     Object.keys(callbacks.onSlideDownPage.callbacks).map(key =>       callbacks.onSlideDownPage.callbacks[key]()     );   } } function addSlideUpPage(f) {   let key = callbacks.onSlideUpPage.generator.next().value;   callbacks.onSlideUpPage.callbacks[key] = f;   return key; } function addSlideDownPage(f) {   let key = callbacks.onSlideDownPage.generator.next().value;   callbacks.onSlideDownPage.callbacks[key] = f;   return key; } function removeSlideUpPage(key) {   delete callbacks.onSlideUpPage.callbacks[key]; } function removeSlideDownPage(key) {   delete callbacks.onSlideDownPage.callbacks[key]; } export default {   onTouchEnd,   onTouchMove,   onTouchStart,   addSlideDownPage,   addSlideUpPage,   removeSlideDownPage,   removeSlideUpPage };
        登錄后復制

        推薦學習:《react視頻教程》

        贊(0)
        分享到: 更多 (0)
        網(wǎng)站地圖   滬ICP備18035694號-2    滬公網(wǎng)安備31011702889846號
        主站蜘蛛池模板: 亚洲欧美国产精品第1页| 精品无码一区二区三区爱欲| 亚洲第一极品精品无码久久| 99久久免费只有精品国产| 亚洲欧美精品AAAAAA片| 精品人妻少妇一区二区三区在线| 久久91精品国产91久久户| 久久久久久亚洲精品成人| 久久夜色撩人精品国产小说| 办公室久久精品| 国产精品视频第一页| 久久99精品久久久久久久不卡| 亚洲国产婷婷综合在线精品| 精品熟女少妇aⅴ免费久久| 2023国产精品自拍| 2021久久精品国产99国产精品| 亚洲AV成人精品网站在线播放| 日韩欧美一区二区三区中文精品 | 999久久久无码国产精品| 精品亚洲麻豆1区2区3区| 十八18禁国产精品www| 色婷婷久久久SWAG精品| 久久91这里精品国产2020| 国产精品成人h片在线| 国产精品粉嫩美女在线观看| 秋霞久久国产精品电影院| 精品999在线| 99久久精品毛片免费播放| 国产精品99精品久久免费| 精品国产福利在线观看| 精品亚洲成AV人在线观看| 久久er99热精品一区二区| 久久水蜜桃亚洲av无码精品麻豆| 亚洲国产精品无码成人片久久| 一本一本久久A久久综合精品 | 午夜精品射精入后重之免费观看| 亚洲乱码精品久久久久..| 亚洲精品无码专区在线在线播放 | 久久99精品国产99久久6男男| 国产精品高清视亚洲精品| 国产精品亚洲片夜色在线|