前端知识点(下)

三、计算机网络与其他知识篇

1.HTTP与HTTPS

HTTP:客户端与服务器之间数据传输的格式规范,表示“超文本传输协议”。
HTTPS:在HTTP与TCP之间添加的安全协议层。
默认端口号:HTTP:80,HTTPS:443。
传输方式:http是明文传输,https则是具有安全性的ssl加密传输协议。
连接方式:http的是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。
————————————————

2.TCP与UDP的区别

  1. TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接。
  2. TCP面向字节流,实际上是TCP把数据看成一连串无结构的字节流;UDP是面向报文的
  3. 每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信
  4. TCP首部开销20字节;UDP的首部开销小,只有8个字节。
  5. TCP提供可靠的服务。UDP适用于一次只传少量数据、对可靠要求不高的环境。

————————————————

3.HTTP常见的状态码

4.如何解决跨域

什么是跨域?
浏览器从一个域名的网页去请求另一个域名的资源时,域名、端口、协议任一不同,都是跨域
常见的:

1、JSONP跨域
原理:利用script标签可以跨域请求资源,将回调函数作为参数拼接在url中。后端收到请求,调用该回调函数,并将数据作为参数返回去,注意设置响应头返回文档类型,应该设置成javascript。
2、跨域资源共享(CORS)
目前最常用的一种解决办法,通过设置后端允许跨域实现。
3、nginx反向代理
跨域限制的时候浏览器不能跨域访问服务器,node中间件和nginx反向代理,都是让请求发给代理服务器,静态页面面和代理服务器是同源的,然后代理服务器再向后端服务器发请求,服务器和服务器之间不存在同源限制。
4、WebSocket协议跨域
5、proxy
前端配置一个代理服务器(proxy)代替浏览器去发送请求:因为服务器与服务器之间是可以通信的不受同源策略的影响。

————————————————
 

5.网页从输入url到页面加载发生了什么

  1. DNS解析
  2. TCP连接
  3. 发送HTTP请求
  4. 服务器处理请求并返回HTTP报文
  5. 浏览器解析并渲染页面————>1.解析文档构建dom树。2.构建渲染树。3.布局与绘制渲染树。
  6. 连接结束

6.HTTP 传输过程

含义:从建立连接到断开连接一共七个步骤,就是三次招手四次挥手

  1. TCP 建立连接
  2. 浏览器发送请求命令
  3. 浏览器发送请求头
  4. 服务器应答
  5. 服务器回应信息
  6. 服务器发送数据
  7. 断开TCP连接

7.浏览器如何渲染页面的?

  1. 浏览器解析html源码,将HTML转换成dom树,
  2. 将CSS样式转换成stylesheet(CSS规则树),
  3. 浏览器会将CSS规则树附着在DOM树上,并结合两者生成渲染树(Render Tree)
  4. 生成布局(flow),浏览器通过解析计算出每一个渲染树节点的位置和大小,在屏幕上画出渲染树的所有节点
  5. 合成绘制生成页面。

————————————————
 

8.对MVC和MVVM的理解

M:model(数据模型),V:view(视图),C:controller(逻辑处理),VM:(连接model和view)
MVC:单向通信。必须通过controller来承上启下。
MVVM:数据双向绑定,数据改变视图,视图改变数据。

9.深拷贝,浅拷贝

浅拷贝:创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值,如果属性是引用类型,拷贝的就是内存地址 ,所以如果其中一个对象改变了这个地址,就会影响到另一个对象。

深拷贝:将一个对象从内存中完整的拷贝一份出来,从堆内存中开辟一个新的区域存放新对象,且修改新对象不会影响原对象。

总而言之,浅拷贝改动拷贝的数组原数组也会变(慎用!项目中很多地方共用的数组都会变)。深拷贝修改新数组不会改到原数组。
实现方法

浅拷贝

  1. Object.assign()
  2. 函数库lodash的 _.clone 方法
  3. es6的展开运算符 
  4. Array.prototype.concat()
  5. Array.prototype.slice()

深拷贝

  1. JSON.parse(JSON.stringify())
  2. 函数库lodash的 _.cloneDeep 方法
  3. **jQuery.extend()**方法
  4. 手写递归方法(转)

 

