首页

你不知道的--save-dev和--save的区别

seo达人

网上对于这两个的区别解释都是统一口径的,一个是开发依赖,一个是线上依赖,打包发布需要用到的要添加到线上依赖,一模一样的回答,误导了很多人。今天自己测试一下这两个命令,记录一下。



–save-dev,会在devDependencies里面添加依赖



-D,会在devDependencies里面添加依赖



–save,会在dependencies里面添加依赖



-S,会在dependencies里面添加依赖



devDependencies和dependencies可以同时存在同一个包的依赖。



如果npm install xxx后面没有输入要保存到哪个里面,devDependencies和dependencies都没有。



我这边直接npm install jquery,node_modules下有jQuery。然后我删除node_modules,执行npm install,node_modules下并没有下载jQuery。



所以,安装依赖的时候如果没有加上要依赖到开发还是线上,只是临时的在node_modules里面帮你下载,而devDependencies和dependencies的依赖都会帮你下载。



然后我在devDependencies下安装依赖:



"devDependencies": {  

    "html-webpack-plugin": "^4.0.3", 

    "jquery": "^3.4.1",  

    "webpack": "^4.42.1", 

    "webpack-cli": "^3.3.11"

}



在入口文件引用和打印jQuery:



import $ from 'jquery'

console.log($)



打包之后,可以使用jQuery。



然后我在dependencies下安装依赖:



"dependencies": { 

    "html-webpack-plugin": "^4.0.3", 

    "jquery": "^3.4.1", 

    "webpack": "^4.42.1", 

    "webpack-cli": "^3.3.11"

}



在入口文件引用和打印jQuery:



import $ from 'jquery'

console.log($)



打包之后,可以使用jQuery。



测试的结果就是,无论是–save还是–save-dev,对于打包都没有任何影响。devDependencies和dependencies两种情况,打包出来的main.js都把jQuery打包进去。这两种情况,如果都没有引用jQuery的情况下,也都不会把jQuery打包。



接着在一个空白的项目里面下载axios,npm install axios -S,打开node_modules文件夹:







发现多出了另外三个依赖,查看axios下的package.json:



"dependencies": {



    "follow-redirects": "1.5.10"



}



查看follow-redirects下的package.json:



"dependencies": {



    "debug": "=3.1.0"



}



查看debugs下的package.json:



"dependencies": {



    "ms": "2.0.0"



}



最后ms的package.json没有dependencies。



而这几个包的devDependencies依赖的包没有一个下载。



接着我在node_modules把follow-redirects、debugs、ms都删了,把axios里面的package.js的dependencies给删了,然后执行npm install,发现没有下载follow-redirects、debugs、ms这几个,也证明了如果node_modules里面有下载的包,是不会重新去下载的。我把node_modules删除,执行npm install,这几个包又都下载下来了。



最后得出 的结论是,–save-dev和–save在平时开发的时候,对于打包部署上线是没有任何影响的。如果你是发布一个包给别人用,而你开发的包依赖第三方的包,那么你如果是–save,那么别人安装你开发的包,会默认下载你依赖的包,如果你是–save-dev,那么别人安装你开发的包,是不会默认帮忙下载你依赖的包。



其实发布的包如果没有必要,很少会默认帮你下载,比如bootstrap,依赖jQuery,怕你原本就下载了引起冲突,也不会在dependencies里面安装jQuery而是:



"peerDependencies": {



    "jquery": "1.9.1 - 3",



    "popper.js": "^1.16.0"



}



表示bootstrap依赖于这两个包,你必须安装,版本不固定,但是一定要安装这两个包,安装的时候会有警告:



peerDependencies WARNING bootstrap@ requires a peer of jquery@1.9.1 - 3 but none was installed



peerDependencies WARNING bootstrap@
requires a peer of popper.js@^1.16.0 but none was installed



当你引用了然后打包,报错:



ERROR in ./node_modules/_bootstrap@4.4.1@bootstrap/dist/js/bootstrap.js



Module not found: Error: Can't resolve 'jquery' in 'C:\Users\wade\Desktop\savedev\node_modules_bootstrap@4.4.1@bootstrap\dist\js'



 @ ./node_modules/_bootstrap@4.4.1@bootstrap/dist/js/bootstrap.js 7:82-99



 @ ./src/index.js



 



ERROR in ./node_modules/_bootstrap@4.4.1@bootstrap/dist/js/bootstrap.js



Module not found: Error: Can't resolve 'popper.js' in 'C:\Users\wade\Desktop\savedev\node_modules_bootstrap@4.4.1@bootstrap\dist\js'



 @ ./node_modules/_bootstrap@4.4.1@bootstrap/dist/js/bootstrap.js 7:101-121



 @ ./src/index.js



以上就是对–save和–save-dev的一些测试,想更快的得出结论其实是自己发布一个包。至于本人的答案是不是存在错误,欢迎指出,因为只是自己简单测试的结果。


vue实现移动端悬浮窗效果

前端达人

本文讲述,在使用VUE的移动端实现类似于iPhone的悬浮窗的效果。

相关知识点

touchstart 当在屏幕上按下手指时触发

touchmove 当在屏幕上移动手指时触发

touchend 当在屏幕上抬起手指时触发
mousedown mousemove mouseup对应的是PC端的事件

touchcancel 当一些更高级别的事件发生的时候(如电话接入或者弹出信息)会取消当前的touch操作,即触发touchcancel。一般会在touchcancel时暂停游戏、存档等操作。

效果图

实现步骤

1.html

总结了一下评论,好像发现大家都碰到了滑动的问题。就在这里提醒一下吧。可将该悬浮 DIV 同你的 scroller web 同级。 —- (log: 2018-08-21)

html结构: <template> <div>你的web页面</div> <div>悬浮DIV</div> </template>

<template>
 <div id="webId">
 ...
 <div>你的web页面</div>
 <!-- 如果碰到滑动问题,1.1 请检查这里是否属于同一点。 -->
 <!-- 悬浮的HTML -->
 <div v-if="!isShow" class="xuanfu" id="moveDiv"
  @mousedown="down" @touchstart="down"
  @mousemove="move" @touchmove="move"
  @mouseup="end" @touchend="end"
 >
  <div class="yuanqiu">
  {{pageInfo.totalPage}}
  </div>
 </div>
 ...
 </div>
