『前端积累』web前端代码片段、学习笔记、指令工具整理

JavaScript

Ajax用jsonp方式跨域发送请求示例

众所周知,Ajax是通过创建XMLHttpRequest对象或ActiveXObject来连接服务器、发送请求以及响应数据,但它却不能跨域。而在分布式系统中我们又需要跨域发送接受数据,于是jsonp出现了...

它是一种跨域请求方式,主要利用了script标签里的src属性,该属性可以跨域发送请求,然后服务器返回js代码,网页端便响应其信息,然后我们可以对其传过来的js代码做处理提取其中的信息。

jsonp发送请求只需在src后面添加“?callback=函数名”就可以,例如“http://www.item.com/list?callback=myfunction",则只需在服务端接受参数myfunction并将函数名与想要返回的数据拼接就可以例如在java中响应该请求,可以获取参数callback的值myfunction,再拼接成myfunction+"("+data+")"格式返回就行,在前端写同名函数接受data并处理就可以了。但在jquery中对jsonp进行了封装,返回函数就是success,数据也用success接受。

例如,前端代码:

//发送请求  
$.ajax({  
   //url:"http://localhost:8081/rest/itemcat/list?callback=getMessage",  
    url:"http://localhost:8081/rest/itemcat/message",      
    type:"get",  
    cache:false,  
    dataType:"jsonp",  
    jsonp:"callback", //这里定义了callback的参数名称,以便服务获取callback的函数名即getMessage  
    jsonpCallback:"getMessage", //这里定义了jsonp的回调函数  
    success:function(data){  
        alert("success:"+data);  
    },  
    error:function(){  
        alert("发生异常");  
    }  
});  

function getMessage(jsonp){  
    alert("message:"+jsonp);  
}

这样发出的请求为:http://localhost:8081/rest/itemcat/message?callback=getMessage
jsonp:"callback",
jsonpCallback:"getMessage",
这两个参数的值会自动拼接在url后面,所以用jquery$.ajax方法发出的url可以不用在后面添加callback=getMessag,返回函数则变为了success而不是getMessage

前端使用RSA加密算法(jsencrypt.js)对用户名密码加密传输

RSA加密算法被称为"非对称加密算法"。

  • (1)乙方生成两把密钥(公钥和私钥)。公钥是公开的,任何人都可以获得,私钥则是保密的。
  • (2)甲方获取乙方的公钥,然后用它对信息加密。
  • (3)乙方得到加密后的信息,用私钥解密。

如果公钥加密的信息只有私钥解得开,那么只要私钥不泄漏,通信就是安全的。

示例代码:

<script src="./js/jsencrypt.min.js"></script>
<script type="text/javascript">
$.ajax({
	url: "/getPublicKey", // 获取公钥
	type: "post",
	dataType: "text",
	success: function(data) {
		var publicKey = data;
		if (publicKey == null) {
			console.log("获取publicKey失败")
		} else {
			var encrypt = new JSEncrypt();
			encrypt.setPublicKey(publicKey);

			$.ajax({
				url: "/login",
				type: "post",
				data: {
					username: encrypt.encrypt($("#username").val()),
					password: encrypt.encrypt($("#password").val()),
					code: encrypt.encrypt($("#code").val())
				},
				success: function(item) {
					// 成功后的操作
				}
			});
		}
	}
});
</script>

通过事件捕获实现登录拦截思路demo

document.addEventListener('click',function(event){
    if(event.target.tagName.toLowerCase() == 'a') {
        // 在此阶段可以判断是否登录,未登录进行阻止捕获
        if (event.preventDefault) {
            event.preventDefault(); 
       } else {
            event.returnValue = false;
      }
    }
},true);

苹果手机 微信调用百度地图Javascript API 频繁闪退问题

最近在网页中调用百度地图API js大众版,但是在IOS8系统中,缩放的时候频繁闪退,安卓手机没有这个问题!

在网上查询了下,有网友回答说不要频繁的去new marker,而是初始化话一定量的marker,然后setPosition。但是我的页面中匹配当前城市 注入marker也没有几个,所以排除这答案。

最后发现有网友说版本不稳定引起的,于是把百度地图API回退到了1.5,结果还真是可以了。

百度地图API调用:

<script type="text/javascript" src="http://api.map.baidu.com/api?v=1.5&ak=dGg7NKEkMCp8j1pWHCHZ3nhk"></script>

pdf.js官网基本代码demo笔记