10.防抖与节流 

防抖:触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间
应用场景:
提交按钮、用户注册时候的手机号验证、邮箱验证、

节流:高频事件触发,但在n秒内只会执行一次,所以节流会稀释函数的执行频率。
应用场景:
window对象的resize、scroll事件
拖拽时候的mousemove
射击游戏中的mousedown、keydown事件
文字输入、自动完成的keyup事件
————————————————

11.性能优化

举例:

  1. 减少http请求次数
  2. 减少DNS查找
  3. 避免重定向
  4. 使用Ajax缓存
  5. 少用全局变量、减少DOM操作的使用
  6. 优化图片大小,通过CSS Sprites(精灵图)优化图片,
  7. 将css放在顶部,将js放在底部

————————————————

12.webpack是怎么打包的,babel又是什么

Webpack:把所有依赖打包成一个 bundle.js文件,通过代码分割成单元片段并按需加载。Webpack是以公共JS的形式来书写脚本的,但对AMD/CMD的支持也很全面,方便旧项目进行代码迁移。
把项目当做一个整体,通过一个给定的主文件(如:index.js),Webpack将从这个文件开始找到项目的所有依赖文件,使用loaders处理它们,最后打包为一个(或多个)浏览器可识别的JavaScript文件。

babel将es6、es7、es8等语法转换成浏览器可识别的es5或es3语法。
————————————————

13.git 和 svn的区别

SVN是集中式版本控制系统,版本库是集中放在中央服务器的,首先要从中央服务器哪里得到最新的版本,干完活后,需要把自己做完的活推送到中央服务器。集中式版本控制系统是必须联网才能工作(如果在局域网还可以,带宽够大,速度够快,如果在互联网下,如果网速慢的话,就纳闷了)

Git是分布式版本控制系统,没有中央服务器的,每个人的电脑就是一个完整的版本库,这样,工作的时候就不需要联网了,因为版本都是在自己的电脑上。自己在电脑上改了文件A,其他人也在电脑上改了文件A,这时,只需把各自的修改推送给对方,就可以互相看到对方的修改了。
————————————————

14.webSocket

webSocket:可以让服务器主动向客户端发送消息,适合开发聊天室,多人游戏等协作应用。

WebSocket协议是基于TCP的一种新的网络协议。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

————————————————

15.require和import区别

调用时间
require运行时调用,理论上可以运用在代码任何地,甚至不需要赋值给某个变量之后再使用。
lmport是编译时候调用,必须放在文件开头,而且使用格式也是确定的。
遵循规范
require 是 AMD规范引入方式
import是es6的一个语法标准,如果要兼容浏览器的话必须转化成es5的语法
本质
require是赋值过程,其实require 的结果就是对象、数字、字符串、函数等,再把require的结果赋值给某个变量。
import是解构过程。
通过require 引入基础数据类型时,属于复制该变量。
通过require 引入复杂数据类型时,数据浅拷贝该对象。
出现模块之间的循环引用时,会输出已经执行的模块,而未执行的模块不输出(比较复杂)。CommonJS模块默认export的是一个对象,即使导出的是基础数据类型。

ES6 模块语法是 JavaScript 模块的标准写法,坚持使用这种写法,取代 Node.js 的 CommonJS 语法。
使用import取代require()。

使用export取代module.exports。

 

 16.事件循环(Event Loop)

原因:JavaScript是单线程,所有任务需要排队,前一个任务结束,才会执行后一个任务。

所有任务可以分成两种,一种是同步任务(synchronous),另一种是异步任务(asynchronous)。
同步任务:在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;
异步任务:不进入主线程、而进入"任务队列"的任务,只有"任务队列"通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。

同步和异步任务分别进入不同的执行环境, 先执行同步任务,把异步任务放入循环队列当中挂起,等待同步任务执行完,再执行队列中的异步任务。异步任务先执行微观任务,再执行宏观任务。一直这样循环,反复执行。

微任务:Promise.then、catch、finally、async/await。
宏任务:整体代码 Script、UI 渲染、setTimeout、setInterval、Dom事件、ajax事件。
————————————————

17.什么是单页面应用(SPA)