</template>

2.JS

<script>
data() {
 return {
 flags: false,
 position: { x: 0, y: 0 },
 nx: '', ny: '', dx: '', dy: '', xPum: '', yPum: '',
 }
}

methods: {
 // 实现移动端拖拽
 down(){
 this.flags = true;
 var touch;
 if(event.touches){
  touch = event.touches[0];
 }else {
  touch = event;
 }
 this.position.x = touch.clientX;
 this.position.y = touch.clientY;
 this.dx = moveDiv.offsetLeft;
 this.dy = moveDiv.offsetTop;
 },
 move(){
 if(this.flags){
  var touch ;
  if(event.touches){
   touch = event.touches[0];
  }else {
   touch = event;
  }
  this.nx = touch.clientX - this.position.x;
  this.ny = touch.clientY - this.position.y;
  this.xPum = this.dx+this.nx;
  this.yPum = this.dy+this.ny;
  moveDiv.style.left = this.xPum+"px";
  moveDiv.style.top = this.yPum +"px";
  //阻止页面的滑动默认事件;如果碰到滑动问题,1.2 请注意是否获取到 touchmove
  document.addEventListener("touchmove",function(){
   event.preventDefault();
  },false);
 }
 },
//鼠标释放时候的函数
 end(){
 this.flags = false;
 },
}
</script>

3.CSS

<style>
 .xuanfu {
 height: 4.5rem;
 width: 4.5rem;
 /* 如果碰到滑动问题,1.3 请检查 z-index。z-index需比web大一级*/
 z-index: 999;
 position: fixed;
 top: 4.2rem;
 right: 3.2rem;
 border-radius: 0.8rem;
 background-color: rgba(0, 0, 0, 0.55);
 }
 .yuanqiu {
 height: 2.7rem;
 width: 2.7rem;
 border: 0.3rem solid rgba(140, 136, 136, 0.5);
 margin: 0.65rem auto;
 color: #000000;
 font-size: 1.6rem;
 line-height: 2.7rem;
 text-align: center;
 border-radius: 100%;
 background-color: #ffffff;
 }
</style>

实现好JS逻辑,基本上,问题不大。

本文链接 http://www.luyixian.cn/javascript_show_166242.aspx



再加一点

css之display:inline-block布局

1.解释一下display的几个常用的属性值,inline , block, inline-block

  • inline(行内元素):
    1. 使元素变成行内元素,拥有行内元素的特性,即可以与其他行内元素共享一行,不会独占一行. 
    2. 不能更改元素的height,width的值,大小由内容撑开. 
    3. 可以使用padding上下左右都有效,margin只有left和right产生边距效果,但是top和bottom就不行.
  • block(块级元素):
    1. 使元素变成块级元素,独占一行,在不设置自己的宽度的情况下,块级元素会默认填满父级元素的宽度. 
    2. 能够改变元素的height,width的值. 
    3. 可以设置padding,margin的各个属性值,top,left,bottom,right都能够产生边距效果.
  •  inline-block(融合行内于块级):
    1. 结合了inline与block的一些特点,结合了上述inline的第1个特点和block的第2,3个特点.
    2. 用通俗的话讲,就是不独占一行的块级元素。如图:

图一:1.png

图二:

2.png

两个图可以看出,display:inline-block后块级元素能够在同一行显示,有人这说不就像浮动一样吗。没错,display:inline-block的效果几乎和浮动一样,但也有不同,接下来讲一下inline-block和浮动的比较。

 

2.inline-block布局 vs 浮动布局

    a.不同之处:对元素设置display:inline-block ,元素不会脱离文本流,而float就会使得元素脱离文本流,且还有父元素高度坍塌的效果

    b.相同之处:能在某程度上达到一样的效果

我们先来看看这两种布局:
图一:display:inline-block3.png

图二:4.png

对两个孩子使用float:left,我在上一篇浮动布局讲过,这是父元素会高度坍塌,所以要闭合浮动,对box使用overflow:hidden,效果如下:

>>乍一看两个都能做到几乎相同的效果,(仔细看看display:inline-block中有间隙问题,这个留到下面再讲)

c.浮动布局不太好的地方:参差不齐的现象,我们看一个效果:
图三:

图四:

>>从图3,4可以看出浮动的局限性在于,若要元素排满一行,换行后还要整齐排列,就要子元素的高度一致才行,不然就会出现图三的效果,而inline-block就不会。

 

3.inline-block存在的小问题:

a.上面可以看到用了display:inline-block后,存在间隙问题,间隙为4像素,这个问题产生的原因是换行引起的,因为我们写标签时通常会在标签结束符后顺手打个回车,而回车会产生回车符,回车符相当于空白符,通常情况下,多个连续的空白符会合并成一个空白符,而产生“空白间隙”的真正原因就是这个让我们并不怎么注意的空白符。

 

b.去除空隙的方法:
1.对父元素添加,{font-size:0},即将字体大小设为0,那么那个空白符也变成0px,从而消除空隙
现在这种方法已经可以兼容各种浏览器,以前chrome浏览器是不兼容的
图一:

 

c.浏览器兼容性:ie6/7是不兼容 display:inline-block的所以要额外处理一下:
在ie6/7下:
对于行内元素直接使用{dislplay:inline-block;}5.png
对于块级元素:需添加{display:inline;zoom:1;}

 6.png

4.总结:

display:inline-block的布局方式和浮动的布局方式,究竟使用哪个,我觉得应该根据实际情况来决定的:
a.对于横向排列东西来说,我更倾向与使用inline-block来布局,因为这样清晰,也不用再像浮动那样清除浮动,害怕布局混乱等等。
b.对于浮动布局就用于需要文字环绕的时候,毕竟这才是浮动真正的用武之地,水平排列的是就交给inline-block了。



node 模块简述

seo达人

Node 的os模块是操作系统的

Node 的内置模块 fs


内置模块在下载node的时候就自带的,使用 require()方法来导入

语法 :require(‘模块fs’)



在内置模块中的方法

1 fs.readFile() —》用来专门 异步 读取文件的方法 三个参数

语法 :fs.readFile(‘要读取的文件’,读取文件的格式,读取成功的回调函数)

