大前端代碼重構(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?。?!
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)文章
基于Vue2-Calendar改進(jìn)的日歷組件(含中文使用說(shuō)明)
這篇文章主要介紹了基于Vue2-Calendar改進(jìn)的日歷組件(含中文使用說(shuō)明)的相關(guān)知識(shí),非常不錯(cuò),具有一定的參考借鑒價(jià)值 ,需要的朋友可以參考下2019-04-04
vue實(shí)現(xiàn)可移動(dòng)的懸浮按鈕
這篇文章主要為大家詳細(xì)介紹了vue實(shí)現(xiàn)可移動(dòng)的懸浮按鈕,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-03-03
解決vue?eslint開(kāi)發(fā)嚴(yán)格模式警告錯(cuò)誤的問(wèn)題
這篇文章主要介紹了解決vue?eslint開(kāi)發(fā)嚴(yán)格模式警告錯(cuò)誤的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-04-04
Vue系列:通過(guò)vue-router如何傳遞參數(shù)示例
本篇文章主要介紹了Vue系列:通過(guò)vue-router如何傳遞參數(shù)示例,具有一定的參考價(jià)值,有興趣的可以了解一下。2017-01-01
Vue多組件倉(cāng)庫(kù)開(kāi)發(fā)與發(fā)布詳解
這篇文章主要介紹了Vue多組件倉(cāng)庫(kù)開(kāi)發(fā)與發(fā)布詳解,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-02-02
vue中filters 傳入兩個(gè)參數(shù) / 使用兩個(gè)filters的實(shí)現(xiàn)方法
這篇文章主要介紹了vue中filters 傳入兩個(gè)參數(shù) / 使用兩個(gè)filters的實(shí)現(xiàn)方法,文中給大家提到了Vue 中的 filter 帶多參的使用方法,需要的朋友可以參考下2019-07-07