// atob() is used to convert base64 encoded PDF to binary-like data.
// (See also https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/
// Base64_encoding_and_decoding.)
var pdfData = atob(
  'JVBERi0xLjcKCjEgMCBvYmogICUgZW50cnkgcG9pbnQKPDwKICAvVHlwZSAvQ2F0YWxvZwog' +
  'IC9QYWdlcyAyIDAgUgo+PgplbmRvYmoKCjIgMCBvYmoKPDwKICAvVHlwZSAvUGFnZXMKICAv' +
  'TWVkaWFCb3ggWyAwIDAgMjAwIDIwMCBdCiAgL0NvdW50IDEKICAvS2lkcyBbIDMgMCBSIF0K' +
  'Pj4KZW5kb2JqCgozIDAgb2JqCjw8CiAgL1R5cGUgL1BhZ2UKICAvUGFyZW50IDIgMCBSCiAg' +
  'L1Jlc291cmNlcyA8PAogICAgL0ZvbnQgPDwKICAgICAgL0YxIDQgMCBSIAogICAgPj4KICA+' +
  'PgogIC9Db250ZW50cyA1IDAgUgo+PgplbmRvYmoKCjQgMCBvYmoKPDwKICAvVHlwZSAvRm9u' +
  'dAogIC9TdWJ0eXBlIC9UeXBlMQogIC9CYXNlRm9udCAvVGltZXMtUm9tYW4KPj4KZW5kb2Jq' +
  'Cgo1IDAgb2JqICAlIHBhZ2UgY29udGVudAo8PAogIC9MZW5ndGggNDQKPj4Kc3RyZWFtCkJU' +
  'CjcwIDUwIFRECi9GMSAxMiBUZgooSGVsbG8sIHdvcmxkISkgVGoKRVQKZW5kc3RyZWFtCmVu' +
  'ZG9iagoKeHJlZgowIDYKMDAwMDAwMDAwMCA2NTUzNSBmIAowMDAwMDAwMDEwIDAwMDAwIG4g' +
  'CjAwMDAwMDAwNzkgMDAwMDAgbiAKMDAwMDAwMDE3MyAwMDAwMCBuIAowMDAwMDAwMzAxIDAw' +
  'MDAwIG4gCjAwMDAwMDAzODAgMDAwMDAgbiAKdHJhaWxlcgo8PAogIC9TaXplIDYKICAvUm9v' +
  'dCAxIDAgUgo+PgpzdGFydHhyZWYKNDkyCiUlRU9G');

// Loaded via <script> tag, create shortcut to access PDF.js exports.
var pdfjsLib = window['pdfjs-dist/build/pdf'];

// The workerSrc property shall be specified.
pdfjsLib.GlobalWorkerOptions.workerSrc = '//mozilla.github.io/pdf.js/build/pdf.worker.js';

// Using DocumentInitParameters object to load binary data.
var loadingTask = pdfjsLib.getDocument({data: pdfData});
loadingTask.promise.then(function(pdf) {
  console.log('PDF loaded');
  
  // Fetch the first page
  var pageNumber = 1;
  pdf.getPage(pageNumber).then(function(page) {
    console.log('Page loaded');
    
    var scale = 1.5;
    var viewport = page.getViewport(scale);

    // Prepare canvas using PDF page dimensions
    var canvas = document.getElementById('the-canvas');
    var context = canvas.getContext('2d');
    canvas.height = viewport.height;
    canvas.width = viewport.width;

    // Render PDF page into canvas context
    var renderContext = {
      canvasContext: context,
      viewport: viewport
    };
    var renderTask = page.render(renderContext);
    renderTask.then(function () {
      console.log('Page rendered');
    });
  });
}, function (reason) {
  // PDF loading error
  console.error(reason);
});

设置二级域名cookie共享

也即是把cookie的domain设置为顶级域名。

function getdomain(){
    var domain = document.domain;
    var ip = /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/;
    if(ip.test(domain)){
        return domain;
    }else{
        return document.domain.split('.').slice(1).join('.');
    }
}
var firstDomainName = getdomain();
document.cookie="userid=888abc;domain="+firstDomainName+";path=/";

二进制转base64

// 二进制转base64
export function arraybufferToBase64(buffer) {
    let  binary = '';
    let bytes = new Uint8Array(buffer);
    let len = bytes.byteLength;
    for (var i = 0; i < len; i++) {
        binary += String.fromCharCode(bytes[i]);
    }
   return 'data:image/png;base64,' + window.btoa(binary);
}

base64转文件(file对象)