Eg : fs.readFIle(‘a’,’utf8’,’function(err,data){ })



2 fs.readFileSync()-– 专门用来 同步 读取的方法, 两个参数

语法: fs.readFileSync(‘要读取的文件’,读取格式)



3 fs.writeFIle() —>用来写入 异步 文件的方法 三个参数

语法: fs.writeFile(‘写入到哪个文件’,写入的内容,成功的回调函数)

Eg: fs.writeFile(‘./text.tex’,”内容”, function(){ })

注意:再次写入的内容会完全覆盖 。如果文件夹没有 会自动创建一个文件夹



4 fs.writeFileSync() --> 同步写入的方法

语法: fs.writeFileSync(‘写入到文件’,“写入的内容”)



Node的http模块

这个模块专门用来创建服务的

只能支持http协议。

也是使用require()方法

Const http= require(“http”)



方法

1 http.createServer(function(req,res){ }) 两个形参

Req=request 代表每次的请求信息

Res=response 代表每次请求的响应

返回值是一个服务,当服务监听端口号的时候,就变成了服务器。

2 监听端口号

创建的服务.listen(监听的端口号,监听成功的回调函数(选填))

server.listen(8080,function(){ 端口号0-65535 建议0-1023不使用 })

此时浏览器就可以执行localhost进行访问了



自定义模块

每一个js文件都是一个独立的模块,他们都自带一个 module 是一个对象,

其中 module里面的 exports,是一个对象 这个 module.exports 就是这个文件向外导出的内容,也就是说,只有导出,才能导入



Eg: function fn1(){console.log() }

Module.exports.fn1=fn1

这样,才能是另一个js文件到入这个文件 同样也是require(‘./js’)方法


教你用面向对象编程写一个烟花爆炸的

前端达人

点击查看原图



想要学会这个漂亮的烟花吗?快来跟着学习吧~

结构

<div class="container"></div>

我们只需要一个盒子表示烟花爆炸范围就可以了

样式

fire是烟花 注意添加绝对定位

 <style>
    .container{
        margin: 0 auto;
        height: 500px;
        width: 1200px;
        background: black;
        position: relative;
        overflow: hidden;
    }
    .fire{
        width: 10px;
        background: white;
        height: 10px;
        /* border-radius: 50%; */
        position: absolute;
        bottom: 0;
    }
    </style>



行为

编写构造函数Firework

需要用到一个鼠标点击的位置,一个div选择器,一个爆炸样式

 function Firework(x,y,selector,type){
        //此处获取对象的方式为单例的思想,避免重复获取相同的元素
        if(Firework.box && selector === Firework.box.selector){
            this.box =  Firework.box.ele;
        }else{
            Firework.box = {
                ele:document.querySelector(selector),
                selector:selector
            }
            this.box = Firework.box.ele;
        }
        this.type = type;
        this.init(x,y)
    }



封装一个运动的方法
function animation(ele,attroptions,callback){
    for(var attr in attroptions){
        attroptions[attr] ={
            target:attroptions[attr],
            inow:parseInt(getComputedStyle(ele)[attr])
        } 
    }
    clearInterval(ele.timer);
    ele.timer = setInterval(function(){
        for(var attr in attroptions ){
            var item = attroptions[attr]
            var target = item.target;
            var inow = item.inow;
            var speed = (target - inow)/10;
            speed = speed>0?Math.ceil(speed):Math.floor(speed);
            if(Math.abs(target - inow) <= Math.abs(speed)){
                ele.style[attr] = target+"px";
                delete attroptions[attr];
                for(var num  in attroptions){
                    return false;
                }
                clearTimeout(ele.timer);
                if(typeof callback === "function")callback();
            }else{
                attroptions[attr].inow += speed;
                ele.style[attr]  = attroptions[attr].inow+"px";
            }
        }
    },30)
}



编写原型方法
Firework.prototype = {
        constructor:Firework,
        //初始化
        init:function(x,y){
            //创建一个烟花
            this.ele = this.createFirework();
            //xy为鼠标落点
            this.x = x ;
            this.y = y;
            //maxXy为最大运动范围
            this.maxX = this.box.offsetWidth - this.ele.offsetWidth;
            this.maxY = this.box.offsetHeight - this.ele.offsetHeight;
            //初始化结束后  烟花随机颜色
            this.randomColor(this.ele);
            //烟花升空
            this.fireworkUp(this.ele);
        },
        //创造烟花
        createFirework:function(){
            var ele = document.createElement("div");
            ele.className = "fire";
            this.box.appendChild(ele);
            return ele;
        },
        //烟花升空
        fireworkUp:function(ele){
            ele.style.left = this.x + "px";
            //此处用到刚刚封装的运动方法
            animation(ele,{top:this.y},function(){
                ele.remove();
                this.fireworkBlast()
            }.bind(this));
        },
        //烟花爆炸
        fireworkBlast:function(){
            for(var i = 0 ; i < 20; i++){
                var ele = document.createElement("div");
                ele.className = "fire";
                ele.style.left = this.x + "px";
                ele.style.top = this.y + "px";
                this.box.appendChild(ele);
                ele.style.borderRadius = "50%";
                this.randomColor(ele);
                //判定一下输入的爆炸方式是原型烟花 还是散落烟花 由此更改获取的烟花位置
                animation(ele,this.type === "circle"?this.circleBlast(i,20): this.randomPosition(),function(cale){
                    cale.remove();
                }.bind(this,ele))
            }
        },
        //圆形爆炸位置
        circleBlast:function(i,total){
            var r = 200;
            var reg = 360 / total *i;
            var deg = Math.PI / 180 *reg;
            return {
                left:r * Math.cos(deg) + this.x ,
                top:r * Math.sin(deg) + this.y 
            }
        },
        //随机颜色
        randomPosition:function(){
            return {
                left : Math.random()*this.maxX,
                top : Math.random()*this.maxY
            }
        },
        randomColor:function(ele){
            var color =  "#" + parseInt(parseInt("ffffff",16)*Math.random()).toString(16).padStart(6,0);
            return ele.style.backgroundColor = color;
        }
    }



绑定事件
document.querySelector(".container").addEventListener("click",function(evt){
    var e = evt||event;
    new Firework(e.offsetX,e.offsetY,".container","circle")
    new Firework(e.offsetX,e.offsetY,".container")
})

