成人怡红院-成人怡红院视频在线观看-成人影视大全-成人影院203nnxyz-美女毛片在线看-美女免费黄

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

react怎么實(shí)現(xiàn)滑動(dòng)

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

react怎么實(shí)現(xiàn)滑動(dòng)

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

react怎么實(shí)現(xiàn)滑動(dòng)?

react 實(shí)現(xiàn)左右滑動(dòng)效果

React 中滑動(dòng)手勢(shì)的實(shí)現(xiàn)

react怎么實(shí)現(xiàn)滑動(dòng)

最近做了一點(diǎn)關(guān)于react在移動(dòng)端滑動(dòng)翻頁(yè)的功能。

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

看了下原理,基本就是配合onTouchStart,onTouchMove和onTouchEnd這三個(gè)事件,來(lái)記錄滑動(dòng)過(guò)的點(diǎn),然后來(lái)計(jì)算手勢(shì)。

顯然對(duì)于多點(diǎn)觸摸,需要找到每個(gè)點(diǎn)觸摸的路徑,所以有如下幾步:

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

  • 在onTouchMove事件中根據(jù)identifier來(lái)記錄每個(gè)touch經(jīng)過(guò)的點(diǎn)的坐標(biāo)。

  • 在onTouchEnd事件中,找到結(jié)束的touch事件,然后通過(guò)結(jié)束的touch事件劃過(guò)的點(diǎn)來(lái)計(jì)算要執(zhí)行的手勢(shì)。

對(duì)于我來(lái)說(shuō)我只是想要上下滑動(dòng)的功能那么我就只關(guān)注單點(diǎn)觸摸的情況。

接下來(lái)準(zhǔn)備上代碼。哦,不對(duì),首先要想想要怎么封裝。開(kāi)始自問(wèn)自答:

我想用一個(gè)單例模式。

是不是使用有點(diǎn)太麻煩了,還要先實(shí)例化一下?

那用靜態(tài)類(lèi)?

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

那好吧,開(kāi)始擼吧。

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

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

記錄觸摸部分

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

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]()     );      // 向上翻頁(yè)   } else if (start.y - end.y > 200) {     Object.keys(callbacks.onSlideDownPage.callbacks).map(key =>       callbacks.onSlideDownPage.callbacks[key]()     );     // 向下翻頁(yè)   } }
登錄后復(fù)制

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

接口部分

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

這沒(méi)啥說(shuō)的,就是折麼簡(jiǎn)單粗暴。接下來(lái),就在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>  { // 將所有導(dǎo)出的touch事件綁定在最外層的div上 // 這樣就可以全局注冊(cè)事件了 }         </Provider>       </Container>     );   } }  export default withReduxStore(MyApp);
登錄后復(fù)制

接下來(lái)看看如何使用。

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>   ); };
登錄后復(fù)制

在原生react中使用

這個(gè)項(xiàng)目使用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>   ); }
登錄后復(fù)制

結(jié)語(yǔ)

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

的確是這樣,就沒(méi)關(guān)react什么事了。解釋就是這些數(shù)據(jù)不用通過(guò)react的state或者redux的state太傳遞,一來(lái)是在性能上,一更新redux或者react的state就會(huì)觸發(fā)react的重新渲染,沒(méi)有必要,二就是希望可以全局使用這些接口,所以就并沒(méi)有借助react的機(jī)制。其實(shí)這就像是react所說(shuō)的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 };
登錄后復(fù)制

推薦學(xué)習(xí):《react視頻教程》

