当前位置: 首页 > news >正文

Godaddy优惠码网站怎么做的做的一个网站多少钱

Godaddy优惠码网站怎么做的,做的一个网站多少钱,两学一做网站,小型企业网站有哪些目录 1_防抖和节流1.1_认识防抖和节流函数1.2_认识防抖debounce函数1.3_防抖函数的案例1.4_认识节流throttle函数 2_Underscore实现防抖和节流2.1_Underscore实现防抖和节流2.2_自定义防抖函数2.3_自定义节流函数 3_自定义深拷贝函数4_自定义事件总线 1_防抖和节流 1.1_认识防… 目录 1_防抖和节流1.1_认识防抖和节流函数1.2_认识防抖debounce函数1.3_防抖函数的案例1.4_认识节流throttle函数 2_Underscore实现防抖和节流2.1_Underscore实现防抖和节流2.2_自定义防抖函数2.3_自定义节流函数 3_自定义深拷贝函数4_自定义事件总线 1_防抖和节流 1.1_认识防抖和节流函数 防抖和节流的概念其实最早并不是出现在软件工程中防抖是出现在电子元件中节流出现在流体流动中 而JavaScript是事件驱动的大量的操作会触发事件加入到事件队列中处理。而对于某些频繁的事件处理会造成性能的损耗就可以通过防抖和节流来限制事件频繁的发生 防抖和节流函数目前已经是前端实际开发中两个非常重要的函数也是面试经常被问到的面试题。 但是很多前端开发者面对这两个功能有点摸不着头脑 某些开发者根本无法区分防抖和节流有什么区别面试经常会被问到某些开发者可以区分但是不知道如何应用某些开发者会通过一些第三方库来使用但是不知道内部原理更不会编写 学习防抖和节流函数不仅仅要区分清楚防抖和节流两者的区别也要明白在实际工作中哪些场景会用到 1.2_认识防抖debounce函数 当事件触发时相应的函数并不会立即触发而是会等待一定的时间当事件密集触发时函数的触发会被频繁的推迟只有等待了一段时间也没有事件触发才会真正的执行响应函数 防抖的应用场景很多 输入框中频繁的输入内容搜索或者提交信息频繁的点击按钮触发某个事件监听浏览器滚动事件完成某些特定操作用户缩放浏览器的resize事件 1.3_防抖函数的案例 场景在某个搜索框中输入自己想要搜索的内容 比如想要搜索一个MacBook 当输入m时为了更好的用户体验通常会出现对应的联想内容这些联想内容通常是保存在服务器的所以需要一次网络请求当继续输入ma时再次发送网络请求那输入macbook一共需要发送7次网络请求这大大损耗整个系统的性能无论是前端的事件处理还是对于服务器的压力; 问题真的需要这么多次的网络请求吗 不需要正确的做法应该是在合适的情况下再发送网络请求比如如果用户快速的输入一个macbook那只发送一次网络请求比如如果用户是输入一个m想了一会儿这个时候m确实应该发送一次网络请求也就应该监听用户在某个时间比如500ms内没有再次触发时间时再发送网络请求 这就是防抖的操作只有在某个时间内没有再次触发某个函数时才真正的调用这个函数 1.4_认识节流throttle函数 当事件触发时会执行这个事件的响应函数 如果这个事件会被频繁触发那么节流函数会按照一定的频率来执行函数不管在这个中间有多少次触发这个事件执行函数的频繁总是固定的 节流的应用场景 监听页面的滚动事件 鼠标移动事件 用户频繁点击按钮操作 游戏中的一些设计 2_Underscore实现防抖和节流 2.1_Underscore实现防抖和节流 可以通过一些第三方库来实现防抖操作 lodash、 underscore 使用underscore 可以理解成lodash是underscore的升级版它更重量级功能也更多但是目前underscore还在维护lodash已经很久没有更新了 Underscore的官网 https://underscorejs.org/ Underscore的安装有很多种方式 下载Underscore本地引入 !-- 本地引入: 下载js文件, 并且本地引入 --script src./js/underscore.js/script通过CDN直接引入 !-- CDN引入: 网络的js文件 -- script srchttps://cdn.jsdelivr.net/npm/underscore1.13.4/underscore-umd-min.js/script通过包管理工具npm管理安装略 补充引入这个库后如何操作防抖函数基本实现防抖而已 // 2.underscore防抖处理代码let counter 1 inputEl.oninput _.debounce(function() {console.log(发送网络请求${counter}:, this.value) }, 1000)2.2_自定义防抖函数 防抖基本功能实现可以实现防抖效果【面试】 bodybutton按钮/buttoninput typetextscript//自己实现防抖的基本功能function mydebounce(fn, delay) {// 1.用于记录上一次事件触发的timerlet timer null// 2.触发事件时执行的函数const _debounce () {// 2.1.如果有再次触发(更多次触发)事件, 那么取消上一次的事件if (timer) clearTimeout(timer)// 2.2.延迟去执行对应的fn函数(传入的回调函数)timer setTimeout(() {fn()timer null // 执行过函数之后, 将timer重新置null}, delay);}// 返回一个新的函数return _debounce}/scriptscript// 1.获取input元素const inputEl document.querySelector(input)// 3.自己实现的防抖let counter 1inputEl.oninput mydebounce(function() {console.log(发送网络请求${counter})}, 1000)/script/body优化一优化参数和this指向 bodybutton按钮/buttoninput typetextscriptfunction mydebounce(fn, delay) {// 1.用于记录上一次事件触发的timerlet timer null// 2.触发事件时执行的函数const _debounce function(...args) {// 2.1.如果有再次触发(更多次触发)事件, 那么取消上一次的事件if (timer) clearTimeout(timer)// 2.2.延迟去执行对应的fn函数(传入的回调函数)timer setTimeout(() {fn.apply(this, args) //事件绑定thistimer null // 执行过函数之后, 将timer重新置null}, delay);}// 返回一个新的函数return _debounce}/scriptscript// 1.获取input元素const inputEl document.querySelector(input)// 3.自己实现的防抖let counter 1inputEl.oninput mydebounce(function(event) { //参数event是为了让this绑定input事件console.log(发送网络请求${counter}:, this, event)}, 1000)/script /body优化二优化取消操作增加取消功能 //body 添加“取消按钮”button classcancel取消/button//function mydebounce(fn, delay) {} 添加“取消”事件的代码function mydebounce(fn, delay) {// 1.用于记录上一次事件触发的timerlet timer null// 2.触发事件时执行的函数const _debounce function(...args) {// 2.1.如果有再次触发(更多次触发)事件, 那么取消上一次的事件if (timer) clearTimeout(timer)// 2.2.延迟去执行对应的fn函数(传入的回调函数)timer setTimeout(() {fn.apply(this, args) //事件绑定thistimer null // 执行过函数之后, 将timer重新置null}, delay);} // 3.给_debounce绑定一个取消的函数_debounce.cancel function() {if (timer) clearTimeout(timer)}// 返回一个新的函数return _debounce}//“取消”按钮添加“取消”事件的功能cancelBtn.onclick function() {debounceFn.cancel()}优化三优化立即执行效果第一次立即执行 // 原则: 一个函数进行做一件事情, 一个变量也用于记录一种状态 function mydebounce(fn, delay, immediate false) {// 1.用于记录上一次事件触发的timerlet timer nulllet isInvoke false// 2.触发事件时执行的函数const _debounce function(...args) {// 2.1.如果有再次触发(更多次触发)事件, 那么取消上一次的事件if (timer) clearTimeout(timer) // 第一次操作不需要延迟立即执行if (immediate !isInvoke) {fn.apply(this, args)isInvoke truereturn}// 2.2.延迟去执行对应的fn函数(传入的回调函数)timer setTimeout(() {fn.apply(this, args)timer null // 执行过函数之后, 将timer重新置nullisInvoke false}, delay);}// 3.给_debounce绑定一个取消的函数_debounce.cancel function() {if (timer) clearTimeout(timer)timer nullisInvoke false}// 返回一个新的函数return _debounce}优化四优化返回值 // 原则: 一个函数进行做一件事情, 一个变量也用于记录一种状态function mydebounce(fn, delay, immediate false, resultCallback) {// 1.用于记录上一次事件触发的timerlet timer nulllet isInvoke false// 2.触发事件时执行的函数const _debounce function(...args) {return new Promise((resolve, reject) { //用Promise决定返回值的类型try {// 2.1.如果有再次触发(更多次触发)事件, 那么取消上一次的事件if (timer) clearTimeout(timer)// 第一次操作不需要延迟立即执行let res undefinedif (immediate !isInvoke) {res fn.apply(this, args)if (resultCallback) resultCallback(res)resolve(res)isInvoke truereturn}// 2.2.延迟去执行对应的fn函数(传入的回调函数)timer setTimeout(() {res fn.apply(this, args)if (resultCallback) resultCallback(res)resolve(res)timer null // 执行过函数之后, 将timer重新置nullisInvoke false}, delay);} catch (error) {reject(error)}})}// 3.给_debounce绑定一个取消的函数_debounce.cancel function() {if (timer) clearTimeout(timer)timer nullisInvoke false}// 返回一个新的函数return _debounce}// 2.手动绑定函数和执行const myDebounceFn mydebounce(function(name, age, height) {console.log(----------, name, age, height)return coderhhh 哈哈哈哈}, 1000, false)myDebounceFn(wmy, 18, 1.88).then(res {console.log(拿到执行结果:, res)})2.3_自定义节流函数 interval表示间隔时间nowtime-startime是为了计算距离函数开始执行经过多少时间当这个经过时间等于间隔时间的时候说明该再次执行某函数。 节流函数的基本实现可以实现节流效果【面试】 bodybutton按钮/buttoninput typetextscript//基本实现节流函数 。fn代表要执行的函数interval表示间隔时间function mythrottle(fn, interval) {let startTime 0const _throttle function() {const nowTime new Date().getTime()const waitTime interval - (nowTime - startTime)if (waitTime 0) {fn()startTime nowTime}}return _throttle}/script script// 获取input元素const inputEl document.querySelector(input)// 自己实现的节流函数let counter 1inputEl.oninput mythrottle(function() {console.log(发送网络请求${counter}:, this.value)}, 1000)/script 优化一节流立即执行 // 加入”立即执行“状态变量leadingfunction mythrottle(fn, interval, leading true) {let startTime 0const _throttle function(...args) {// 1.获取当前时间const nowTime new Date().getTime()// 如果立即执行状态变量为falseif (!leading startTime 0) {startTime nowTime}// 2.计算需要等待的时间执行函数const waitTime interval - (nowTime - startTime)if (waitTime 0) {fn.apply(this, args)startTime nowTime}}return _throttle}let counter 1inputEl.oninput mythrottle(function(event) {console.log(发送网络请求${counter}:, this.value, event)}, 1000)优化二节流最后一次也可以执行尾部执行了解即可 // 加入trailing决定是否尾部执行 function mythrottle(fn, interval, { leading true, trailing false } {}) {let startTime 0let timer nullconst _throttle function(...args) {// 1.获取当前时间const nowTime new Date().getTime()// 对立即执行进行控制if (!leading startTime 0) {startTime nowTime}// 2.计算需要等待的时间执行函数const waitTime interval - (nowTime - startTime)if (waitTime 0) {// console.log(执行操作fn)if (timer) clearTimeout(timer)fn.apply(this, args)startTime nowTimetimer nullreturn} // 3.判断是否需要执行尾部if (trailing !timer) {timer setTimeout(() {// console.log(执行timer)fn.apply(this, args)startTime new Date().getTime()timer null}, waitTime);}}return _throttle}优化三优化添加取消功能 //添加取消 按钮button classcancel取消/button//在节流函数加入取消的代码_throttle.cancel function() {if (timer) clearTimeout(timer)startTime 0timer null}//调用取消 按钮的代码cancelBtn.onclick function() {throttleFn.cancel()}优化四优化返回值问题 function mythrottle(fn, interval, { leading true, trailing false } {}) {let startTime 0let timer nullconst _throttle function(...args) {return new Promise((resolve, reject) { //用Promise优化返回值try {// 1.获取当前时间const nowTime new Date().getTime()// 对立即执行进行控制if (!leading startTime 0) {startTime nowTime}// 2.计算需要等待的时间执行函数const waitTime interval - (nowTime - startTime)if (waitTime 0) {// console.log(执行操作fn)if (timer) clearTimeout(timer)const res fn.apply(this, args)resolve(res)startTime nowTimetimer nullreturn} // 3.判断是否需要执行尾部if (trailing !timer) {timer setTimeout(() {// console.log(执行timer)const res fn.apply(this, args)resolve(res)startTime new Date().getTime()timer null}, waitTime);}} catch (error) {reject(error)}})}//取消节流_throttle.cancel function() {if (timer) clearTimeout(timer)startTime 0timer null}return _throttle}3_自定义深拷贝函数 对象相互赋值的一些关系分别包括 引入的赋值指向同一个对象相互之间会影响对象的浅拷贝只是浅层的拷贝内部引入对象时依然会相互影响对象的深拷贝两个对象不再有任何关系不会相互影响 前面可以通过一种方法来实现深拷贝了JSON.parse 这种深拷贝的方式其实对于函数、Symbol等是无法处理的并且如果存在对象的循环引用也会报错的 const info {name: hhh,age: 18,friend: {name: kobe},running: function() {},[Symbol()]: abc,// obj: info}info.obj info// 1.操作一: 引用赋值const obj1 info// 2.操作二: 浅拷贝const obj2 { ...info }obj2.name jamesobj2.friend.name jamesconsole.log(info.friend.name)const obj3 Object.assign({}, info)// obj3.name curryobj3.friend.name curryconsole.log(info.friend.name)// 3.操作三: 深拷贝// 3.1.JSON方法 缺点不能拷贝一些特殊的值比如函数const obj4 JSON.parse(JSON.stringify(info))info.friend.name curryconsole.log(obj4.friend.name)console.log(obj4) 自定义深拷贝的基本功能【面试】 // 需求: 判断一个标识符是否是对象类型 function isObject(value) {const valueType typeof valuereturn (value ! null) ( valueType object || valueType function ) }// 深拷贝函数function deepCopy(originValue) {// 1.如果是原始类型, 直接返回if (!isObject(originValue)) {return originValue}// 2.如果是对象类型, 才需要创建对象const newObj {}for (const key in originValue) {newObj[key] deepCopy(originValue[key]);}return newObj}const info {name: hhh,age: 18,friend: {name: kobe,address: {name: 洛杉矶,detail: 斯坦普斯中心}}}const newObj deepCopy(info)info.friend.address.name 北京市console.log(info.friend.address.name) //北京市console.log(newObj.friend.address.name) //洛杉矶 //说明深拷贝函数执行正确让原对象与新对象互不影响对Symbol的key进行处理以及其他数据类型的值进程处理数组、函数、Symbol、Set、Map // 深拷贝函数function deepCopy(originValue) {// 0.如果值是Symbol的类型if (typeof originValue symbol) {return Symbol(originValue.description) //返回其原型}// 1.如果是原始类型, 直接返回if (!isObject(originValue)) {return originValue}// 2.如果是set类型if (originValue instanceof Set) {const newSet new Set()for (const setItem of originValue) {newSet.add(deepCopy(setItem))}return newSet}// 3.如果是函数function类型, 不需要进行深拷贝if (typeof originValue function) {return originValue}// 2.如果是对象/数组类型, 才需要创建对象const newObj Array.isArray(originValue) ? []: {}// 遍历普通的keyfor (const key in originValue) {newObj[key] deepCopy(originValue[key]);}// 单独遍历symbolconst symbolKeys Object.getOwnPropertySymbols(originValue)for (const symbolKey of symbolKeys) {newObj[Symbol(symbolKey.description)] deepCopy(originValue[symbolKey])}return newObj}对循环引用的处理 // 深拷贝函数 循环引用// let map new WeakMap()function deepCopy(originValue, map new WeakMap()) {// const map new WeakMap()// 0.如果值是Symbol的类型if (typeof originValue symbol) {return Symbol(originValue.description)}// 1.如果是原始类型, 直接返回if (!isObject(originValue)) {return originValue}// 2.如果是set类型if (originValue instanceof Set) {const newSet new Set()for (const setItem of originValue) {newSet.add(deepCopy(setItem))}return newSet}// 3.如果是函数function类型, 不需要进行深拷贝if (typeof originValue function) {return originValue}// 4.如果是对象类型, 才需要创建对象if (map.get(originValue)) {return map.get(originValue)}const newObj Array.isArray(originValue) ? []: {}map.set(originValue, newObj)// 遍历普通的keyfor (const key in originValue) {newObj[key] deepCopy(originValue[key], map);}// 单独遍历symbolconst symbolKeys Object.getOwnPropertySymbols(originValue)for (const symbolKey of symbolKeys) {newObj[Symbol(symbolKey.description)] deepCopy(originValue[symbolKey], map)}return newObj}const info {name: hhh,age: 18,friend: {name: kobe,address: {name: 洛杉矶,detail: 斯坦普斯中心}},// self: info}info.self infolet newObj deepCopy(info)console.log(newObj)console.log(newObj.self newObj) 4_自定义事件总线 自定义事件总线属于一种观察者模式其中包括三个角色 发布者Publisher发出事件Event 订阅者Subscriber订阅事件Event并且会进行响应Handler 事件总线EventBus无论是发布者还是订阅者都是通过事件总线作为中台的 可以选择一些第三方的库 Vue2默认是带有事件总线的功能 Vue3中推荐一些第三方库比如mitt 也可以实现自己的事件总线 事件的监听方法on 事件的发射方法emit 事件的取消监听off bodybutton classnav-btnnav button/buttonscript// 类EventBus - 事件总线对象class HYEventBus {constructor() {this.eventMap {}}// 监听on(eventName, eventFn) {let eventFns this.eventMap[eventName]if (!eventFns) {eventFns []this.eventMap[eventName] eventFns}eventFns.push(eventFn)}// 取消监听off(eventName, eventFn) {let eventFns this.eventMap[eventName]if (!eventFns) returnfor (let i 0; i eventFns.length; i) {const fn eventFns[i]if (fn eventFn) {eventFns.splice(i, 1) //删除数组eventFns中第i个序号的元素break}}// 如果eventFns已经清空了if (eventFns.length 0) {delete this.eventMap[eventName]}}// 事件发射emit(eventName, ...args) {let eventFns this.eventMap[eventName]if (!eventFns) returneventFns.forEach(fn {fn(...args)})}}// 使用过程const eventBus new HYEventBus()// aside.vue组件中监听事件eventBus.on(navclick, (name, age, height) {console.log(navclick listener 01, name, age, height)})const click () {console.log(navclick listener 02)}eventBus.on(navclick, click)setTimeout(() {eventBus.off(navclick, click)}, 5000);eventBus.on(asideclick, () {console.log(asideclick listener)})// nav.vueconst navBtnEl document.querySelector(.nav-btn)navBtnEl.onclick function() {console.log(自己监听到)eventBus.emit(navclick, hhh, 18, 1.88)}/script/body
http://www.pierceye.com/news/457982/