全部代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
    .container{
        margin: 0 auto;
        height: 500px;
        width: 1200px;
        background: black;
        position: relative;
        overflow: hidden;
    }
    .fire{
        width: 10px;
        background: white;
        height: 10px;
        /* border-radius: 50%; */
        position: absolute;
        bottom: 0;
    }
    </style>
</head>
<body>
    <div class="container"></div>
    <script src="./utils.js"></script>
    <script>

    function animation(ele,attroptions,callback){
        for(var attr in attroptions){
            attroptions[attr] ={
                target:attroptions[attr],
                inow:parseInt(getComputedStyle(ele)[attr])
            } 
        }
        clearInterval(ele.timer);
        ele.timer = setInterval(function(){
            for(var attr in attroptions ){
                var item = attroptions[attr]
                var target = item.target;
                var inow = item.inow;
                var speed = (target - inow)/10;
                speed = speed>0?Math.ceil(speed):Math.floor(speed);
                if(Math.abs(target - inow) <= Math.abs(speed)){
                    ele.style[attr] = target+"px";
                    delete attroptions[attr];
                    for(var num  in attroptions){
                        return false;
                    }
                    clearTimeout(ele.timer);
                    if(typeof callback === "function")callback();
                }else{
                    attroptions[attr].inow += speed;
                    ele.style[attr]  = attroptions[attr].inow+"px";
                }
            }
        },30)
    }  

        function Firework(x,y,selector,type){
            if(Firework.box && selector === Firework.box.selector){
                this.box =  Firework.box.ele;
            }else{
                Firework.box = {
                    ele:document.querySelector(selector),
                    selector:selector
                }
                this.box = Firework.box.ele;
            }
            this.type = type;
            this.init(x,y)
        }

        Firework.prototype = {
            constructor:Firework,
            //初始化
            init:function(x,y){
                this.ele = this.createFirework();
                this.x = x ;
                this.y = y;
                this.maxX = this.box.offsetWidth - this.ele.offsetWidth;
                this.maxY = this.box.offsetHeight - this.ele.offsetHeight;
                this.randomColor(this.ele);
                this.fireworkUp(this.ele);
            },
            //创造烟花
            createFirework:function(){
                var ele = document.createElement("div");
                ele.className = "fire";
                this.box.appendChild(ele);
                return ele;
            },
            fireworkUp:function(ele){
                ele.style.left = this.x + "px";
                animation(ele,{top:this.y},function(){
                    ele.remove();
                    this.fireworkBlast()
                }.bind(this));
            },
            //烟花爆炸
            fireworkBlast:function(){
                for(var i = 0 ; i < 20; i++){
                    var ele = document.createElement("div");
                    ele.className = "fire";
                    ele.style.left = this.x + "px";
                    ele.style.top = this.y + "px";
                    this.box.appendChild(ele);
                    ele.style.borderRadius = "50%";
                    this.randomColor(ele);
                    animation(ele,this.type === "circle"?this.circleBlast(i,20): this.randomPosition(),function(cale){
                        cale.remove();
                    }.bind(this,ele))
                }
            },
            circleBlast:function(i,total){
                var r = 200;
                var reg = 360 / total *i;
                var deg = Math.PI / 180 *reg;
                return {
                    left:r * Math.cos(deg) + this.x ,
                    top:r * Math.sin(deg) + this.y 
                }
            },
            randomPosition:function(){
                return {
                    left : Math.random()*this.maxX,
                    top : Math.random()*this.maxY
                }
            },
            randomColor:function(ele){
                var color =  "#" + parseInt(parseInt("ffffff",16)*Math.random()).toString(16).padStart(6,0);
                return ele.style.backgroundColor = color;
            }
        }

        document.querySelector(".container").addEventListener("click",function(evt){
            var e = evt||event;
            new Firework(e.offsetX,e.offsetY,".container","circle")
            new Firework(e.offsetX,e.offsetY,".container")
        })
    </script>
</body>
</html>

————————————————
版权声明:本文为CSDN博主「SpongeBooob」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_41383900/article/details/105026768


NodeJS服务总是崩溃的解决办法

seo达人

许多人都有这样一种映像,NodeJS比较快; 但是因为其是单线程,所以它不稳定,有点不安全,不适合处理复杂业务; 它比较适合对并发要求比较高,而且简单的业务场景。 

在Express的作者的TJ Holowaychuk的 告别Node.js一文中列举了以下罪状: 

Farewell NodeJS (TJ Holowaychuk) 

•   you may get duplicate callbacks 
•   you may not get a callback at all (lost in limbo) 
•   you may get out-of-band errors 
•   emitters may get multiple “error” events 
•   missing “error” events sends everything to hell 
•   often unsure what requires “error” handlers 
•   “error” handlers are very verbose 
•   callbacks suck 

其实这几条主要吐嘈了两点: node.js错误处理很扯蛋,node.js的回调也很扯蛋。

 

 

事实上呢?

 


事实上NodeJS里程确实有“脆弱”的一面,单线程的某处产生了“未处理的”异常确实会导致整个Node.JS的崩溃退出,来看个例子, 这里有一个node-error.js的文件: 

 

var http = require('http');

var server = http.createServer(function (req, res) {

  //这里有个错误,params 是 undefined
  var ok = req.params.ok;

  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World
');
});

server.listen(8080, '127.0.0.1');

console.log('Server running at http://127.0.0.1:8080/');


启动服务,并在地址栏测试一下发现 http://127.0.0.1:8080/  不出所料,node崩溃了 


 

$ node node-error
Server running at http://127.0.0.1:8080/

c:githubscript
ode-error.js:5
  var ok = req.params.ok;
                     ^
TypeError: Cannot read property 'ok' of undefined
    at Server.<anonymous> (c:githubscript
ode-error.js:5:22)
    at Server.EventEmitter.emit (events.js:98:17)
    at HTTPParser.parser.onIncoming (http.js:2108:12)
    at HTTPParser.parserOnHeadersComplete [as onHeadersComplete] (http.js:121:23)
    at Socket.socket.ondata (http.js:1966:22)
    at TCP.onread (net.js:525:27)



 

怎么解决呢?