贊(0)
分享到: 更多 (0)
?
網(wǎng)站地圖   滬ICP備18035694號(hào)-2    滬公網(wǎng)安備31011702889846號(hào)
国产ZLJZLJZLJZLJ| 国产未成女一区二区三区| 好了AV四色综合无码久久| 久久国产精品无码网站| 人妻厨房出轨上司HD院线| 玩弄人妻少妇500系列视频| 亚洲一区二区三区国产精华液| XX性欧美肥妇精品久久久久久| 国产精品久久自在自线| 久久亚洲人成网站| 色天天躁夜夜躁天干天干 | 国99精品无码一区二区三区| 精品无人区一线二线三线区别| 秋霞网一区二区三区| 亚洲av网站在线| A级毛片免费网站| 国产熟女一区二区三区四区五区| 免费 成 人 黄 色 网站69| 挺进朋友人妻的身体里| 中国CHINAGARY武警网站| 国产成人啪精品视频免费软件| 久久精品国产精品亚洲精品| 日韩AV无码免费播放| 亚洲色婷婷六月亚洲婷婷6月 | www.丁香五月| 激情欧美日韩一区二区| 日本JAPANESE丰满白浆| 亚洲色欲综合天堂亚洲 | 无码播放一区二区三区| 18成禁人视频免费网站| 国产亚洲成AⅤ人片在线观看蜜桃 国产亚洲成AⅤ人片在线观看麻豆 | 99热最新成人国产精品| 国内ZOOM人与ZOOM| 日本丰满熟妇×××××乱| 亚洲熟妇另类AV老熟女| 国产成人AV一区二区三区不卡| 麻花传媒MD0076在线入口| 无码日韩人妻AV一区免费| AV无码爆乳护士在线播放| 激情内射亚洲一区二区三区爱妻 | 日本极品人妻VIDEOSSEX| 亚洲色欲色欲WWW成人网| 国产成人久久精品一区二区三区| 妺妺窝人体色www九色| 性色AV无码久久一区二区三区| JIZZJIZZ日本护士视频| 久久久久波多野结衣高潮| 无码人妻熟妇av又大又粗浪潮| H系列高强无收缩灌浆料黄文| 九九久久精品无码专区| 无码人妻出轨与黑人中文字幕| BBWBBW肥妇BBWBBW| 久久久久亚洲AV无码六十路老熟| 无人高清影视在线观看| 成年网站未满十八禁在线观看| 老头猛挺进小雯的体内视频| 亚洲AV成人在线播放| 俄罗斯人和欧洲人长相区别| 欧美黑人极品猛少妇色XXXXⅩ| 亚洲午夜性春猛交XXXX亚训| 好爽又高潮了毛片| 人妻互换免费中文字幕| 玩弄人妻热妇性色Av少妇| 把腿张开老子cao烂你动态图| 久久久亚洲欧洲日产国码是AV| 无码一区二区三区AⅤ免费蜜桃视| 被喂春药蹂躏的欲仙欲死视频| 脔到她哭H粗话H好爽五星视频 | 六十路垂乳熟年交尾| 亚洲成AV人片在线观看无| 国产成人无码精品久久久免费| 人妻AV综合天堂一区| 最新的国产成人精品2022| 久久精品国产亚洲AV蜜臀色欲| 无码人妻精品一区二区三区99不 | 国精产品一区二区三区有限公司| 免费看漫画在线成人漫画| 超碰人人看人人2017| 精品无人区麻豆乱码无限制| 无码专区国产精品视频| 大爷你的太大了我| 人妻18毛片A级毛片免费看| 中文字幕无码一区二区免费| 久久精品亚洲精品国产色婷| 亚洲AV专区无码观看精品天堂 | YY111111少妇无码理论片| 内射干少妇亚洲69XXX| 用舌头去添高潮无码AV在线观看| 精品国色天香一卡2卡3卡 | 亚洲中文字幕无码AV永久| 国色天香卡一卡2卡3卡4卡5| 无码专区一VA亚洲V天堂| 国产精品国产三级欧美二区| 天天看高清影视在线观看| 吃了继兄开的药我做的梦更| 日本无人区码一码二码三码四码 | 丰满人妻妇伦又伦精品国产 | 日本高清乱理伦片中文字幕| Z0OZO0人善之交另类| 青草国产超碰人人添人人碱| CHINESE熟女老女人HD视频| 欧美精产国品一二三产品工艺| 1000部又爽又黄无遮挡的视频| 老熟女太熟了95AV| 中国老熟女XXXⅩ全部| 免费人成网站在线观看欧美| 7777奇米四色眼影| 欧美嫩FREEXXXHD| TPU色母能与PA6色母通用吗| 人妻无码中文字幕免费视频蜜桃| 啊别插了视频高清在线观看| 日本50岁丰满熟妇XXXX| 大陆极品少妇内射AAAAA| 熟妇与小伙子MATUR老熟妇E| 国产精品视频一区二区| 性亚洲VIDEOFREE高清极| 好男人影视官网在线WWW| 亚洲人ⅤSAⅤ国产精品| 久久久久亚洲AV成人网| 自慰无码一区二区三区| 欧美婷婷丁香五月社区| 成人免费A级毛片无码片在线播放 成人免费A级毛片无码片2022 | 激情综合婷婷丁香五月俺来也 | 岳两腿之间白嫩的小缝| 免费黄色网站久久精品| MM1313亚洲精品无码又大又| 日韩欧美成人免费观看| 国产成人一区二区精品视频| 亚洲av成人一区| 久久久WWW成人免费看片| 中文字幕一本性无码| 人妻无码ΑV中文字幕琪琪布| 丰满人妻熟妇乱又伦精品| 西西人体444www大胆无码视频| 狠狠色噜噜狠狠狠狠AV不卡| 要灬要灬再深点受不了好舒服| 男生把手放进我内裤揉摸好爽| 被学长抱进小树林C个爽| 无码成人亚洲AV污污污在线看| 果冻传媒亚洲区二期| 永久AV狼友网站在线观看| 欧美亚洲一区二区三区| 高清国产亚洲精品自在久久| 亚洲AV无码国产精品久久| 久久久一本精品99久久精品| A级国产乱理伦片在线观看| 少妇人妻偷人精系列| 哈昂~哈昂够了太多了男男| 再深点灬舒服灬太大了添视频软件| 欧美又粗又大XXXⅩBBBB| 国产成人午夜高潮毛片| 亚洲情综合五月天| 欧亚专线欧洲S码W MY| 国产高潮刺激叫喊视频| 亚洲日韩国产一区二区蜜桃| 欧美精品色婷婷五月综合| 国产成人无码免费看片软件| 亚洲日韩AV无码中文字幕美国| 欧美军警GAY巨大粗长| 国产精品福利一区二区| 亚洲资源AV无码日韩AV无码| 人妻无码ΑV中文字幕琪琪布 | 国产精品天干天干在线观看澳门| 亚洲一区二区三区蜜桃| 人妻熟女AⅤ中文字幕在线看| 国产日产欧洲系列| 在线日产精品一区| 舌头伸进去添的我好爽高视频| 精品一区二区久久久久久久网站| HEYZO无码综合国产精品| 无遮高潮国产免费观看| 毛片无遮挡高清免费| 国产69精品久久久久久妇女迅雷| 亚洲婷婷五月色香综合缴情| 日本极品少妇XXXX| 精品国产免费第一区二区三区 | 老汉扛起娇妻玉腿进入| 粗大的内捧猛烈进出小视频| 亚洲人成无码网站| 日韩免费一区二区三区高清| 精品无码久久久久久午夜| YY111111人妻影院| 亚洲精品无码不卡| 日韩免费无码成人久久久久久片| 精品日产A一卡2卡三卡4卡乱| 不屈的儿媳妇电视剧汉语版| 亚洲日韩国产精品第一页一区 | 久久精品国产清高在天天线| 成人免费A级毛片无码片在线播放| 亚洲色精品三区二区一区 | 国产美女在线精品免费观看| 666西方大但人文艺术| 亚洲AV涩涩涩成人网站在线播放| 欧美交换配乱吟粗大视频| 极品教师第二季免费观看| 成人3D动漫一区二区三区| 亚洲中文无码A∨在线观看| 四川小少妇BBAABBAA| 男生女生一起相差差差30| 好大好深好猛好爽视频免费|