大前端代碼重構(gòu)之事件攔截iOS?Flutter?Vue示例分析
一、需求來(lái)源
app需要支持實(shí)現(xiàn)游客模式,啟動(dòng)后直接進(jìn)入首頁(yè)菜單,但是進(jìn)入二級(jí)頁(yè)則自動(dòng)調(diào)用登錄頁(yè)面??偨Y(jié)需求就是父視圖攔截子視圖的響應(yīng)事件,思考之后發(fā)現(xiàn)在事件響應(yīng)鏈上做攔截是最優(yōu)方法。
二、iOS 事件攔截
1、使用示例
absorbing 屬性為 true 時(shí),會(huì)攔截子視圖的事件。點(diǎn)擊 button 時(shí)只會(huì)調(diào)用 absorbPointerView(綠色) 的響應(yīng)方法。
absorbing 屬性為 false 時(shí),不會(huì)攔截子視圖的事件。點(diǎn)擊 button 時(shí)只會(huì)調(diào)用 button(藍(lán)色)的響應(yīng)方法。
import UIKit import SnapKit import SwiftExpand /** 通過(guò)遞歸遍歷將所有子視圖設(shè)置 isUserInteractionEnabled = false,則該視圖可以響應(yīng)事件; */ class NNAbsorbPointerViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. edgesForExtendedLayout = [] view.backgroundColor = .white title = "NNAbsorbPointerView" absorbPointerView.addSubview(button) view.addSubview(absorbPointerView) // view.recursion{ e in // e.isUserInteractionEnabled = false; // } view.addGestureTap { reco in debugPrint("\(Date()):reco.view") } } override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() let edge = UIEdgeInsets(all: 50) button.snp.makeConstraints { make in make.edges.equalToSuperview().inset(edge) } absorbPointerView.snp.makeConstraints { make in make.edges.equalToSuperview().inset(edge) } } lazy var absorbPointerView: NNAbsorbPointerView = { let view = NNAbsorbPointerView(frame: .zero); view.absorbing = true; view.backgroundColor = .green; view.addGestureTap { reco in debugPrint("\(Date()):NNAbsorbPointerView") } return view }() lazy var button: UIButton = { let view = UIButton(type: .custom); view.setTitle("UIButton", for: .normal) view.setTitleColor(.white, for: .normal) view.backgroundColor = .blue; view.addGestureTap { reco in debugPrint("\(Date()):button") } return view }() }
2、自定義視圖 NNAbsorbPointerView,用來(lái)攔截它子視圖事件。
import UIKit class NNAbsorbPointerView: UIView { /// 是否攔截響應(yīng) var absorbing = false; // **MARK: - 重寫(xiě)加載方法** override init(frame: CGRect) { super.init(frame: frame); } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func layoutSubviews() { super.layoutSubviews() } override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { if absorbing { return self } // 1.判斷能不能處理事件 if isUserInteractionEnabled == false, isHidden, alpha <= 0.01 { return nil } // 2.判斷點(diǎn)在不在當(dāng)前控件上 if self.point(inside: point, with: event) == false { return nil; } for subView in subviews.reversed() { let subPoint = self.convert(point, to: subView); if let targetView = subView.hitTest(subPoint, with: event) { return targetView; } } return self } // **MARK: - 私有方法** }
三、Flutter 事件攔截
1、使用示例
absorbing 屬性為 true 時(shí),會(huì)攔截子視圖的事件。點(diǎn)擊藍(lán)色 Container 時(shí)只會(huì)調(diào)用綠色 Container 的響應(yīng)方法。
absorbing 屬性為 false 時(shí),不會(huì)攔截子視圖的事件。點(diǎn)擊藍(lán)色 Container 時(shí)只會(huì)調(diào)用藍(lán)色 Container 的響應(yīng)方法。
// // AbsorbPointerDemo.dart // flutter_templet_project // // Created by shang on 10/25/21 11:05 AM. // Copyright ? 10/25/21 shang. All rights reserved. // // AbsorbPointer本身可以接收點(diǎn)擊事件,消耗掉事件,而IgnorePointer無(wú)法接收點(diǎn)擊事件,其下的控件可以接收到點(diǎn)擊事件(不是子控件)。 import "package:flutter/material.dart"; import 'package:flutter_templet_project/extension/ddlog.dart'; class AbsorbPointerDemo extends StatefulWidget { const AbsorbPointerDemo({Key? key}) : super(key: key); @override _AbsorbPointerDemoState createState() => _AbsorbPointerDemoState(); } class _AbsorbPointerDemoState extends State<AbsorbPointerDemo> { bool _disable = false; bool _switchValue = false; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Absorbpointer'), centerTitle: true, elevation: 0, ), body: Column( mainAxisAlignment: MainAxisAlignment.start, children: <Widget>[ Row( children: <Widget>[ Text('不可點(diǎn)擊:absorbing: ${_disable}'), Switch( value: _disable, onChanged: (bool val) { _disable = val; setState(() {}); }, ) ], ), Divider(), _buildAbsorbPointerNew(absorbing: _disable), MaterialButton( color: Colors.lightBlue, onPressed: () => onClick('我是外面的按鈕,不受影響'), child: Text('我是外面的按鈕,不受影響'), ), ], ), ); } /// 默認(rèn)吸收事件,攔截事件 _buildAbsorbPointerNew({bool absorbing = true}) { return InkWell( onTap: () => onClick("outside"), child: Container( color: Colors.green, padding: EdgeInsets.all(20), child: AbsorbPointer( absorbing: absorbing, child: InkWell( onTap: () => onClick("inside"), child: Container( color: Colors.blue, width: 200.0, height: 100.0, alignment: Alignment.center, child: Text("Container"), ), ), ), ), ); } onClick(String msg) { debugPrint(msg); } }
四、Web 事件攔截
1、Vue 事件攔截
實(shí)現(xiàn)很簡(jiǎn)單,@click 添加修飾符 capture.stop 即可攔截子標(biāo)簽事件。
點(diǎn)擊 button 時(shí),父視圖(綠色)會(huì)攔截響應(yīng)事件。
<template> <h2>{{ $route.meta.title }}</h2> <!-- <h2>{{ JSON.stringify(route) }}</h2> --> <div class="page" @click.capture.stop="doThis"> <button @click="onClick">button</button> </div> </template> <script setup> import { getCurrentInstance, ref, reactive, watch, onMounted, } from 'vue'; import { useRouter, useRoute } from 'vue-router'; const router = useRouter(); const route = useRoute(); const doThis = () => { console.log(`${new Date()}: doThis`); }; const onClick = () => { console.log(`${new Date()}: onClick`); }; </script> <style scoped lang='scss'> .page{ background-color: green; } </style>
2、react 事件攔截
暫無(wú)
3、angular 事件攔截
暫無(wú)
最后、總結(jié)
1、iOS 還有一種辦法,遞歸遍歷所有子視圖進(jìn)行處理,讓其不響應(yīng)事件,事件自然會(huì)傳遞到 目標(biāo)父視圖,只是性能較差;
2、Flutter 中隨組件類(lèi)型不同有略微差距,使用時(shí)需要根據(jù)實(shí)際情況調(diào)試。
3、大前端思路都是通的,事件機(jī)制一端弄懂了就三端都差不多了,細(xì)微差距可以在實(shí)際開(kāi)發(fā)中再思考總結(jié)。以后大前端加一門(mén)后端技能是時(shí)代趨勢(shì),Keep Learning?。。?/p>
NNAbsorbPointerViewController.swift
以上就是大前端代碼重構(gòu)之事件攔截iOS Flutter Vue示例分析的詳細(xì)內(nèi)容,更多關(guān)于前端重構(gòu)事件攔截iOS Flutter Vue的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
vue實(shí)現(xiàn)將圖像文件轉(zhuǎn)換為base64
這篇文章主要介紹了vue實(shí)現(xiàn)將圖像文件轉(zhuǎn)換為base64,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-02-02vue.js集成echarts時(shí)遇到的一些問(wèn)題總結(jié)
這篇文章主要給大家總結(jié)介紹了關(guān)于vue.js集成echarts遇到的一些問(wèn)題,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04基于vue-resource jsonp跨域問(wèn)題的解決方法
下面小編就為大家分享一篇基于vue-resource jsonp跨域問(wèn)題的解決方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-02-02vue-router history模式服務(wù)器端配置過(guò)程記錄
vue路由有hash和history兩種模式,這篇文章主要給大家介紹了關(guān)于vue-router history模式服務(wù)器端配置的相關(guān)資料,需要的朋友可以參考下2021-06-06ruoyi-vue3 集成aj-captcha實(shí)現(xiàn)滑塊、文字點(diǎn)選驗(yàn)證碼功能
這篇文章主要介紹了 ruoyi-vue3 集成aj-captcha實(shí)現(xiàn)滑塊、文字點(diǎn)選驗(yàn)證碼,本文基于后端RuoYi-Vue 3.8.7 和 前端 RuoYi-Vue3 3.8.7,集成以AJ-Captcha文字點(diǎn)選驗(yàn)證碼為例,不需要鍵盤(pán)手動(dòng)輸入,極大優(yōu)化了傳統(tǒng)驗(yàn)證碼用戶體驗(yàn)不佳的問(wèn)題,感興趣的朋友一起看看吧2023-12-12vue使用element-resize-detector監(jiān)聽(tīng)元素寬度變化方式
這篇文章主要介紹了vue使用element-resize-detector監(jiān)聽(tīng)元素寬度變化方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12vue實(shí)現(xiàn)簡(jiǎn)單的登錄彈出框
這篇文章主要為大家詳細(xì)介紹了vue實(shí)現(xiàn)簡(jiǎn)單的登錄彈出框,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-10-10vue阻止頁(yè)面回退的實(shí)現(xiàn)方法(瀏覽器適用)
這篇文章主要介紹了vue阻止頁(yè)面回退的實(shí)現(xiàn)方法(瀏覽器適用),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-05-05