一个系统只加载一次资源,之后的操作交互、数据交互是通过路由、ajax来进行,页面并没有刷新。
在一个页面上集成多种功能,甚至整个系统就只有一个页面,所有的业务功能都是它的子模块,通过特定的方式挂接到主界面上。
优点:

前后端分离
良好的交互体验——用户不用刷新页面,页面显示流畅
减轻服务器压力——服务器只出数据
共用一套后端代码——多个客户端可共用一套后端代码
加载速度快,内容的改变不需要重新加载整个页面,对服务器压力小
缺点:

SEO难度高——数据渲染在前端进行
页面初次加载比较慢,页面复杂提高很多
多页面:一个应用多个页面,页面跳转时整个页面都刷新,每次都请求一个新的页面
优点:SEO效果好
缺点:页面切换慢,每次切换页面需要选择性的重新加载公共资源
————————————————

18.什么叫优雅降级和渐进增强?

渐进增强(Progressive Enhancement):一开始就针对低版本浏览器进行构建页面,完成基本的功能,然后再针对高级浏览器进行效果、交互、追加功能达到更好的体验。
优雅降级(Graceful Degradation):一开始就构建站点的完整功能,然后针对浏览器测试和修复。

在传统软件开发中,经常会提到向上兼容和向下兼容的概念。渐进增强相当于向上兼容,而优雅降级相当于向下兼容。向下兼容指的是高版本支持低版本的或者说后期开发的版本支持和兼容早期开发的版本,向上兼容的很少。大多数软件都是向下兼容的。

二者区别:
1、优雅降级和渐进增强只是看待同种事物的两种观点。
2、优雅降级观点认为应该针对那些最高级、最完善的浏览器来设计网站。
3、渐进增强观点则认为应关注于内容本身
————————————————

四、VUE篇

1.数据双向绑定原理

答:通过数据劫持结合发布—订阅模式,通过Object.defineProperty()为各个属性定义get、set方法,在数据发生改变时给订阅者发布消息,触发相应的事件回调。

2. vue生命周期

概念:从创建、初始化数据、编译模板、挂载DOM、渲染-更新-渲染、卸载等一系列过程,称为为Vue 实例的生命周期。

vue2.0

  1. beforeCreate:创建前。此时,组件实例刚刚创建,还未进行数据观测和事件配置,拿不到任何数据。
  2. created:创建完成。vue 实例已经完成了数据观测,属性和方法的计算(比如props、methods、data、computed和watch此时已经拿得到),未挂载到DOM,不能访问到el属性,el属性,ref属性内容为空数组常用于简单的ajax请求,页面的初始化。
  3. beforeMount:挂载前。挂在开始之前被调用,相关的render函数首次被调用(虚拟DOM)。编译模板,把data里面的数据和模板生成html,完成了el和data 初始化,注意此时还没有挂在html到页面上。
  4. mounted:挂载完成。也就是模板中的HTML渲染到HTML页面中,此时可以通过DOM API获取到DOM节点,$ref属性可以访问常用于获取VNode信息和操作,ajax请求,mounted只会执行一次。
  5. beforeUpdate:在数据更新之前被调用,发生在虚拟DOM重新渲染和打补丁之前,不会触发附加地重渲染过程。
  6. updated:更新后。在由于数据更改导致地虚拟DOM重新渲染和打补丁之后调用,
  7. beforeDestroy;销毁前。在实例销毁之前调用,实例仍然完全可用。(一般在这一步做一些重置的操作,比如清除掉组件中的定时器 和 监听的dom事件)
  8. destroyed:销毁后。在实例销毁之后调用,调用后,vue实列指示的所有东西都会解绑,所有的事件监听器会被移除。
  9. 其他:
  10. activated:在keep-alive组件激活时调用
  11. deactivated:在keep-alive组件停用时调用

————————————————
vue3.0

  • onBeforeMount
  • onMounted
  • onBeforeUpdate
  • onUpdated
  • onBeforeUnmount
  • onUnmounted

 

 3.组件之间如何传值

一、Vue父子 组件之间传值

子组件通过props来接受数据和通过$emit来触发父组件的自定义事件;
二、兄弟组件之间的传值

建一个公共组件bus.js.。传递方通过事件触发bus.$emit。接收方通过在mounted(){}生命周期里触发bus.$on。
三、可以通过VUEX 来跨组件传参。

