前端乱炖之 前端技术问答和小知识分享 分站 www.jser.biz

http://www.jser.biz

一个前端技术问答和小知识分享网站。在这里可以提出问题,会有专业前端给您解答,提问前请先注册账号。

你也可以把自己的一些感悟想法和小知识记录在这里,分享给更多的前端开发同仁们。

博主会不定期发布一些前端小知识。简短而有用。欢迎订阅。

互换友情链接,请加群:227896607

给项目写了个简单的打包工具。。。

简直就不能叫打包工具。。。。就是个文件合并工具。

 

因为本项目目录清晰,代码结构简单,所以打包工具也异常简单,基于nodejs,原理就是把项目里所有的js文件都合并到一个文件中。

不想合并的,可以写在黑名单里。

/**
 * 直接把文件打包到一个文件夹里,没有依赖逻辑判断,不想打包的文件名,请写在黑名单blackList里面。
 * 安装 nodejs 然后执行此文件即可
 */
 
 
var fs = require('fs'),
fileList = [];
var pathMod=require("path")
//黑名单,不读取
var blackList=[
    "district.js"
]
//打包到哪
var packTo=pathMod.resolve(__dirname.replace(/\/[^/]*?$/|>,""), '1.0/tmb.js')
//获取文件列表
function walk(path){
    var dirList = fs.readdirSync(path);
    dirList.forEach(function(item){
        if(fs.statSync(path + '/' + item).isDirectory()){
            walk(path + '/' + item);
        }else{
            if(pathMod.extname(item)==".js"){
                if(blackList.indexOf(item)==-1){
                      fileList.push(path + '/' + item);
                }
 
            }
 
        }
    });
}
walk(pathMod.resolve(__dirname.replace(/\/[^/]*?$/|>,""), '1.0/mb'));
var str=""
//读到字符串变量里
var readCount=0;
function readFile(callback){
    if(readCount>=fileList.length){
        callback();
        return;
    }
    console.log("packing "+fileList[readCount])
    fs.readFile(fileList[readCount],'utf8',function (err, data) {
        if (err) throw err;
        str+=data;
        readCount++;
        readFile(callback);
    });
}
//写文件
readFile(function(){
    fs.writeFile(packTo,str,"utf8");
})
console.log("Pack OK!")

使用无逻辑模板( Mustache )递归渲染树状结构

使用无逻辑模板递归渲染树状结构

通常情况下,无逻辑模板的应用范围不是一整个页面,而是类似重复的商品列表之类的小范围场景。

不过订单页面是个比较特殊的页面,将Mustache应用于此页面的时候,既不是整个页面的范围,也不是简单的列表范围。而是一种类似树状结构的场景。

这里说的就是如何在树状结构的页面中应用无逻辑模板。

树状结构

树状结构,正如字面意思,通过主干贯穿,但是又有分支,分支上也可以有分支。最后汇聚于一点。

在具体的场景中,例如确认订单页面,结构是这样的:


总订单   →  活动订单1   → 活动内店铺1 → 商品1 → 商品的各种属性
  |           |          ↓
  |           |         商品2 → 商品2的各种属性
  |           ↓
  |         活动内店铺2 → 商品3
  |           ↓
  |         商品4
  ↓
独立店铺3 → 商品5
  ↓
店铺的各种属性
            

这就是个简单的树状结构,当然树枝里有很多元素,这里不表现出来,只是一个大体结构。


继续阅读 »

前端模板之《Mustache简介》

Mustache简介

what?

Mustache官方简介:点击访问

Mustache是一个logic-less(无逻辑,轻逻辑)的模板语言,可以在浏览器端利用js把数据和模板合成最后的html片段。

Mustache是一个渲染速度非常快的模板语言。纯粹而强大。

轻逻辑和为什么轻逻辑

轻逻辑

M跟其他类型的模板语言比起来真的很易学,因为他里面的逻辑语句非常少,我们抛去官网里提到的特性中的高级特性,只涉及最基本的应用。