// base64转文件
export function base64toFile(dataurl, filename = "file") {
  let arr = dataurl.split(',');
  let mime = arr[0].match(/:(.*?);/)[1];
  let suffix = mime.split('/')[1];
  let bstr = window.atob(arr[1]);
  let n = bstr.length;
  let u8arr = new Uint8Array(n);
  while(n--){
      u8arr[n] = bstr.charCodeAt(n);
  }
  return new File([u8arr], `${filename}.${suffix}`, {type: mime});
}

文件下载失败,将Blob对象转换为Json,处理异常错误?

捕获异常:

/** 导出文件流成功失败分别干干什么
 * @param {String} res 文件流或者JSON对象(错误情况下)
 * @param {Boolean} blob res资源是否是blob对象,文件流 默认不传递该参数
 *
 * */
export function downStreamCheck(res, blob) {
  let result = {};
  return new Promise((resolve, reject) => {
    let reader = new FileReader();
    reader.onload = e => {
      try {
        result = JSON.parse(e.target.result);
      } catch (e) {
        // console.log(e)
      } finally {
        if (typeof result.code !== 'undefined') { // 返回错误对象
          Message({
            message: result.message,
            type: 'error',
            duration: 5 * 1000
          });
        } else {
          resolve();
        }
      }
    }
    if (!blob) {
      reader.readAsText(new Blob([res.data], {
        type: 'application/octet-stream'
      }));
    } else {
      reader.readAsText(res.data);
    }
  })
}

调用方式:

 this.downStreamCheck(result).then(() => {
    //导出文件成功后的操作
    this.result=result;
})

问题地址:处理文件下载失败,如何将Blob对象转换为Json?
《参考:FileReader》

获取响应头部返回的文件名

一般下载的文件都需要从响应头部读取文件名,如下代码:

/** 从响应头部读取文件名称
 * @param {res}  response
 * */
export function responseFileName(res) {
  if (res && res.headers) {
    let resultFileName = decodeURI(res.headers['content-disposition']);
    return resultFileName.substring(resultFileName.indexOf('=')).substring(1);
  }
  return '';
}

模拟a标签实现接口下载

如果返回的正常的文件流一般模拟a标签实现下载,如下:

/**
 * @param {String} resource 文件流
 * @param {String} fileType 文件类型
 * @param {String} fileName 文件名 (可以响应头部读取文件名,如下)
 *  let resultFileName = res.headers['content-disposition'];
 *  let name = resultFileName.substring(resultFileName.indexOf('=')).substring(1);
 * 使用方式 this.$downloadBlob(data,'application/octet-stream','download.zip');其中文件名可以从响应头截取
 *
 * */
export function downloadBlob(resource, fileType, fileName) {
  var data = new Blob([resource], {
    type: fileType
  });
  if ('download' in document.createElement('a')) { //非IE
    var downloadUrl = window.URL.createObjectURL(data);
    var anchor = document.createElement("a");
    anchor.href = downloadUrl;
    anchor.download = fileName;
    anchor.style.display = 'none';
    document.body.appendChild(anchor);
    anchor.click();
    window.URL.revokeObjectURL(anchor.href);
    document.body.removeChild(anchor);
  } else { //IE10+下载
    navigator.msSaveBlob(data, fileName);
  }
}

上面三个函数一般综合起来一起使用,下面vue使用方式,代码把三个方法注册到了全局,如下:

packetDownload(params).then((res) => {
    this.$downStreamCheck(res).then(() => {
        let fileName = this.$responseFileName(res);
         this.$downloadBlob(res.data,'application/octet-stream',fileName);
    })
 })

实现周的切换(上一周、下一周)

<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="UTF-8">
<style>
    .con{overflow: hidden;}
    .same,#time{float:left;}
    #time{
        width: 260px;
        text-align: center;
    }
</style>
</head>
<body>
    <div class="con">
        <button class="same" id="last-week">前一周</button>
        <div id="time"></div>
        <button class="same" id="next-week">下一周</button>
    </div>