四、父孙传值 $attrs(向下)$listeners(向上)

五、 祖先和子孙传值provide/inject

六、获取父组件实例this.$parent
————————————————

4.路由之间如何传参

  • 通过router-link路由导航跳转传递
  • 跳转时使用push方法拼接携带参数。
  • 通过路由属性中的name来确定匹配的路由,通过params来传递参数。
  • 使用path来匹配路由,然后通过query来传递参数。

注意:query有点像ajax中的get请求,而paramspost请求。

params在地址栏中不显示参数,刷新页面,参数丢失,
其余方法在地址栏中显示传递的参数,刷新页面,参数不丢失。

————————————————

5.谈一谈VUEX

原理:Vuex是专门为vue.js应用程序设计的状态管理工具。
构成:

state:vuex的基本数据,用来存储变量,存放的数据是响应式的。
mutations:提交更改数据,同步更新状态。
actions:提交mutations,可异步操作。
getters:是store的计算属性。
modules:模块,每个模块里面有四个属性。
关于VUEX如何使用可以看VUE的传值问题
————————————————

6.如何解决vuex页面刷新数据丢失问题?

原因:因为vuex里的数据是保存在运行内存中的,当页面刷新时,页面会重新加载vue实例,vuex里面的数据就会被清空。
解决方法:将vuex中的数据直接保存到浏览器缓存中。(一般是用sessionStorage)

————————————————

7.computed和watch的区别?

-详情请看Vue的计算属性与methods、watch的区别

computed值有缓存、触发条件是依赖值发生更改、 watch无缓存支持异步、监听数据变化

computed: 是计算属性,依赖其它属性值,并且 computed 的值有缓存,只有它依赖的属性值发生改变,下一次获取 computed 的值时才会重新计算 computed 的值;
watch: 更多的是观察的作用,支持异步,类似于某些数据的监听回调 ,每当监听的数据变化时都会执行回调进行后续操作;

computed应用场景:需要进行数值计算,并且依赖于其它数据时,应该使用 computed,因为可以利用 computed 的缓存特性,避免每次获取值时,都要重新计算;
watch应用场景:需要在数据变化时执行异步或开销较大的操作时,应该使用 watch,使用 watch 选项允许我们执行异步操作 ( 访问一个 API ),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的。
————————————————

8.如何封装axios?

9.Route和router的区别

  • route:是路由信息对象,包括“path,parms,hash,name“等路由信息参数。
  • Router:是路由实例对象,包括了路由跳转方法,钩子函数等。

10.v-show和v-if的区别

  • v-if:组件的销毁和重建,更适合带有权限的操作,切换开大。如果开始条件为false则什么都不做,只有为true才会编译。
  • v-show:css切换,隐藏显示更适合频繁切换。在任何情况下都会被编译,然后被缓存,而且dom元素会被保留。

11.vue中数据变了但是视图不跟新怎么解决?
原因:

数组数据变动:使用某些方法操作数组,变动数据时,有些方法无法被vue监测。
Vue 不能检测到对象属性的添加或删除。
异步更新队列:数据第一次的获取到了,也渲染了,但是第二次之后数据只有在再一次渲染页面的时候更新,并不能实时更新。
————————————————

12.vue中data为什么是函数而不是对象 

官网中有这么一段介绍,详情可以看组件的复用

 

 意思就是,在Vue中组件是可以被复用的,而当data是一个函数的时候,每一个实例的data都是独立的,不会相互影响了。

更详细的解释 ==>

 

13.vue中父子组件传值,父组件异步请求,子组件不能实时更新怎么解决?(vue中数据不能实时更新怎么解决?)

首先了解父子组件生命周期执行顺序 ==>
加载渲染数据过程
父组件 beforeCreate -->
父组件 created -->
父组件 beforeMount -->
子组件 beforeCreate -->
子组件 created -->
子组件 beforeMount -->
子组件 mounted -->
父组件 mounted -->

原因:因为生命周期只会执行一次,数据是要等到异步请求以后才能拿到,那么子组件的mounted钩子执行的时候,还没有拿到父组件传递过来的数据,但是又必须要打印出来结果,那这样的话,就只能去打印props中的默认值空字符串了,所以打印的结果是一个空字符串。
————————————————