其实Node.JS发展到今天,如果连这个问题都解决不了,那估计早就没人用了。 

 

使用uncaughtException


我们可以uncaughtException来全局捕获未捕获的Error,同时你还可以将此函数的调用栈打印出来,捕获之后可以有效防止node进程退出,如: 

 

process.on('uncaughtException', function (err) {
  //打印出错误
  console.log(err);
  //打印出错误的调用栈方便调试
  console.log(err.stack);
});


这相当于在node进程内部进行守护, 但这种方法很多人都是不提倡的,说明你还不能完全掌控Node.JS的异常。 

 

使用 try/catch


我们还可以在回调前加try/catch,同样确保线程的安全。 

 

var http = require('http');

http.createServer(function(req, res) {
  try {
    handler(req, res);
  } catch(e) {
    console.log('
', e, '
', e.stack);
    try {
      res.end(e.stack);
    } catch(e) { }
  }
}).listen(8080, '127.0.0.1');

console.log('Server running at http://127.0.0.1:8080/');

var handler = function (req, res) {
  //Error Popuped
  var name = req.params.name;

  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello ' + name);
};


这种方案的好处是,可以将错误和调用栈直接输出到当前发生的网页上。 

 

集成到框架中


标准的HTTP响应处理会经历一系列的Middleware(HttpModule),最终到达Handler,如下图所示: 

\ 


这 些Middleware和Handler在NodeJS中都有一个特点,他们都是回调函数,而回调函数中是唯一会让Node在运行时崩溃的地方。根据这个 特点,我们只需要在框架中集成一处try/catch就可以相对完美地解决异常问题,而且不会影响其它用户的请求request。 

事实上现在的NodeJS WEB框架几乎都是这么做的,如 OurJS开源博客所基于的 WebSvr 

就有这么一处异常处理代码: 

 

Line: 207

  try {
    handler(req, res);
  } catch(err) {
    var errorMsg
      = '
'
      + 'Error ' + new Date().toISOString() + ' ' + req.url
      + '
'
      + err.stack || err.message || 'unknow error'
      + '
'
      ;

    console.error(errorMsg);
    Settings.showError
      ? res.end('<pre>' + errorMsg + '</pre>')
      : res.end();
  }


那么不在回调中产生的错误怎么办?不必担心,其实这样的node程序根本就起不起来。 

此外node自带的 cluster 也有一定的容错能力,它跟nginx的worker很类似,但消耗资源(内存)略大,编程也不是很方便,OurJS并没有采用此种设计。 

 

守护NodeJS进程和记录错误日志


现 在已经基本上解决了Node.JS因异常而崩溃的问题,不过任何平台都不是100%可靠的,还有一些错误是从Node底层抛出的,有些异常 try/catch和uncaughtException都无法捕获。之前在运行ourjs的时侯,会偶尔碰到底层抛出的文件流读取异常,这就是一个底层 libuv的BUG,node.js在0.10.21中进行了修复。 

面对这种情况,我们就应该为nodejs应用添加守护进程,让NodeJS遭遇异常崩溃以后能马上复活。 

另外,还应该把这些产生的异常记录到日志中,并让异常永远不再发生。 

 

使用node来守护node


node-forever 提供了守护的功能和LOG日志记录功能。 

安装非常容易 

 

[sudo] npm install forever


使用也很简单 

 

$ forever start simple-server.js
$ forever list
  [0] simple-server.js [ 24597, 24596 ]


还可以看日志 

 

forever -o out.log -e err.log my-script.js


 

使用shell启动脚本守护node


使用node来守护的话资源开销可能会有点大,而且也会略显复杂,OurJS直接在开机启动脚本来进程线程守护。 

如在debian中放置的 ourjs 开机启动文件: /etc/init.d/ourjs 

这个文件非常简单,只有启动的选项,守护的核心功能是由一个无限循环 while true; 来实现的,为了防止过于密集的错误阻塞进程,每次错误后间隔1秒重启服务 

 

WEB_DIR='/var/www/ourjs'
WEB_APP='svr/ourjs.js'

#location of node you want to use
NODE_EXE=/root/local/bin/node

while true; do
    {
        $NODE_EXE $WEB_DIR/$WEB_APP config.magazine.js
        echo "Stopped unexpected, restarting 

"
    } 2>> $WEB_DIR/error.log
    sleep 1
done


 

错误日志记录也非常简单,直接将此进程控制台当中的错误输出到error.log文件即可: 2>> $WEB_DIR/error.log  这一行, 2 代表 Error。

JSP的刨根问底

前端达人

JSP的刨根问底

  • 一.概念
  • 二.原理
  • 三.脚本
  • 四.内置对象
  • 五.注释
  • 六.编译指令
  • 七.动作指令


  • 点击查看原图


    这篇文章从一个初学者的角度,复习一波JSP。






    一.概念
    Java Server Pages: java服务器端页面

    可以理解为:一个特殊的页面,其中既可以指定定义html标签,又可以定义java代码
    用于简化书写!!!
    二.原理
    本质是一个Servlet

    三.脚本
    定义:Jsp定义java代码的方式

    <% 代码 %>:定义的java代码,在service方法中。service方法中可以定义什么,该脚本中就可以定义什么。
    <%! 代码 %>:定义的java代码,在jsp转换后的java类的成员位置。
    <%= 代码 %>:定义的java代码,会输出到页面上。输出语句中可以定义什么,该脚本中就可以定义什么。
    四.内置对象
    对象名 实现接口或继承类 作用
    PageContext 当前页面共享数据,还可以获取其他八个内置对象
    request HttpServletRequest 一次请求访问的多个资源(转发)
    session HttpSession 一次会话的多个请求间
    application ServletContext 所有用户间共享数据
    response HttpServletResponse 响应对象
    page Object 当前页面(Servlet)的对象 this
    out JspWriter 输出对象,数据输出到页面上
    config ServletConfig Servlet的配置对象
    expection Throwable 异常对象
    五.注释
    1.html注释
    <!-- -->:只能注释html代码片段
    2.jsp注释
    <%-- --%>:可以注释所有

    六.编译指令
    作用
    用于配置JSP页面,导入资源文件

    格式
    <%@ 指令名称 属性名1=属性值1 属性名2=属性值2 ... %>
    分类
    1.page
    配置JSP页面的
    1. contentType:等同于response.setContentType()
    *设置响应体的mime类型以及字符集
    * 设置当前jsp页面的编码(只能是高级的IDE才能生效,如果使用低级工具,则需要设置pageEncoding属性设置当前页面的字符集)
    2.import:导包
    3. errorPage:当前页面发生异常后,会自动跳转到指定的错误页面
    4.isErrorPage:标识当前也是是否是错误页面。
    * true:是,可以使用内置对象exception
    * false:否。默认值。不可以使用内置对象exception
    2.include
    页面包含的。导入页面的资源文件

     <%@include file="top.jsp"%>
    3.导入资源
    导入资源

     <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
      prefix:前缀,自定义的
    1
    七.动作指令
    作用
    动作指令与编译指令不间,编译指令是通知 Servlet 引擎的处理消息,而动作指令只是运行时的脚本动作。编译指令在将JSP 编译成 Servlet 时起作用:处理指令通常可替换成 Java脚本,是 JSP脚本的标准化写法。

    分类
    指令 作用
    jsp:forward 执行页面转向,将请求的处理转发到下一个页面。
    jsp:param 用于传递参数,必须与其他支持参数曲标签一起使用。
    jsp:include 用于动态引入一个 JSP 页面。
    jsp:plugin 用于下载 JavaBean 或 Applet 到客户端执行。
    jsp:useBean 使用 JavaBean。
    jsp:setProperty 修改 JavaBean 实例的属性值。
    jsp:getProperty 获取 JavaBean 实例的属性值。
    具体细节:
    jsp:forward:
    动作把请求转到另外的页面。可以转发静态的HTML页面,也可以转发动态的JSP页面,或者转发到容器中的servlet jsp:forward标记只有一个属性page。 page属性包含的是一个相对URL。 page的值既可以直接给出,也可以在请求的时候动态计算。

    jsp:param
    用于设定参数值,这个指令不能单独使用 可以与以下三个指令结合使用:
    jsp:include :用于将参数值出入被导入页面
    jsp:forword : 用于将参数值传入被转向页面
    jsp:plugin : 用于将参数值传入页面中javaBean的实例

    jsp:include
    (拿目标页面插入原有页面)该动作是一个动态的include指令,也用于带入某个页面,他不会导入被include页面的编译指令,仅仅导入页面的body内容插入到本页面
    该动作把指定文件插入正在生成的页面。其语法如下:   flush:用于指定输出缓存是否转移到被导入的文件中, true:包含在被导入的文件中 false:包含在源文件中
    前面已经介绍过include指令,它是在JSP文件被转换成Servlet的时候引入文件,而这里的jsp:include动作不同,插入文件的时间是在页面被请求的时候。j
    sp:include动作的文件引入时间决定了它的效率要稍微差一点,而且被引用文件不能包含某些JSP代码(例如不能设置HTTP头),但它的灵活性却要好得多。
    jsp:plugin

    用于下载服务器端的javaBean或applet到客户端)
    jsp:plugin动作用来根据浏览器的类型,插入通过Java插件运行Java Applet所必需的OBJECT或EMBED元素。

    <jsp:plugin  
      type="bean | applet"   : 被执行的java程序的类型
      code="classFileName" :被执行的文件名,必须以  .class 结尾
      codebase="classFileDirectoryName"   :被执行文件的所在目录
      [ name="instanceName" ] :给程序起一个名字用来标识该程序
      [ archive="URIToArchive, ..." ] :指向一些要预先载入的将要使用到的类
      [ align="bottom | top | middle | left | right" ] :
      [ height="displayPixels" ]
      [ width="displayPixels" ]
      [ hspace="leftRightPixels" ] 
      [ vspace="topBottomPixels" ]
      [ jreversion="JREVersionNumber | 1.1" ]   :能正确运行改程序必须的JRE的版本
      [ nsplug inurl="URLToPlugin" ]  
      [ iepluginurl="URLToPlugin" ] >
      [ <jsp:params>
      [ <jsp:param name="parameterName" value="{parameterValue | <%= expression %>}" /> ]+
      </jsp:params> ]
      [ <jsp:fallback> text message for user </jsp:fallback> ]  :当不能正确显示该Applet时,显示该指令中的文本提示
     <jsp:plugin>
    



    jsp:useBean
    useBean:用于在jsp页面中初始化一个java实例(如果多个jsp中需要重复使用某段代码,可以把这段代码定义成java类在页面中引用)
    jsp:useBean动作用来装载一个将在JSP页面中使用的JavaBean。这个功能非常有用,因为它使得我们既可以发挥Java组件重用的优势,同时也避免了损失JSP区别于Servlet的方便性。
    jsp:useBean动作最简单的语法为:<jsp:useBean id=“JavaBean的名称” class=“package.class"包名.类名” scope=“有效范围”/>

    这行代码的含义是:“创建一个由class属性指定的类的实例,然后把它绑定到其名字由id属性给出的变量上”。不过,就象我们接下来会看到的,定义一个scope属性可以让Bean关联到更多的页面,它可接受四个值:request、session、page、application。此时,jsp:useBean动作只有在不存在同样id和scope的Bean时才创建新的对象实例,同时,获得现有Bean的引用就变得很有必要。
    获得Bean实例之后,要修改Bean的属性既可以通过jsp:setProperty动作进行,也可以在Scriptlet中利用id属性所命名的对象变量,通过调用该对象的方法显式地修改其属性。这使我们想起,当我们说“某个Bean有一个类型为X的属性foo”时,就意味着“这个类有一个返回值类型为X的getFoo方法,还有一个setFoo方法以X类型的值为参数”。  有关jsp:setProperty动作的详细情况在后面讨论。但现在必须了解的是,我们既可以通过jsp:setProperty动作的value属性直接提供一个值,也可以通过param属性声明Bean的属性值来自指定的请求参数,还可以列出Bean属性表明它的值应该来自请求参数中的同名变量。
    在JSP表达式或Scriptlet中读取Bean属性通过调用相应的getXXX方法实现,或者更一般地,使用jsp:getProperty动作。
    注意,包含Bean的类文件应该放到服务器正式存放Java类的目录下,而不是保留给修改后能够自动装载的类的目录。例如,对于Java Web
    Server来说,Bean和所有Bean用到的类都应该放入classes目录,或者封装进jar文件后放入lib目录,但不应该放到servlets下。
    id:javaBean的实例名 class: javaBean的实现类 scope:指定javaBean实例的生存范围
    page:javaBean仅在该页面有效 request:javaBean在本次请求中有效 session:
    javaBean在本次session内有效 application:
    javaBean在本应用内一直有效  下面是一个很简单的例子,它的功能是装载一个Bean,然后设置/读取它的message属性。
    关于jsp:useBean的进一步说明   使用Bean最简单的方法是先用下面的代码装载Bean:   <jsp:useBean id=“name” class=“package.class” />
    然后通过jsp:setProperty和jsp:getProperty修改和提取Bean的属性。 不过有两点必须注意。   第一,我们还可以用下面这种格式实例化Bean: <jsp:useBean …>   Body   </jsp:useBean>
    它的意思是,只有当第一次实例化Bean时才执行Body部分,如果是利用现有的Bean实例则不执行Body部分。正如下面将要介绍的,jsp:useBean并非总是意味着创建一个新的Bean实例。
    第二,除了id和class外,jsp:useBean还有其他三个属性,即:scope、type、beanName。
    id:命名引用该Bean的变量。如果能够找到id和scope相同的Bean实例,jsp:useBean动作将使用已有的Bean实例而不是创建新的实例。
    class:指定Bean的完整包名。
    scope:指定Bean在哪种上下文内可用,可以取下面的四个值之一:page、request、session和application。  默认值是page,表示该Bean只在当前页面内可用(保存在当前页面的PageContext内)。
    request表示该Bean在当前的客户请求内有效(保存在ServletRequest对象内)。
    session表示该Bean对当前HttpSession内的所有页面都有效。
    最后,如果取值application,则表示该Bean对所有具有相同ServletContext的页面都有效。
    scope之所以很重要,是因为jsp:useBean只有在不存在具有相同id和scope的对象时才会实例化新的对象;
    如果已有id和scope都相同的对象则直接使用已有的对象,此时jsp:useBean开始标记和结束标记之间的任何内容都将被忽略。
    type:指定引用该对象的变量的类型,它必须是Bean类的名字、超类名字、该类所实现的接口名字之一。请记住变量的名字是由id属性指定的。
    beanName:指定Bean的名字。如果提供了type属性和beanName属性,允许省略class属性。

    jsp:setProperty
    jsp:setProperty用来设置已经实例化的Bean对象的属性,有两种用法。
    首先,你可以在jsp:useBean元素的外面(后面)使用jsp:setProperty,    …

    第二种用法是把jsp:setProperty放入jsp:useBean元素的内部, …

    jsp:setProperty动作有下面四个属性:name:表示要设置属性的是哪个Bean。  property:表示要设置哪个属性。有一个特殊用法:如果property的值是"",表示所有名字和Bean属性名字匹配的请求参数都将被传递给相应的属性set方法。  value:value属性是可选的。该属性用来指定Bean属性的值。字符串数据会在目标类中通过标准的valueOf方法自动转换成数字、boolean、Boolean、byte、Byte、char、Character。例如,boolean和Boolean类型的属性值(比如“true”)通过Boolean.valueOf转换,int和Integer类型的属性值(比如"42")通过Integer.valueOf转换。  value和param不能同时使用,但可以使用其中任意一个。  Param:param是可选的。它指定用哪个请求参数作为Bean属性的值。如果当前请求没有参数,则什么事情也不做,系统不会把null传递给Bean属性的set方法。因此,你可以让Bean自己提供默认属性值,只有当请求参数明确指定了新值时才修改默认属性值。  例如,下面的代码片断表示:如果存在numItems请求参数的话,把numberOfItems属性的值设置为请求参数numItems的值;否则什么也不做。    如果同时省略value和param,其效果相当于提供一个param且其值等于property的值。进一步利用这种借助请求参数和属性名字相同进行自动赋值的思想,你还可以在property(Bean属性的名字)中指定“”,然后省略value和param。此时,服务器会查看所有的Bean属性和请求参数,如果两者名字相同则自动赋值。  下面是一个利用JavaBean计算素数的例子。如果请求中有一个numDigits参数,则该值被传递给Bean的numDigits属性;numPrimes也类似。  JspPrimes.jsp

    20200321215032100.jpg
    jsp:getProperty
    jsp:getProperty动作提取指定Bean属性的值,转换成字符串,然后输出。
    jsp:getProperty有两个必需的属性,即:name,表示Bean的名字;property,表示要提取哪个属性的值。

    END!!!有什么意见可以提出来!
    长路漫漫,JAVA为伴!!!
    ————————————————
    版权声明:本文为CSDN博主「福尔摩东」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/qq_43688587/article/details/105017469