相关文章:

  • 南宁站建好就够用秦皇岛微信推广平台
  • 物流公司做网站有用吗河北省住房和城乡建设网站
  • 网站举报官网seo站长论坛
  • 建站工具有哪些论坛网站建设总体要求
  • 公司网页网站建设 pptwordpress php 采集
  • 遵义网站开发公司舟山网站建设企业
  • 外贸网站一站式服务招网站建设销售
  • 绚丽的网站wordpress进入后台显示500
  • 威海城乡与住房建设部网站小颜自助建站系统
  • 域名怎么解析到网站做响应式网站需要学哪些知识
  • wordpress手机端慢seoer是什么意思
  • wordpress添加站点江苏廉政建设网站
  • 网站seo是什么做二维码推送网站
  • win7 iis默认网站设置游戏推广员
  • 湖北二师网站建设排名潍坊专业捞泵电话
  • 个人网站设计内容和要求萍乡网站制作公司
  • 合肥网站seo费用怎么把文章导入wordpress
  • 赣州网站推广哪家最专业阿里云wordpress数据库备份
  • 珠海专业网站建设公司做网站虚拟主机好还是
  • 做美图 网站有哪些wordpress哪些插件
  • 倒计时网站模板全屋定制设计培训学校哪里有
  • 凡客做网站网站排名的重要性
  • 怎么问客户做不做网站企业网站源码 多语言
  • wordpress网站基础知识信息网络公司经营范围
  • 智汇隆网站建设wordpress建字段
  • 广东专业商城网站建设软文投稿平台有哪些
  • 广告公司起什么名字好seo教程有什么
  • 搭建网站什么意思网站制作网址
  • 哈尔滨站建筑松原市建设局网站
  • 浙江网站建设 seo深圳建设岗位证书报名网站