<script type="text/javascript" src="js/jquery-1.11.3.min.js"></script>
<script type="text/javascript">
    var currentFirstDate;
    var startTime = '';
    var endTime = '';
    function formatDate(date,joinStr){ 
        if(joinStr) {
            return date.getFullYear()+ joinStr + (date.getMonth()+1)+ joinStr + date.getDate();
        } else {
            return date.getFullYear()+'年' + (date.getMonth()+1)+'月' + date.getDate()+'日';
        }
    }
    
    function addDate(date,n) {
        date.setDate(date.getDate()+n);    
        return date;
    }
    function setDate(date) {
        var week = date.getDay()-1;
        date = addDate(date,week*-1);
        currentFirstDate = new Date(date);
        var str = formatDate(date) + '-' + formatDate(addDate(date,6));
        startTime = formatDate(addDate(date,-6),'-');
        endTime = formatDate(addDate(date,6),'-');
        $('#time').html(str);
    }
    function ajaxlist() {
        
    }
    
    $(function() {
        setDate(new Date());
        ajaxlist();
        $('#last-week').on('click',function() {
            setDate(addDate(currentFirstDate,-7));  
            // 接口请求
            ajaxlist();
        })
        $('#next-week').on('click',function() {
            setDate(addDate(currentFirstDate,7)); 
             // 接口请求
            ajaxlist();
        }) 
    })
</script>
</body>
</html>

获取浏览器版本