label和span标签设置宽度width无效的解决办法

前端达人

如何用CSS使label标签等宽?

<div><label>密码</label><input type="password" /></div>
<div><label>确认密码</label><input type="password" /></div>
如何对齐呢?加空格的方法不好哦。(因为label中的字数不一样,所以页面显示效果不对齐)
问题原因及解决办法:

label默认为内联元素,元素前后没有换行符,并且不可以设置宽度。

如果要为label设置宽度,则需要改变label的display属性,使其变为一个块级元素。

方法如下:

1.增加inline-block属性值,将label标签变为行内块元素(css2.1新增)

     {display:inline-block;}

2.增加width属性,如将宽度设置为100px
    label{width:100px;display:inline-block;}

3.添加好后页面上所有的label标签会变为100pxv



JavaScript中的混淆器

随着 AJAX 和富界面技术的发展,Javascript 在 Web 应用上的重要性越来越高,Javascript 代码的复杂性、功能和技术含量也越来越高,对Javascript 代码保护的需要也越来越迫切。



压缩 compress: 去掉空格,换行,注释等,格式紧凑,节约存储空间。



混淆 obfuscate/garble:替换变量名或方法名,让js不容易看懂。也做到了压缩的效果。



加密 encrypt:一般用eval方法加密,效果与混淆相似。也做到了压缩的效果。



