导航  导航
每日一言

能被js重写的终将会被js重写。

 全部文章(7)

electron全局修改请求头的方法

const { session } = require("electron"); const xxx_filter = {   urls: ["*://*/*"] }; session.defaultSession.webRequest.onBeforeSendHeaders(xxx_filter, (details, callback) => {  details.requestHeaders['Origin'] = "http://www.baidu.com"; callback({ requestHeaders: details.requestHeaders }); }); 注意:此方法需要写在app的ready事件里面

css中counter的用法

在上篇文章”css为元素中如何使用css变量“中,用到了counter,因此这篇文章简单记录一下counter的概念和使用。counter——顾名思义,是计数器的意思。这个系列的属性包含三个属性:counter-reset,别被属性名迷惑,简单的可以理解为计数器名称和计数器初始值,名称必填,初始值默认为0。counter-increment,这是计数器的变化规则,如自增多少、自减多少。counter(),这是个函数,传入计数器名称,即可返回计数器的值。下面举个栗子:div:before{ counter-reset:num 1; /* 可以写多个计数器,以空格隔开 */ counter-increment:num 2; /* 计数器num自增2,自减2就是num -2,此属性每写一次就会自增或自减一次 */ content:counter(num); }

css伪元素content中如何使用css变量?

css变量很香,但是无法直接在伪元素content属性中使用。例如:div:before{ --num:50; content:var(--num) } 这样使用是一点作用都没有的,所以,只能借助外力——counter,正确用法:div:before{ --num:50; counter-reset:num var(--num); content:counter(num) }

对于nodejs与浏览器的事件循环的个人理解

平时开发过程中,对于事件,我们基本只需要知道同步和异步的区别就差不多了,但是如果业务逻辑比较复杂时,不理解事件循环机制的话,很容易掉进坑里。无奈网上的一些文章文字太多,大多堆砌了太多官方概念,对于我这种看文字就头晕的人,很容易被劝退。但实在没办法,只能多看几篇文章,硬着头皮去理解,然后用自己的语言来记录一下。1、js的任务分为宏任务和微任务宏任务:setTimeout, setInterval, setImmediate, I/O, UI rendering微任务:process.nextTick, Promise等2、nodejs事件循环执行同步任务--->遇到异步任务,把异步任务放进任务队列--->执行宏任务(执行之前检测任务队列里有没有微任务,有则先执行微任务),如此循环。3、浏览器事件循环与nodejs的事件循环不同的是,如果宏任务里面包含微任务,则把里面的所有微任务放进队列,然后执行完宏任务里的所有微任务。下面举一个烂大街的例子:'use strict'; console.log(1); setTimeout(() => { console.log(2) new Promise((resolve) => { console.log(6); resolve(7); }).then((num) => { console.log(num); }) }); setTimeout(() => { console.log(3); new Promise((resolve) => { console.log(9); resolve(10); }).then((num) => { console.log(num); }) setTimeout(()=>{ console.log(8); }) }) new Promise((resolve) => { console.log(4); resolve(5) }).then((num) => { console.log(num); new Promise((resolve)=>{ console.log(11); resolve(12); }).then((num)=>{ console.log(num); }) }) 以上代码在nodejs下与浏览器下的执行结果分别是:nodejs:1、4、5、11、12、2、6、3、9、1、10、8浏览器:1、4、5、11、12、2、6、7、3、9、10、8可以明显的看出,浏览器在执行setTimeout时,直接执行了里面的promise。需要注意的是:promise里的代码属于同步代码,then里面的才是异步代码。以上结论纯属个人理解,如有错误,请指正。

react实现组件拖拽的方法