export const browser = (() => {
	const userAgent = navigator.userAgent.toLowerCase();
	const isIE = userAgent.indexOf("compatible") > -1 && userAgent.indexOf("msie") > -1;
	const isIE11 = userAgent.indexOf("trident") > -1 && userAgent.indexOf("rv:11.0") > -1;
	const isEdge = userAgent.indexOf("edge") > -1 || userAgent.indexOf('edg') > -1;
	return {
		version: (userAgent.match(/.+(?:rv|it|ra|ie)[/: ]([\d.]+)/) || [0, '0'])[1], // 获取版本号
		webkit: /webkit/.test(userAgent), // 是否webkit浏览器
		opera: /opera/.test(userAgent), // 是否opera浏览器
		mozilla: /mozilla/.test(userAgent) && !/(compatible|webkit)/.test(userAgent), // 是否mozilla浏览器
		tt: /tencenttraveler/.test(userAgent), // 是否TT浏览器
		chrome: /chrome/.test(userAgent), // 是否chrome浏览器
		firefox: /firefox/.test(userAgent), // 是否firefox浏览器
		ie: isIE, // 判断是否IE浏览器,不包括edge浏览器,不包括IE11
		ie11: isIE11,
		edge: isEdge, // 判断是否IE的Edge浏览器
		safari: !(userAgent.indexOf("chrome") > -1) && (/webkit|khtml/).test(userAgent) && userAgent.indexOf('safari') > -1, // 是否safari浏览器
 		mobile: !!userAgent.match(/applewebkit.*mobile.*/),
		ios: !!userAgent.match(/\(i[^;]+;( u;)? cpu.+mac os x/),
		android: userAgent.indexOf('android') > -1 || userAgent.indexOf('linux') > -1,
		iPhone: userAgent.indexOf('iphone') > -1,
		iPad: userAgent.indexOf('ipad') > -1,
		iWinPhone: userAgent.indexOf('windows phone') > -1,
		isWeiXin: !!userAgent.match(/MicroMessenger/i),
		ieVersion: function() {
			if (isIE) {
				userAgent.match(/msie (\d+\.\d+);/g);
				var fIEVersion = parseFloat(RegExp.$1);
				if (fIEVersion == 7) {
					return 7;
				} else if (fIEVersion == 8) {
					return 8;
				} else if (fIEVersion == 9) {
					return 9;
				} else if (fIEVersion == 10) {
					return 10;
				} else {
					return 6; //IE版本<7
				}
			} else if (isEdge) {
				return 'Edge'
			} else if (isIE11) {
				return 11;
			} else {
				return -1;
			}
		}
	}
})()

设计模式-面向对象编程

Function.prototype.addMethod = function (name,fn) {
   this.prototype[name] = fn;
   return this;
};
var Methods = function(){};
Methods.addMethod('checkName',function () {
   //验证姓名
   console.log('姓名');
}).addMethod('checkEmail',function () {
   //验证邮箱
   console.log('邮箱');
});
var m = new Methods();
m.checkName();
m.checkEmail();

CSS(3)

前端强制页面不缓存no-cache、no-store

<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0" />

HTML(5)

canvas图片预加载及进度条的实现

/*star
 *loading模块
 *实现图片的预加载,并显示进度条
 *参数:图片数组对象,加载完成的回调函数
 */
function loadImages(sources,callback){    
    var loadedImages = 0;    
    var numImages = 0;  
    ctx.font='14px bold';
    ctx.lineWidth=5;
    var clearWidth=canvas.width;
    var clearHeight=canvas.height;
    // get num of sources    
    for (var src in sources) {    
        numImages++;    
    }    
    for (var src in sources) {    
        images[src] = new Image();
        //当一张图片加载完成时执行    
        images[src].onload = function(){ 
            //重绘一个进度条
            ctx.clearRect(0,0,clearWidth,clearHeight);
            ctx.fillText('Loading:'+loadedImages+'/'+numImages,200,280);
            ctx.save();
            ctx.strokeStyle='#555';
            ctx.beginPath();
            ctx.moveTo(200,300);
            ctx.lineTo(600,300);
            ctx.stroke();
            ctx.beginPath();
            ctx.restore();
            ctx.moveTo(200,300);
            ctx.lineTo(loadedImages/numImages*400+200,300);  
            ctx.stroke();
            //当所有图片加载完成时,执行回调函数callback
            if (++loadedImages >= numImages) {    
                callback();    
            }    
        };  
        //把sources中的图片信息导入images数组  
        images[src].src = sources[src];    
    }    
}    
//定义预加载图片数组对象,执行loading模块
window.onload = function(){    
    var sources = {    
        PaperBoy1: "images/run/PaperBoy1.png",    
        PaperBoy2: "images/run/PaperBoy2.png", 
        PaperBoy3: "images/run/PaperBoy3.png",    
        PaperBoy4: "images/run/PaperBoy4.png" 
    };    
    //执行图片预加载,加载完成后执行main
    loadImages(sources,main);    
};   
/*end*/

使用高德地图API创建地图以及获取当前地址经纬度

创建API地图带有点标记:

<script src="http://webapi.amap.com/maps?v=1.4.1&key=bcf87f3263f98cc37309298bca20c622"></script>
<script type="text/javascript">
    // 实例化点标记
 function addMarker() {
        marker = new AMap.Marker({
            icon: "http://webapi.amap.com/theme/v1.3/markers/n/mark_b.png",
            position: [116.41, 39.91]
        });
        marker.setMap(map);
    }

 var map = new AMap.Map('container', {
        resizeEnable: true,
        center: [116.40, 39.91],
        zoom: 13
    });
 addMarker();
</script>

根据浏览器定位获取当前经纬度:

<div id="container_display"></div>
<script src="https://webapi.amap.com/maps?v=1.4.1&key=bcf87f3263f98cc37309298bca20c622"></script>
<script>
function loadingCurrentPosition(callback){
    
    document.getElementById('container_display').innerHTML = '';
      //加载地图,调用浏览器定位服务
    map = new AMap.Map('container_display', {
        resizeEnable: true
    });
    map.plugin('AMap.Geolocation', function() {
        geolocation = new AMap.Geolocation({
            enableHighAccuracy: true,//是否使用高精度定位,默认:true
            timeout: 10000,          //超过10秒后停止定位,默认:无穷大
            buttonOffset: new AMap.Pixel(10, 20),//定位按钮与设置的停靠位置的偏移量,默认:Pixel(10, 20)
            zoomToAccuracy: true,      //定位成功后调整地图视野范围使定位位置及精度范围视野内可见,默认:false
            buttonPosition:'RB'
        });
        map.addControl(geolocation);
        geolocation.getCurrentPosition();
        AMap.event.addListener(geolocation, 'complete', onComplete);//返回定位信息
        AMap.event.addListener(geolocation, 'error', onError);      //返回定位出错信息
    });
    //解析定位结果
    function onComplete(data) {
        var getLngdata = data.position.getLng();
        var getLatdata = data.position.getLat();
        if(callback){
            callback(getLngdata,getLatdata); //回调参数中传递经度与纬度
        }
    }
    //解析定位错误信息
    function onError(data) {
        alert('定位失败');
    }
}

$(function(){
    var getLng = ''; //存经度
    var getLat = ''; //存纬度
    //默认加载一次自动获取当前人的位置
    loadingCurrentPosition(function(lngdata,Latdata){
        getLng = lngdata;
        getLat = Latdata;
    });
    $(".getCurrentPosition").on('click',function(){
        loadingCurrentPosition(function(lngdata,Latdata){
            getLng = lngdata;
            getLat = Latdata;
        });
    });
})

</script>

JS创建canvas示例代码

HTML5中的Canvas标签的创建:

window.onload = function(){
     createCanvas();
}
function createCanvas(){
    var canvas_width= 200, canvas_height = 200;
    document.body.innerHTML = "<canvas id=\"canvas\" width=\""+canvas_width+"\" height=\""+canvas_height+"\"></canvas>";
}

HTML5Canvas标签绘制图形:

var canvas_width= 500, canvas_height = 500;
var mycanvas, context;
window.onload = function(){
    createCanvas();
    drawRect();
}
function createCanvas(){
   document.body.innerHTML = "<canvas id=\"mycanvas\" width=\""+canvas_width+"\" height=\""+canvas_height+"\"></canvas>";
   mycanvas = document.getElementById("mycanvas");
   context = mycanvas.getContext("2d");
}
 
function drawRect(){
    context.fillStyle ="#FF0000";
    //context.rotate(45);//旋转45度
    //context.translate(200,200);//移动
    //context.scale(2,0.5);//缩放
    context.fillRect(0,0,200,200);
 }

HTML5Canvas标签绘制图片:

var canvas_width= 500, canvas_height = 500;
var mycanvas, context;
window.onload = function(){
    createCanvas();
    drawImage();
}
function createCanvas(){
    document.body.innerHTML = "<canvas id=\"mycanvas\" width=\""+canvas_width+"\" height=\""+canvas_height+"\"></canvas>";
    mycanvas = document.getElementById("mycanvas");
    context = mycanvas.getContext("2d");
}
 
function drawImage(){
    var img = new Image();
    img.onload = function(){
        context.drawImage(img,0,0);
    }
     img.src = "1.png";
}

canvas绘制文本内容自动换行

/** canvas中的文字字段断行
 * @param {String} textContent 绘制的文本内容
 * @param {Number} textMaxWidth 每行文本的最大宽度
 * @param {Number} drawX 绘制文本的x坐标
 * @param {Number} drawY 绘制文本的y坐标
 * @param {Number} lineHeight 文本之间的行高
 * @param {Number} lineNum 最多绘制的行数 超过设置的行数..展示, 不设置此参数自动往下断行
 * 
 * */
function textBrokenLine(textContent,textMaxWidth,drawX,drawY,lineHeight,lineNum) {
    // 创建canvas
    var canvas = document.createElement('canvas');
    canvas.id = 'canvas';
    document.body.appendChild(canvas);
    var ctx = canvas.getContext('2d');
    ctx.font = "14px 微软雅黑";
    ctx.fillStyle = 'black';

    if(ctx.measureText(textContent).width <= textMaxWidth) {
        ctx.fillText(textContent,drawX,drawY);
    } else {
        var drawTxt = ''; // 当前绘制的内容
        var drawIndex = 0; // 当前绘制内容的索引
        var drawLine = 1; // 第几行开始绘制
        for(var i = 0; i < textContent.length; i++) {
            drawTxt += textContent[i];
            if(ctx.measureText(drawTxt).width >= textMaxWidth) {
                if(lineNum) { // 有最多展示几行的参数进行特殊处理
                    if (drawLine >= lineNum) {
                        ctx.fillText(textContent.substring(drawIndex, i) + '..', drawX, drawY);
                        break;
                    } else {
                        ctx.fillText(textContent.substring(drawIndex, i + 1), drawX, drawY);
                        drawIndex = i + 1;
                        drawLine += 1;
                        drawY += lineHeight;
                        drawTxt = '';
                    }
                } else {
                    ctx.fillText(textContent.substring(drawIndex, i + 1), drawX, drawY);
                    drawIndex = i + 1;
                    drawY += lineHeight;
                    drawTxt = '';
                }
            } else {
                // 内容绘制完毕,但是剩下的内容宽度不到textMaxWidth
                if (i === textContent.length - 1) {
                    ctx.fillText(textContent.substring(drawIndex),drawX,drawY);
                }
                
            }
        } 
    }
    
    
    // 获取canvas转化结果base64
    var canvasDom = document.getElementById("canvas");
    canvasDom.style.border = "red 1px solid";
    var base64 = canvasDom.toDataURL("image/png");
    console.log(base64);
    // canvasDom.parentNode.removeChild(canvasDom);
}

// 调用
textBrokenLine('这是用户输入的一段文字,这是用户输入的一段文字,这是用户输入的一段文字',100,0,20,20);

JS跳转到app store内应用下载页面

跳转到应用商店:

(https)|(itms-apps)://itunes.apple.com/app/id{appID}

跳转到撰写评价:

(https)|(itms-apps)://itunes.apple.com/app/id{appID}?action=write-review

跳转到查看评价:

(https)|(itms-apps)://itunes.apple.com/app/viewContentsUserReviews?id={appID}

手机端和pc端均可适用。

示例代码:

window.location.href = 'itms-apps://itunes.apple.com/app/id414478124?action=write-review'

h5 JS判断是安卓还是ios设备,跳转到对应的下载地址

;(function(){
    var u = navigator.userAgent;
    var ua = navigator.userAgent.toLowerCase();
    var dom = document.getElementById('btn');
    var isAndroid = u.indexOf('Android') > -1 || u.indexOf('Adr') > -1; //android终端
    var isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios终端
    if(ua.match(/MicroMessenger/i)=="micromessenger") {   //微信内置浏览器
        dom.addEventListener('touchstart', function (event) {
        
        },false);
    }else{
        if(isiOS){
            dom.addEventListener('touchstart', function (event) {
               //跳转到ios下载地址(示例:微信app)
                window.location.href='itms-apps://itunes.apple.com/app/id414478124';
            },false);
        }
        else if(isAndroid){
             dom.addEventListener('touchstart', function (event) {
                window.location.href='http://www.XXX.com/apk/demo.apk';
            },false);
        }else{  //PC 端
             dom.addEventListener('click',function(){
                //跳转到andriod下载地址 
                window.location.href='http://www.XXX.com/apk/demo.apk';
            },false);
        }
    }
    
})();

判断移动端、ipad设备

try {
		if(/Android|Windows Phone|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) {
			 window.location.href = "https://pc.com/";
		} else if(/iPad/i.test(navigator.userAgent)) {
			window.location.href = "https://pad.com/"
		}
} catch(e) {}

前端工具

webpack常用操作

  • 自动创建package.json文件:npm init
  • 如何根据package.json来自动安装包:npm install
  • npm具体安装某个组件:npm install name -g
  • 如何手动更新npm中指定的插件版本号:修改package.json中依赖包版本,执行npm install --force
  • 清理npm:npm cache clean --force
  • 设置npm代理地址:npm config set registry http://registry.cnpmjs.org
  • 淘宝npm代理:npm config set registry https://registry.npm.taobao.org
  • 安装cnpm:npm install -g cnpm --registry=https://registry.npm.taobao.org(使用命令换成比如cnpm install)
  • 查看设置过的源地址:npm config get registry
  • 默认的是Vue2.0,如果要使用Vue 1.X的话,执行下面的操作:vue init webpack#1.0 my-project
  • 安装webpack
    • 全局安装:npm install -g webpack
    • 安装到你的项目目录: npm install --save-dev webpack
  • linux系统下执行npm install 没权限创建node-modules下的目录:npm install --unsafe-perm
  • 查看webpack安装的版本:npm info webpack 显示的第一条就是版本号

vue常用指令

  • vue-cli(2.x)安装:npm install -g vue-cli
  • vue-cli(3.x)安装:npm install -g @vue/cli
  • vue-cli(2.x)脚手架快速生成工程:$ vue init webpack vuedemo
  • vue-cli(3.x)脚手架快速生成工程:vue create hello-world
  • 卸载vue-cli(2.x):npm uninstall -g vue-cli
  • 如果使用SCSS需要安装sass-loader:npm install sass-loader node-sass webpack --save-dev
  • vue-router中路由懒加载的方式引入插件:npm install babel-plugin-dynamic-import-node --save-dev
  • ES6 中用来传递异步消息的的Promise,而IE低版本的浏览器不支持,需要安装polyfill:npm install --save babel-polyfill
  • npm install出现"Unexpected end of JSON input while parsing near"错误解决方法:npm cache clean -force

git常用命令

  • 克隆github项目:git clone 仓库地址
  • 查看本地及远程分支:git branch -a
  • 查看本地分支:git branch
  • 查看远程分支:git branch -r
  • 切换本地分支 git checkout 分支名
  • 创建本地分支并切换到该新分支 git checkout -b 分支名
  • git add <file> # 将工作文件修改提交到本地暂存区
  • git add . # 将所有修改过的工作文件提交暂存区
  • git commit -m #用于提交暂存区的文件
  • git push -u origin master # 将本地主分支推到远程(如无远程主分支则创建,用于初始化远程仓库)
  • git将远程分支拉取到本地:git pull origin master:localbranch(git pull origin是固定的部分,后面接远程分支名,冒号后面接本地分支名)
  • 查看git提交的记录:git log (可以看到有commit提交编号)
  • 回退到某次的提交:git reset --hard commit编号
  • git log退出方法:输入Q
  • 合并某个分支到当前分支:git merge master(把master代码合并到当前分支)
  • cd : change directory的简写,改变目录的意思,就是切换到哪个目录下, 如 cd e:\fff 切换 E 盘下面的fff 目录。当我们用cd 进入文件夹时,我们可以使用 通配符, cd f, 如果E盘下只有一个f开头的文件夹,它就会进入到这个文件夹.
  • 添加远程仓库地址:git remote add origin https://git.github.com.cn....online.git
  • 查看远程配置:git remote -v
  • 删除远程配置:git remote remove origin
  • 推送本地分支到远程仓库并在远程仓库创建新分支:$ git push <远程主机名> <本地分支名>:<远程分支名>
  • 克隆SVN代码到git:git svn clone 地址/template --no-metadata --trunk=trunk --tags=tags --branches=branches --authors-file=author.txt template

git代码提交规范:

feat - 新功能 feature
fix - 修复 bug
docs - 文档注释
style - 代码格式(不影响代码运行的变动)
refactor - 重构、优化(既不增加新功能,也不是修复bug)
perf - 性能优化
test - 增加测试
chore - 构建过程或辅助工具的变动
revert - 回退

例如:

1.[feat]新功能xxx
2.[fix]修复xxx问题
3.[perf]优化xxx代码
4.[build]打包xxx文件
5....等等

使用webpack打包自己的library类库,怎样忽略eslint语法检测

在打包的时候在类库js最前面添加/* eslint-disable */忽略检测的语法,在配置文件中实现一个简单的类:

class ignoreEslintPlugin {
  constructor(options) {
    this.options = options;
  }
  apply(compiler) {
    compiler.hooks.emit.tap('ignoreEslintPlugin', (compilation) => {
      var topInfo = '/* eslint-disable */\n';
      for(let i in compilation.assets) {
        if(i.lastIndexOf('.js') != -1 && i.lastIndexOf('.json') == -1) {
          let content = topInfo + compilation.assets[i].source();
          compilation.assets[i] = {
            source: () => content,
            size: () => content.length
          }
        }
      }
    })
  }
}

调用:

 plugins: [
    new ignoreEslintPlugin()
  ]

使用Nginx的Rewrite匹配特殊符号并替换再重定向

rewrite ^(.*)/rewriteSystem/(.*)$ $1/#/$2 redirect;

详细可参考《Nginx中的Rewrite的重定向配置与实践》

Hbuilder中配置cmd

  • 1.运行——>外部工具——>外部工具 配置
  • 2.新建一个名为cmd(随意命名)的外部工具:
    • 名称:cmd
    • 要执行的命令或文件:C:\Windows\System32\cmd.exe
    • 工作目录:${selected_resource_loc} 基于选中文件夹的绝对路径
    • (先用鼠标选中要cmd.exe执行的文件夹再选择【cmd】运行。)

钉钉内网穿透工具

doc命令

  • doc命令到某个盘:d:
  • doc命令到某个文件夹下:cd public
  • doc命令返回上级目录:cd..
  • doc命令创建文件夹:md public(指到某个文件夹或者盘下面再执行md,后面跟一个创建的文件名即可创建)
  • 使用cmd命令新建某个文件夹:mkdir test
  • 使用cmd命令删除文件夹下所有文件:rmdir /s/q dist(删除当前目录下的dist文件夹以及下面的所有文件)
    • /s 是代表删除所有子目录跟其中的档案
    • /q 是不要它在删除档案或目录时,不再问我 Yes or No 的动作
    • 要删除的目录前也可以指定路径,如:rmdir /s/q d:\webpack\test(把磁盘驱动器 D 的webpack文件夹里面的test文件夹中的所有东西全部删除)
  • 使用cmd命令删除某个文件,如删除a.txt文件:del a.txt
  • 使用cmd命令查看当前目录下的文件列表:dir

其它

  • 检查node是否正确安装:node --version
  • 检查npm是否正确安装:npm --version
  • 检查npx是否正确安装:npx --version

npm是一个node package安装工具。
npx的作用是先检查本地有没有安装某个package,如果没有去远程registry找,找到的话直接使用,不用下载到本地node-modules包里面,这样就能优化本地项目的大小,也可以避免安装package到全局。

  • excel换行:alt+enter
  • PS填充前景色的快捷键:Alt+Delete
  • PS填充填充背景色快捷键:Ctrl+Delete
  • 给自己的博客园装饰萌萝莉(live2d)
  • 无法访问github项目地址时,把https://github.com换为https://hub.fastgit.org就可以
posted @ 2019-09-02 21:06  风雨后见彩虹  阅读(1257)  评论(0编辑  收藏  举报