我们可以通过工具进行混淆,通过工具也是目前最好的方式。推荐一个很好的混淆工具: JSObfuscator By Unest


20200321102359879.png


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

版权声明:本文为CSDN博主「刘亦枫」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/liuyifeng0000/article/details/105004732




"从客户端中检测到有潜在危险的 Request.Form 值"的解决方案汇总

seo达人

在一个asp.net 的项目中,前端通过ajax将富文本中的文字内容post到服务端的一个ashx中,在ashx中尝试读取参数值时,

结果报错:“从客户端中检测到有潜在危险的 Request.Form 值”

#事故分析
由于在asp.net中,Request提交时出现有html代码字符串时,程序系统会认为其具有潜在危险的值。会报出“从客户端 中检测到有潜在危险的Request.Form值”这样的Error。

而富文本中的内容是包含html代码的,所以...

#解决方案:
1、前端对富文本字符串进行encodeURI编码,服务端进行HttpUtility.UrlDecode解码操作;
前端代码:

var str = '<p><span style="color: #00B0F0;"><em><strong>我想留在你的身边,</strong></em></span><br/></p><p><span style="color: #7030A0;"><strong><span style="text-decoration: underline;">深情款款多么可怜;</span></strong></span></p>';
    $(function() {
        $.ajax({
            type: "post",
            url: "TestHandle.ashx",
            data: { Title: 'jack', Content: encodeURI(str) },
            success: function (data) {
                $("#div").html(data);
            }
        });
    });