项目中经常会有组件拖拽的功能,每次要不就是从头写起,要不就是面向百度,两者都比较耗时,因此在此记录一下代码,以便日后复用。react实现拖拽与普通项目实现拖拽唯一的不同就是要在鼠标移动事件中不断地调用setState触发组件更新,以下是具体代码:class Drag extends Component {   constructor(props) {     super(props);     this.state = {       // 初始left、top       elX: 'unset',       elY: 'unset',     }     // 初始化鼠标点击位置与元素上侧和左侧的距离     this.disX = 0;     this.disY = 0;   }   // 定义鼠标下落事件   fnDown = (e) => {     const event = e || window.event;     const target = event.currentTarget || event.srcElement;     // 计算鼠标点击的位置与元素左侧和上侧的距离     this.disX = event.clientX - target.offsetLeft;     this.disY = event.clientY - target.offsetTop;     target.style.right = 'unset' // 如果外部样式表里使用right定位则需要写这一行     target.style.bottom = 'unset' // 如果外部样式表里使用right定位则需要写这一行     this.setState({       elX: event.clientX - this.disX,       elY: event.clientY - this.disY,     });     addEvent(document, 'mousemove', this.fnMove);     addEvent(document, 'mouseup', this.fnUp);     document.body.style.userSelect = 'none' // 拖动时禁止选择文本   }      // 鼠标移动事件   fnMove = (e)=> {     const event = e || window.event;     // 左右边界检测     let elX = event.clientX - this.disX     let elY = event.clientY - this.disY     let el = ReactDOM.findDOMNode(this)     if(elX <= 0) {       elX = 0     }else if(elX >= document.body.scrollWidth - el.offsetWidth) {       elX = document.body.scrollWidth - el.offsetWidth     }     if(elY <= 0) {       elY = 0     }else if(elY >= document.body.scrollHeight - el.offsetHeight) {       elY = document.body.scrollHeight - el.offsetHeight     }     this.setState({       elX,       elY,     });   }      fnUp = () => {     removeEvent(document, 'mousemove', this.fnMove);     removeEvent(document, 'mouseup', this.fnUp);     document.body.style.userSelect = 'unset'   }   render() {     return (       <div onMouseDown={this.fnDown} style={{ left:this.state.elX,top:this.state.elY }}></div>     );   } }

js中间件的实现,简单 容易理解

中间件是一张设计模式,所谓中间件,简单的理解就好比工厂的流水线,每一个流程需要用到的机器都是一个中间件,对产品进行加工包装。我们在使用vue、react等前端框架或者nodejs的koa、express等框架的时候,使用中间件通常是下面这种方式:app.use(function(ctx,next){ ctx.title = "hello" next() }) 那么我们如何使用js编码,能够实现上面的用法呢?接下来,咱们就动手实现一下:const app = { fns:[], use:function(fn){ this.fns.push(fn) }, run:function(ctx,callback){ let i = 0 const next = () => { i++ } this.fns.map((fn,index) => { if(i == index){ fn(ctx,next) } }) i == this.fns.length && callback && callback(ctx) } } app.use(function(ctx,next){ ctx.title = "hello" next() }) app.run({},function(ctx){ console.log(ctx) // 输出{ title: 'hello' } })

记录学习使用vue ssr框架nuxt的关键点

最近在学习使用nuxtjs框架,此博客系统的前端部分就是使用nuxt框架搭建的。为什么选择nuxt框架?因为考虑到seo(搜索引擎优化),国内多数搜索引擎蜘蛛是无法爬取到ajax获取的内容的,现在流行的SPA单页面应用都是采用前后端分离的形式开发,基本采用ajax请求的方式去做数据交互,对seo很不友好,所以要使用ssr(服务端渲染),即在后端渲染数据,多年前jsp,php等语言所写的页面就是服务端渲染,前后端杂糅在一起写,或者使用模板引擎。nuxt的使用场景:1、项目中有seo的需求,但是不想采用传统的ssr方案,而是采用现代前后端分离的方式开发。2、简化vue开发接下来就说一下nuxt中的重点:1、路由在nuxt中,不需要自己写router.js文件,有种约定大于配置的思想,直接在pages文件夹中创建文件夹和vue文件,即可生成对应的router,编译之后在.nuxt文件夹中可以看到。比如pages/admin/user/index.vue,在浏览器地址栏可以通过localhost:端口/admin/user访问。2、动态路由动态路由的文件需要命名为_+参数名的形式,如pages/article/_id.vue,访问方式为localhost/article/123,此时与vue一样,在程序中使用params即可获取id的值为123。3、asyncData方法asyncData方法与data()和生命周期方法同级,此方法在vue实例创建之前执行(因此不同通过this获取vue实例),用来渲染页面上需要seo的数据。方法入参有个context对象,具体看下面例子:async asyncData({$axios,params}){  let id = params.id  let user = await ($.axios.$get("http://localhost/api/getUserById"+id)).data  return {   user //这里返回的user就是相当于在data方法里返回的,可以通过this.user访问  } } 4、nuxt-link标签与a标签本人一开始使用nuxt-link去实现页面跳转,结果发现页面跳转非常慢,后来了解到nuxt-link是局部重新渲染,需要等asyncData方法获取数据完毕之后才会跳转页面,所以需要使用a标签去跳转。那为什么要有nuxt-link标签呢,因为如果项目不是ssr模式,那么为了用户体验,需要局部渲染,就要使用这个标签。5、created生命周期函数里不能使用window对象在created函数里面,不能使用window对象,比如sessionStorage,在asyncData同样不能!以上就是本人在nuxt开发学习中的主要经验,后续还会继续补充。