继续阅读 »

前后端解耦的意义和前端模块化思想

感觉涉及公司业务很少,所以拿来博客充数,随时可能被撤下。。。。

今天突然有点小感悟,跟大家分享一下。

写着写着发现写太多了,其实就讨论了两个问题:前后端解耦的意义和前端模块化思想。废话也有点多了,懒得看的可以回头用到或者想到的时候再看。其中主要包括了一些想法的历程,所以才写这么长,希望能给大家带来一些收获。
1.关于今年遇到的两个技术方面的感悟。

从去年到今年的确大家都做了不少事情,事情做的多了,收获多了,但是同时困惑也会变多。这里不是想说怎么去解决这个困惑,怎么沉淀收获。就是分享我遇到的两个比较大的困惑和解决方式,算是技术上的困惑和收获。

继续阅读 »

用深拷贝解决console.log的中对象的调试问题

用深拷贝解决console.log的中对象的调试问题

var obj={aa:1}
console.log(obj);
obj.aa=2
console.log(obj);

运行上面一段代码。为了跨越console.log的异步特性,将上述代码一句一句在控制台里执行,这样尅忽略异步或者多线程的问题。

然后观察结果,发现输出了两个object。鼠标点开的时候会看到对象的内容,但是发现两个object的内容是一样的。
也就是说,这种情况下,不管是何时输出的obj,点开后看到的都是最后obj的值,而不是输出的时候对象的值。
可能是因为consolelog只是输出一个对象的引用,鼠标点开的时候,会去内存里取这个引用,取到的当然总是最后的值。
这个时候,如果需要实时调试,那就需要对象深拷贝了。原理很简单:

 var object_copy=function(obj){
            var cache={}
            for(var i in obj){
                if(typeof(obj[i])=="object"){
                    cache[i]=object_copy(obj[i])
                }else{
                    cache[i]=obj[i]
                }
            }
            return cache;
        }

这里有递归操作,如果页面里有大量这样的调试的话,可能会内存溢出或者堆栈溢出,小心小心。

Chrome插件中的创新与应用

年前在周会上的分享,介绍了一些chrome插件可以做什么,和我的一些插件中的一些技巧,技术和创新

ruby清除mac下的svn项目

require 'find'
require 'fileutils'
Find.find('C:/xampp/htdocs/my') do |file|
  if file=~/\.svn$/
		FileUtils.rm_r file if File.exists?file
		puts file
	end
end

贝塞尔曲线的更正和一些方法

之前写过一篇关于贝塞尔曲线的文章,写的很复杂,用矩阵算出的贝塞尔,今天在使用的时候发现是有错误的.

所以重新写了一个方法,比矩阵简单的多:

资料:http://paulbourke.net/geometry/bezier/index2.html

前提:定义一个向量类,主要用来标识点坐标,所以叫 Point:

(function(){
    var p=SCD.Point;
    SCD.Point=function(x,y){
        this.x=x||0;
        this.y=y||0;
    }

    SCD.Point.prototype={
        /*~!Vector*/
        toArray:function(){
            return [this.x,this.y]
        },
        add:function(v){
            return new SCD.Point(this.x+v.x,this.y+v.y);
        },
        sub:function(v){
            return new SCD.Point(this.x-v.x,this.y-v.y);
        },
        getMod:function(){
            return Math.sqrt(this.x*this.x+this.y*this.y);
        },
        mulNum:function(num){
            return new SCD.Point(this.x*num,this.y*num);
        },
        getNegative:function(){
            return new SCD.Point(-this.x,-this.y);
        },
        /**
         *返回一个常数代表b在a上的投影乘以a的长度
         */
        dotMul:function(v){
            return this.x*v.x+this.y*v.y;
        },
        crossMul:function(v){
            return   this.x*v.y-this.y*v.x;
        },
        /**
         *获取夹角,注意返回的是角度
         */
        getAngle:function(v){
            return Math.acos(this.dotMul(v)/(this.getMod()*v.getMod()))* 180/Math.PI;

        },
        /**
         *获取夹角,返回的是弧度
         */
        getRadian:function(v){
            var m1=this.getMod(),m2=v.getMod();
            if(m1==0||m2==0){
                return 0;
            }
            return Math.acos(this.dotMul(v)/(m1*m2));
        },
        distance:function(v){
            return Math.sqrt((this.x-v.x)*(this.x-v.x)+(this.y-v.y)*(this.y-v.y))
        },
        distance2:function(v){
            return (this.x-v.x)*(this.x-v.x)+(this.y-v.y)*(this.y-v.y)
        },
        /**
         *求某向量的法向量,返回一个单位向量,其模为1,返回的向量总是指向this向量的右边
         * @return
         */
        getNormal:function(){
            return new SCD.Point(this.y/(Math.sqrt(this.x*this.x+this.y*this.y)),-this.x/(Math.sqrt(this.x*this.x+this.y*this.y)));
        },
        reflex:function(v){
            var normal=v.getNormal();//先求法向量
            var angle=this.getAngle(normal);//求与法线的夹角
            return this.sub(normal.mulNum(2*this.dotMul(normal)));
        },
        mirror:function(v){
            return this.reflex(v).getNegative();
        },
        isZero:function(){
            if(this.x==0&&this.y==0) return true;else return false;
        },
        /**
         *判断某个点是否在某个矩形区域里,如果在里面的话,并且存在第四个参数的话(true),
         *就继续判断相对矩形中心点所在象限,最后返回象限,不存在第四个参数返回-1
         *如果不在矩形区域里,就直接返回false
         *
         *@param {vector} t 矩形左上角坐标
         *@param {vector} b 矩形右下角坐标
         *@param {boolean} q 是否返回象限
         *@return {number} 象限或者-1
         */
        isIn:function(t,b,q){
            var r1=this.sub(t),r2=this.sub(b)
            if(r1.x>=0&&r1.y>=0&&r2.x<=0&&r2.y<=0){
                if(q){
                    var c=t.add(b).mulNum(0.5)
                    return this.getQ(c)
                }else{
                    return -1;
                }
            }else{
                return false;
            }
        },
        /**
         *获取第一个点相对第二个点所在的象限
         *
         *@param {vector} pc 第二个点的坐标
         */
        getQ:function(pc){
            var r=this.sub(pc);
            if(r.x>=0&&r.y>=0){
                return 4
            }else if(r.x<0 &&r.y>=0){
                return 3
            }else if(r.x<0&&r.y<0){
                return 2
            }else if(r.x>=0&&r.y<0){
                return 1
            }
        },
        toString:function(){
            return this.x+":"+this.y;
        }
    /*END~!Vector*/
    }
})();

三维贝塞尔方法:

var bezier=function(begin,c1,c2,end,t){
            var p=new SCD.Point(0,0)
            p.x=begin.x*(1-t)*(1-t)*(1-t)+c1.x*3*t*(1-t)*(1-t)+c2.x*3*t*t*(1-t)+end.x*t*t*t
            p.y=begin.y*(1-t)*(1-t)*(1-t)+c1.y*3*t*(1-t)*(1-t)+c2.y*3*t*t*(1-t)+end.y*t*t*t
            return p;
        }

最后一个参数是t,大小从0到1 ,0的时候是起点,1是终点.
附上一些方法:
包括: //判断两条线段是否相交 //检测点是否在多边形内//三维贝塞尔//二维贝塞尔//打碎三维贝塞尔 //打碎二维贝塞尔