后端代码:

    public void ProcessRequest(HttpContext context)
    {
        string str = context.Request["content"];
        string content = HttpUtility.UrlDecode(str);
        context.Response.ContentType = "text/plain";
        context.Response.Write(content);
    }
效果图:

2、前端不以form的方式提交,直接以json方式提交,服务端从request的body中读取数据,然后反序列化,得到信息;
前端代码:

    var str = '<p><span style="color: #00B0F0;"><em><strong>我想留在你的身边,</strong></em></span><br/></p><p><span style="color: #7030A0;"><strong><span style="text-decoration: underline;">深情款款多么可怜;</span></strong></span></p>';
    var temp = { Title: 'jack', Content: str };
    $.ajax({
        type: "post",
        url: "TestHandle.ashx",
        contentType:"application/json;charset=utf-8",
        data: JSON.stringify(temp),
        success: function (data) {
            $("#div").html(data);
        }
    });
后端代码:

    string bodyText;
    using (var bodyReader = new System.IO.StreamReader(context.Request.InputStream))
    {
        bodyText = bodyReader.ReadToEnd();
    }
    dynamic bodyObj = JsonConvert.DeserializeObject(bodyText);
 
    context.Response.ContentType = "text/plain";
    context.Response.Write(bodyObj.Content);
效果图:

#其他场景的解决方案:
1、aspx页面,当前页面进行form提交
打开当前.aspx页面,页头加上代码:validateRequest=”false”,如:

<%@ Page Language="C#" ValidateRequest="false" AutoEventWireup="false" CodeFile="default.aspx.cs" Inherits="default" %>
该方法不推荐,还有一种修改web.config配置文件的方法,强烈不推荐,就不写在这里了;

2、在ASP.NET MVC中的解决方案
1)、针对某个实体类的单个字段设置 [AllowHtml] ,这样提交的时候,系统就会放过该字段。

2)、前端代码:

    var str = '<p><span style="color: #00B0F0;"><em><strong>我想留在你的身边,</strong></em></span><br/></p><p><span style="color: #7030A0;"><strong><span style="text-decoration: underline;">深情款款多么可怜;</span></strong></span></p>';
    $(function () {
        $.ajax({
            type: "post",
            url: "Home/Test",
            data: { Title: 'jack', Content: str },
            success: function (data) {
                $("#div").html(data.ok);
            }
        });
    });
3)、后端代码:

    public class NewInfo
    {
        public string Title { get; set; }
        [AllowHtml]
        public string Content { get; set; }
    }
 #写在最后
 该文只是浅显的总结一下,其中涉及的xss方面,没有详细考虑,欢迎指正!

JavaScript中Array数组的some()函数的详解

seo达人

前言

开发中,经常会用到js的Array数组的各种迭代函数map(),filter(),some(),every(),forEach(),find() findIndex(),也是在ES6中新增一些遍历函数。同样是不是也是一道面试题,说说ES6新增的一些新特性????



✍开始正文some()函数



✍一、对some()函数的定义:



some():用于检测数组中的元素是否满足指定条件(函数提供);

some()方法会依次执行数组中的每一个元素:



如果有一个元素满足条件,则表达式返回true,剩余的元素不会再执行检测。

如果没有满足条件的元素,则返回false。

注意:



some()不会对空数组进行检测。

some() 不会改变原始数组。

✍二、浏览器支持

表格中的数字表示支持该方法的第一个浏览器的版本号。



✍三、语法



array.some(function(currentValue,index,arr),thisValue)

1

参数说明:



✍三、示例



<script>

var ages = [4, 12, 16, 20];



function checkAdult(age) {

    return age >= document.getElementById("ageToCheck").value;

}



function myFunction() {

    document.getElementById("demo").innerHTML = ages.some(checkAdult);

}

</script>


通过JavaScript制作table表格隔行变色

seo达人

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<title>隔行变色</title>

</head>

<body>

<table id="mytable" align="center" width="80%" border="1">

<tr bgcolor="#cccccc">

<td>aaa</td>

<td>aaa</td>

<td>aaa</td>

</tr>

<tr>

<td>bbb</td>

<td>bbb</td>

<td>bbb</td>

</tr>

<tr>

<td>ccc</td>

<td>ccc</td>

<td>ccc</td>

</tr>

</table>

<script type="text/javascript">

window.onload=function(){

//获取mytable中标签名为tr的字节点

mytable=document.getElementById("mytable");

trs=mytable.getElementsByTagName("tr");

len=trs.length;

flag=true;

for(i=0;i<len;i++){

if(flag){

//每隔一行设置背景色

var tr=document.getElementsByTagName("tr")[i].setAttribute("bgcolor","#cccccc");

flag=false;

}else{

flag=true;

}

}

}

</script>

</body>

</html>


日历

链接

个人资料

蓝蓝设计的小编 http://www.lanlanwork.com

存档