大前端代码重构之事件拦截iOS Flutter Vue示例分析

 更新时间:2023年04月04日 08:55:31   作者:SoaringHeart  
这篇文章主要为大家介绍了大前端代码重构之事件拦截iOS Flutter Vue示例分析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

一、需求来源

app需要支持实现游客模式,启动后直接进入首页菜单,但是进入二级页则自动调用登录页面。总结需求就是父视图拦截子视图的响应事件,思考之后发现在事件响应链上做拦截是最优方法。

二、iOS 事件拦截

1、使用示例

absorbing 属性为 true 时,会拦截子视图的事件。点击 button 时只会调用 absorbPointerView(绿色) 的响应方法。

absorbing 属性为 false 时,不会拦截子视图的事件。点击 button 时只会调用 button(蓝色)的响应方法。

import UIKit
import SnapKit
import SwiftExpand
/**
 通过递归遍历将所有子视图设置 isUserInteractionEnabled = false,则该视图可以响应事件;
 */
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,用来拦截它子视图事件。

import UIKit
class NNAbsorbPointerView: UIView {
    /// 是否拦截响应
    var absorbing = false;
    // **MARK: - 重写加载方法**
    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.判断点在不在当前控件上
        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 时,会拦截子视图的事件。点击蓝色 Container 时只会调用绿色 Container 的响应方法。

absorbing 属性为 false 时,不会拦截子视图的事件。点击蓝色 Container 时只会调用蓝色 Container 的响应方法。

//
//  AbsorbPointerDemo.dart
//  flutter_templet_project
//
//  Created by shang on 10/25/21 11:05 AM.
//  Copyright © 10/25/21 shang. All rights reserved.
//
// AbsorbPointer本身可以接收点击事件,消耗掉事件,而IgnorePointer无法接收点击事件,其下的控件可以接收到点击事件(不是子控件)。
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('不可点击:absorbing: ${_disable}'),
              Switch(
                value: _disable,
                onChanged: (bool val) {
                  _disable = val;
                  setState(() {});
                },
              )
            ],
          ),
          Divider(),
          _buildAbsorbPointerNew(absorbing: _disable),
          MaterialButton(
            color: Colors.lightBlue,
            onPressed: () => onClick('我是外面的按钮,不受影响'),
            child: Text('我是外面的按钮,不受影响'),
          ),
        ],
      ),
    );
  }
  /// 默认吸收事件,拦截事件
  _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 事件拦截

实现很简单,@click 添加修饰符 capture.stop 即可拦截子标签事件。

点击 button 时,父视图(绿色)会拦截响应事件。

<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 事件拦截

暂无

3、angular 事件拦截

暂无

最后、总结

1、iOS 还有一种办法,递归遍历所有子视图进行处理,让其不响应事件,事件自然会传递到 目标父视图,只是性能较差;

2、Flutter 中随组件类型不同有略微差距,使用时需要根据实际情况调试。

3、大前端思路都是通的,事件机制一端弄懂了就三端都差不多了,细微差距可以在实际开发中再思考总结。以后大前端加一门后端技能是时代趋势,Keep Learning!!!

AbsorbPointerDemo.dart

NNAbsorbPointerViewController.swift

EventIntercept.vue

以上就是大前端代码重构之事件拦截iOS Flutter Vue示例分析的详细内容,更多关于前端重构事件拦截iOS Flutter Vue的资料请关注脚本之家其它相关文章!

相关文章

  • vue3.x项目中,出现红色波浪线问题及解决

    vue3.x项目中,出现红色波浪线问题及解决

    这篇文章主要介绍了vue3.x项目中,出现红色波浪线问题及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-03-03
  • Vue express鉴权零基础入门

    Vue express鉴权零基础入门

    这篇文章主要介绍了详解express鉴权,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-02-02
  • Vue使用Echarts实现立体柱状图

    Vue使用Echarts实现立体柱状图

    这篇文章主要为大家详细介绍了Vue使用Echarts实现立体柱状图,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-09-09
  • vue组件入门知识全梳理

    vue组件入门知识全梳理

    这篇文章主要给大家介绍了关于vue组件入门知识的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-09-09
  • 详谈Object.defineProperty 及实现数据双向绑定

    详谈Object.defineProperty 及实现数据双向绑定

    这篇文章主要介绍了详谈Object.defineProperty 及实现数据双向绑定,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-07-07
  • Vue Echarts渲染数据导致残留脏数据的问题处理

    Vue Echarts渲染数据导致残留脏数据的问题处理

    这篇文章主要介绍了Vue Echarts渲染数据导致残留脏数据的问题处理,文中通过代码示例给大家讲解的非常详细,对大家的学习或工作有一定的帮助,需要的朋友可以参考下
    2024-08-08
  • VueRouter导航守卫用法详解

    VueRouter导航守卫用法详解

    这篇文章主要介绍了VueRouter导航守卫的详细用法以及分类介绍,有兴趣的朋友学习参考下吧。
    2017-12-12
  • Vue2.0学习系列之项目上线的方法步骤(图文)

    Vue2.0学习系列之项目上线的方法步骤(图文)

    这篇文章主要介绍了Vue2.0学习系列之项目上线的方法步骤(图文),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-09-09
  • vue中ref引用操作DOM元素的实现

    vue中ref引用操作DOM元素的实现

    本文主要介绍了vue中ref引用操作DOM元素的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-01-01
  • vue 使用el-table循环生成表格的过程

    vue 使用el-table循环生成表格的过程

    这篇文章主要介绍了vue 使用el-table循环生成表格的过程,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-04-04

最新评论