解决办法:

  1. 使用v-if控制组件渲染的时机
    初始还没拿到后端接口的异步数据的时候,不让组件渲染,等拿到的时候再去渲染组件。使用v-if="变量"去控制,初始让这个变量为false,这样的话,子组件就不会去渲染,等拿到数据的时候,再让这个变量变成true,
    举例

2. 使用watch监听数据的变化
举例:

3.使用VueX

14.父子组件传参emit如何传多个参数?

子组件:

 父组件

15.Vue 路由跳转方式 

  • router-link 标签跳转
  • this.$router.push()
  • this.$router.replace()
  • this.$router.go(n):(0:当前页,-1上一页,+1下一页,n代表整数)

16.条件渲染v-if 与 v-for 优先级

 

17.Vue 中 $nextTick 作用与原理?

异步渲染、获取DOM、Promise等。

Vue 在更新 DOM 时是异步执行的,在修改数据后,视图不会立刻更新,而是等同一事件循环中的所有数据变化完成之后,再统一进行视图更新。所以修改完数据,立即在方法中获取DOM,获取的仍然是未修改的DOM。 $nextTick的作用是:该方法中的代码会在当前渲染完成后执行,就解决了异步渲染获取不到更新后DOM的问题了。 n e x t T i c k 的原理: nextTick的原理:nextTick的原理:nextTick本质是返回一个Promise 。

应用场景:

在created()里面想要获取操作Dom,把操作DOM的方法放在$nextTick中。
在data()中的修改后,页面中无法获取data修改后的数据,使用$nextTick时,当data中的数据修改后,可以实时的渲染页面
官网中是这么说的

 

18.Vue 中 for循环为什么加 key?

为了性能优化, 因为vue是虚拟DOM,更新DOM时用diff算法对节点进行一一比对,比如有很多li元素,要在某个位置插入一个li元素,但没有给li上加key,那么在进行运算的时候,就会将所有li元素重新渲染一遍,但是如果有key,那么它就会按照key一一比对li元素,只需要创建新的li元素,插入即可,不需要对其他元素进行修改和重新渲染。
key也不能是li元素的index,因为假设我们给数组前插入一个新元素,它的下标是0,那么和原来的第一个元素重复了,整个数组的key都发生了改变,这样就跟没有key的情况一样了。
————————————————

五、REACT篇

1.React的生命周期(版本17.0.2)

概念:每个组件都包含 “生命周期方法”,你可以重写这些方法,以便于在运行过程中特定的阶段执行这些方法。
挂载:

constructor():在 React 组件挂载之前,会调用它的构造函数。(注:如果不初始化 state 或不进行方法绑定,则不需要为 React 组件实现构造函数。)
render(): class 组件中唯一必须实现的方法。
componentDidMount():在组件挂载后(插入 DOM 树中)立即调用。依赖于 DOM 节点的初始化应该放在这里。
更新

render(): class 组件中唯一必须实现的方法。
componentDidUpdate():在更新后会被立即调用。首次渲染不会执行此方法。
卸载

componentWillUnmount():在组件卸载及销毁之前直接调用。在此方法中执行必要的清理操作,例如,清除 timer,取消网络请求或清除在 componentDidMount() 中创建的订阅等

 

2.React如何获取组件对应的DOM元素?

ref:通过当前class组件实例的一些特定属性来直接获取子节点实例。
注意:不能在函数组件上使用 ref 属性,因为他们没有实例。
findDOMNode():findDOMNode 是一个访问底层 DOM 节点的应急方案(escape hatch)。
注意:在大多数情况下,不推荐使用该方法,因为它会破坏组件的抽象结构。严格模式下该方法已弃用。findDOMNode 不能用于函数组件。
详情请看官网:ReactDOM
————————————————

3.React中可以在render访问refs吗?为什么?

答:不能,因为在render阶段refs还未生成。DOM 的读取在 pre-commit 阶段,DOM的使用在 commit 阶段。

4.React中什么是受控组件和非控组件 

渲染表单的 React 组件还控制着用户输入过程中表单发生的操作。被 React 以这种方式控制取值的表单输入元素就叫做“受控组件”。

受控组件更新state的流程:

可以通过初始state中设置表单的默认值

每当表单的值发生变化时,调用onChange事件处理器

事件处理器通过事件对象e拿到改变后的状态,并更新组件的state

一旦通过setState方法更新state,就会触发视图的重新渲染,完成表单组件的更新

对于受控组件来说,输入的值始终由 React 的 state 驱动。你也可以将 value 传递给其他 UI 元素,或者通过其他事件处理函数重置,但这意味着你需要编写更多的代码。

非受控组件
如果一个表单组件没有value props(单选和复选按钮对应的是checked props)时,就可以称为非受控组件。在非受控组件中,可以使用一个ref来从DOM获得表单值。而不是为每个状态更新编写一个事件处理程序。

官网解释:要编写一个非受控组件,而不是为每个状态更新都编写数据处理函数,你可以 使用 ref 来从 DOM 节点中获取表单数据。

因为非受控组件将真实数据储存在 DOM 节点中,所以在使用非受控组件时,有时候反而更容易同时集成 React 和非 React 代码。如果你不介意代码美观性,并且希望快速编写代码,使用非受控组件往往可以减少你的代码量。否则,你应该使用受控组件。
官网非受控组件

总结: 页面中所有输入类的DOM如果是现用现取的称为非受控组件,而通过setState将输入的值维护到了state中,需要时再从state中取出,这里的数据就受到了state的控制,称为受控组件。
————————————————

5.谈一谈React的状态提升?

官网是这么解释的:

多个组件需要反映相同的变化数据,这时我们建议将共享状态提升到最近的共同父组件中去。

简单来说就是:将多个组件需要共享的状态提升到它们最近的父组件上,在父组件上改变这个状态然后通过props分发给子组件。对子组件操作,子组件不改变自己的状态。
可看官网的温度计数器例子
————————————————

6.为什么要使用虚拟DOM?(什么是 Virtual DOM?)

Virtual DOM算法
用一张图片来表示

 

虚拟DOM
那就是虚拟DOM概念出现的地方,并且其性能要比真实DOM好得多。虚拟DOM只是DOM的虚拟表示。每当我们的应用程序状态更改时,虚拟DOM就会更新,而不是真实DOM。

React如何使用虚拟DOM

在React中,每个UI块都是一个组件,每个组件都有一个状态。React遵循可观察的模式,并监听状态变化。当组件的状态改变时,React更新虚拟DOM树。虚拟DOM更新后,React然后将虚拟DOM的当前版本与虚拟DOM的先前版本进行比较。此过程称为“差异化”。

一旦React知道哪些虚拟DOM对象已更改,然后React就会在真实DOM中仅 更新那些对象。与直接操作真实DOM相比,这使性能好得多。

原因:对于局部的小视图的更新,重新构造整棵 DOM没问题;但是对于大型视图,如全局应用状态变更的时候,需要更新页面较多局部视图的时候,这样的做法不可取。 Virtual DOM只是加了一些特别的步骤来避免了整棵 DOM 树变更。

简而言之就是:

频繁的DOM操作昂贵且性能沉重。
虚拟DOM是真实DOM的虚拟表示。
React使用虚拟DOM来增强其性能。
JS 和 DOM 之间的缓存。
————————————————

六、其它篇

1.开发中遇到的bug?

项目中或者地图中遇到引入如图片不显示。

解决办法:使用require动态引入图片。
详细可看设置content加载不出图标

合并多个对象并去重

原因:普通去重不能去除对象。
解决方法:可看数组中有对象去除

移动端1px问题

原因:手机分辨率高,它的实际物理像素数更多了,不同手机屏幕分辨率不同,一般都差不多2倍左右,所以显得更粗。
解决方法:可以参考第二篇CSS的11题。

移动端点击穿透问题
原因:

点击蒙层上的关闭按钮,蒙层消失后触发了按钮下面元素的click事件
如果按钮下面恰好是一个有href属性的a标签,那么页面就会发生跳转
这次没有蒙层,直接点击页内按钮跳转至新页,然后发现新页面中对应位置元素的click事件被触发了.
解决方法:
最优解决方法——只用touch
最简单的解决方案,完美解决点击穿透问题
把页面内所有click全部换成touch事件( touchstart、touchmove、touchend)
 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值