(function(){
    SCD.util={
        //向量叉乘
        crossMul:function(v1,v2){
            return v1.x*v2.y-v1.y*v2.x;
        },
        //判断两条线段是否相交
        checkCross:function(p1,p2,p3,p4){
            var v1={
                x:p1.x-p3.x,
                y:p1.y-p3.y
            },
            v2={
                x:p2.x-p3.x,
                y:p2.y-p3.y
            },
            v3={
                x:p4.x-p3.x,
                y:p4.y-p3.y
            },
            v=this.crossMul(v1,v3)*this.crossMul(v2,v3)
            v1={
                x:p3.x-p1.x,
                y:p3.y-p1.y
            }
            v2={
                x:p4.x-p1.x,
                y:p4.y-p1.y
            }
            v3={
                x:p2.x-p1.x,
                y:p2.y-p1.y
            }
            return (v<=0&&this.crossMul(v1,v3)*this.crossMul(v2,v3)<=0)?true:false
        },
        //检测点是否在多边形内
        checkPP:function(point,polygon){
            var p1,p2,p3,p4
            p1=point
            p2={
                x:-100,
                y:point.y
            }
            var count=0
            //对每条边都和射线作对比
            for(var i=0;i<polygon.length-1;i++){
                p3=polygon[i]
                p4=polygon[i+1]
                if(this.checkCross(p1,p2,p3,p4)==true){
                    count++
                }
            }
            p3=polygon[polygon.length-1]
            p4=polygon[0]
            if(this.checkCross(p1,p2,p3,p4)==true){
                count++
            }
            //  console.log(count)
            return (count%2==0)?false:true
        },
        //  //  B(u) = P0 * ( 1 - u ) 2 + P1 * 2 * u ( 1 - u ) + P2 u2
            //P0 * ( 1 - u )3 + P1 * 3 * u * ( 1 - u )2 + P2 * 3 * u2 * ( 1 - u ) + P3 * u3
            //三维贝塞尔
        bezier:function(begin,c1,c2,end,t){
            var p=new SCD.Point(0,0)
            p.x=begin.x*(1-t)*(1-t)*(1-t)+c1.x*3*t*(1-t)*(1-t)+c2.x*3*t*t*(1-t)+end.x*t*t*t
            p.y=begin.y*(1-t)*(1-t)*(1-t)+c1.y*3*t*(1-t)*(1-t)+c2.y*3*t*t*(1-t)+end.y*t*t*t
            return p;
        },
        //二维贝塞尔
        quadratic:function(begin,c1,end,t){
            var p=new SCD.Point(0,0)
            p.x=begin.x*(1-t)*(1-t)+c1.x*2*t*(1-t)+end.x*t*t
            p.y=begin.y*(1-t)*(1-t)+c1.y*2*t*(1-t)+end.y*t*t
            return p;
        },
        //打碎三维贝塞尔
        brokenBezier:function(begin,c1,c2,end,partCount){
            var partCount=partCount||10;
            var points=[]
            var t=0;
            for(var t=0;t<=1;t+=1/partCount){

                points.push(this.bezier(begin,c1,c2,end,t));
            }
            return points;
        },
         //打碎二维贝塞尔
        brokenQuadratic:function(begin,c1,end,partCount){
            var partCount=partCount||10;
            var points=[]
            var t=0;
            for(var t=0;t<=1;t+=1/partCount){

                points.push(this.quadratic(begin,c1,end,t));
            }
            return points;
        }
    }
})();

如何判断点是否点在贝塞尔曲线上以及如何将贝赛尔曲线打碎成折线

判断点是否在贝塞尔曲线上的方法就是:
把贝塞尔曲线打碎成一个小段一小段的折线,然后去判断每一段折线有没有和点重合.
问题变成如何打碎贝塞尔曲线.
如果你看过我之前一篇文章的话,现在就知道这是多么有用了:
文章见:http://www.html-js.com/?p=1031# (用js计算三次贝塞尔曲线);
利用文中的方式,可以按需计算贝塞尔曲线.只需要调整时间t的增益就行.
看demo:
http://www.html-js.com/mj/pj/v2/test/testbezierBroken.html
调整滑块的值即可改变打碎程度(非ie下浏览)