jquery基础框架
(function(window,undefined){
var arr = [],
push = arr.push,
slice = arr.slice;
//首先要做的就是封装一个parseHtml函数
//要注意的是,parthHtml要放在一个自调用函数内
var parseHtml = (function(){
//做一个模板
var div = document.createElement('div');
//这个函数是用来创建标签
function parseHtml(html){
var res = [];
//这边是将具有html语义的字符串放在模板div中,div里面的就有这些标签了
div.innerHTML = html;
//这个时候div里有标签元素,循环遍历div里面的元素
for(var i = 0;i < div.childNodes.length;i++){
//这边是将div模板里面的元素一一放到res数组里,因为这边的div.childNodes[i]是单个元素,可以直接push进数组
res.push(div.childNodes[i]);
}
//完成之后,将div里面的元素清除掉,方便下一次使用
div.innerHTML = '';
//将这个数组返回
return res;
}
return parseHtml;
})();
//封装insertBefore方法
function prependChild(parent,element){//传入的元素是父元素,要插入的元素
var first = parent.firstChild;//将父元素中的第一个元素取出来
parent.insertBefore(element,first);//使用insertBefore方法将element插入到父元素的第一个子元素的前面
}
//封装cc函数
function cc(html){
//这边返回的是cc原型对象里面的一个方法创建出来的实例
return new cc.fn.init(html);
}
//这边是为了后面书写方便
cc.fn = cc.prototype = {
constructor : cc,
length : 0,
//这两个属性要加到原型上
selector: '',//这两个属性在init所创建的实例之中还会用到,所以要加到这个原型上面
type : 'cc',
init : function(html){//这个函数的作用就是:1.创建实例;2.在这个函数里面对所传入的参数进行一个判断
this.events = {};
if(html == ''){//这边判断传入的参数是不是一个空字符串
return;//如果传入的是一个空字符串,那么就直接返回this,注意,这边虽然没写返回this,但是他是默认的
}else if(cc.isString(html)){//这边是当传入的html是字符串的时候
if(/^</.test(html)){//这边的html是标签组成的字符串
push.apply(this,parseHtml(html));
}else{//这边的html是选择器字符串
//这边的this指的是通过:cc.prototype.init这个函数创建出来的实例
push.apply(this,select(html));
//将这个实例的selector设置成html
this.selector = html;
}
}else if(html && html.type === 'cc'){//这边是当传入的html是一个cc对象的时候
push.apply(this,html);
this.selector = html.selector;
this.events = html.events;
}else if(html && html.nodeType){//这边是当传入的是一个dom对象的时候,因为dom对象都有nodeType属性
this[0] = html;
this.length = 1;
}else if(typeof html === 'function'){//这边是当传入的是一个函数的时候,进入里面
var oldfunc = onload;//将原来onload里面的函数取出来
if(typeof oldfunc === 'function'){
onload = function(){
oldfunc();
html();
}
}else{
onload = html;
}
}
}
};
//将封装好的select方法放到这里面
var select = (function () {
//这是一个异常与捕获的代码,它表示的意思是:如果push方法出现了错误那么就需要重写push方法
try {
//这边是自己模拟一个场景,来使用系统的push方法,如果可以实现的话就证明系统支持push方法
//这种方法是系统能力检测中的方法功能检测
var div = document.createElement( 'div' );
div.innerHTML = '<p></p>';
var arr = [];
push.apply( arr, div.getElementsByTagName( 'p' ));
} catch ( e ) {
//这边是当try里面的push方法不执行的时候,会进入这里面
//在这里面将push重新定义了一下,将其变为一个对象,这个对象里面有一个push方法
var push = {
//将apply变成了push对象里面的一个方法
apply: function ( array1, array2 ) {
for ( var i = 0; i < array2.length; i++ ) {
//注意这边的赋值
array1[ array1.length++ ] = array2[ i ];
}
}
};
}
// 正则表达式
//这句正则表达式是为了匹配系统中是否有自带的方法
var rnative = /\{\s*\[native/;
var rtrim = /^\s+|\s+$/g;
//这个是为了匹配出 Id 类名 通配符 标签名
// 1 2 3 4
var rbaseselector = /^(?:\#([\w\-]+)|\.([\w\-]+)|(\*)|(\w+))$/;
// 基本函数, support 对象, 验证 qsa 与 byclass
var support = {};
//基本函数里面的一个属性,实质上是为了看一下系统中是否有该方法(使用正则来判断)
support.qsa = rnative.test( document.querySelectorAll + '' );
//同上
support.getElementsByClassName = rnative.test( document.getElementsByClassName + '' );
support.trim = rnative.test( String.prototype.trim + '' );
support.indexOf = rnative.test( Array.prototype.indexOf + '' );
// 基本方法
//封装了getElementsByClassName函数,这是为了解决兼容问题
//传入两个参数,一个是className,另一个是node-->这个node指的是从页面上的node元素开始查找这个className
function getByClassName ( className, node ) {
//如果没有传入node的话就给它一个默认值:document
node = node || document;
//声明一些变量
var allElem, res = [], i;
//首先做判断,如果系统有这个方法会使用系统的
if ( support.getElementsByClassName ) {
//直接使用定义的push方法
return push.apply(res,node.getElementsByClassName( className ));
} else {
allElem = node.getElementsByTagName( '*' );
for ( i = 0; i < allElem.length; i++ ) {
if ( allElem[ i ].className === className ) {
res.push( allElem[ i ] );
}
}
return res;
}
}
// 自定义实现 trim 方法,该方法是将字符串中的指定的东西去掉
var myTrim = function ( str ) {
// 表示两端去空格, 然后返回去除空格的结果
if ( support.trim ) {
return str.trim();
} else {
// 自定义实现
//这边是将rtrim转换成空字符串,即将空格去掉了
return str.replace( rtrim, '' );
}
}
//这边封装的是indexOf方法,传入三个参数,数组,要搜索的东西,要搜索的东西在数组里面的开始索引(从第几个开始找)
var myIndexOf = function ( array, search, startIndex ) {
//首先将索引赋值,如果传入了索引,那么就让开始的索引等于它,如果没有传入那么就让它从零开始找
startIndex = startIndex || 0;
//这边还是先判断系统有没有这种方法
if ( support.indexOf ) {
//这里表示系统有这种方法,那么就直接使用就OK了,将结果返回
return array.indexOf( search, startIndex );
} else {
//如果没有的话,我们就自己动手封装一个
//对这个数组进行一个遍历,遍历的初始值就是从startIndex开始
for ( var i = startIndex; i < array.length; i++ ) {
//判断一下,如果数组里面有值与要查询的值相等,那么就返回这个索引值
if ( array[ i ] === search ) {
return i;
}
}
//当遍历完成之后,如果还是没有找到的话,就返回-1
return -1;
}
}
//封装一个去重的函数,传入的参数是一个数组
var unique = function ( array ) {
//声明一个空数组,用于接收去重之后的元素
var resArray = [], i = 0;
//对传入的数组进行一个遍历
for ( ; i < array.length; i++ ) {
//做一个判断,如果说resArray里面没有arr里面的元素,则将arr里面的元素放到resArray里面
//注意,这边使用的是之前封装好的myIndexOf方法
if ( myIndexOf( resArray, array[ i ] ) == -1 ) {
//使用的是前面封装好的push方法
resArray.push( array[ i ] );
}
}
//将这个数组返回
return resArray;
}
//这边封装的是四种基本选择器,ID选择器,类选择器,通配符选择器,标签选择器
function basicSelect ( selector, node ) {
//这边的node指的是要在哪一个下面去寻找selector
node = node || document;
var m, res;
if ( m = rbaseselector.exec( selector ) ) {
if ( m[ 1 ] ) { // id选择器
res = document.getElementById( m[ 1 ] );
if ( res ) {//如果res不是一个空的话,进入
return [ res ];
} else {//当res为空的话返回一个空数组
return [];
}
} else if ( m[ 2 ] ) { // class选择器
return getByClassName( m[ 2 ], node );
} else if ( m[ 3 ] ) {//通配符选择器
return node.getElementsByTagName( m[ 3 ] );
} else if ( m[ 4 ] ) {//标签选择器
return node.getElementsByTagName( m[ 4 ] );
}
}
return [];
}
//封装一个组合选择器,这里面的标签使用逗号隔开的
function select ( selector, results ) {
results = results || [];
var m, temp, selectors, i, subselector;
//这边是如果传入的selector不是一个字符串的话,那么返回空数组
if ( typeof selector != 'string' ) return results;
// 表明参数都没有问题, 接下来就是如何选择
// 首先判断 qsa 是否可用
// 然后再 一步步的 自己实现
if ( support.qsa ) {//如果系统有querySelectorAll方法,那么就使用
push.apply( results, document.querySelectorAll( selector ) );
} else {
// 不存在再来考虑自己实现
//首先将传入的参数以逗号隔开,放到一个数组里面
selectors = selector.split( ',' );
// 循环遍历这个数组
for ( i = 0; i < selectors.length; i++ ) {
//在这个循环里面对数组里面的每一个元素进行一个去除空格的操作,保证数据是我们想要的形式
subselector = myTrim( selectors[ i ] );
// 接下来就是 处理 subselector,使用正则进行判断
if ( rbaseselector.test( subselector ) ) {
// 基本选择器
//如果匹配到了就将匹配到的传入到基本的四种选择器函数只中,返回一个数组,将这个数组进行一个push
push.apply( results, basicSelect( subselector ) );
} else {
//如果匹配不到那么就使用 select2 函数
select2( subselector, results );
}
}
}
// 返回 result注意,这个数组要进行一个去重操作
return unique( results );
}
//封装一个后代选择器的函数,传入两个参数
function select2 ( selector, results ) {
results = results || [];
//将这个参数以逗号隔开
var selectors = selector.split( ' ' );
//声明一个数组,这个数组用于存放元素,以及一个node数组,这个数组用于存放从哪一个元素开始找
var arr = [], node = [ document ];
for ( var j = 0; j < selectors.length; j++ ) {
for ( var i = 0; i < node.length; i++ ) {
//因为这边寻找的是后代选择器,所以只要找到最后面的并将其返回就可以了
push.apply( arr, basicSelect( selectors[ j ], node[ i ] ));
}
//在结束的时候将arr里面的值全部给node,要注意此时node里面的值的作用是什么
node = arr;
//将arr清空
arr = [];
}
//在最后将最后一次获取到的node值赋给results
//这里面的值是最后一次获取到的元素,也就是说是要获取的子代元素中的的最后一个元素
push.apply( results, node );
return results;
}
return select;
})();
//让init这个方法的原型与cc这个构造函数的原型相等,这样init的原型里面就有init的方法
cc.fn.init.prototype = cc.fn;
//给cc以及cc原型添加一个混入的方法
cc.extend = cc.fn.extend = function extend(obj){
for(var k in obj){
this[k] = obj[k];
}
}
//给cc混入方法,这些方法都是静态方法
cc.extend({
//给cc混入一个isString方法
isString : function(html){
return typeof html === "string";
},
//给cc混入一个each方法
each : function(arr,fnc){
var i;
if(arr instanceof Array || arr.length >= 0){
for(i = 0; i < arr.length; i ++){
fnc.call(arr[i],i,arr[i]);
}
}else {
for( i in arr){
fnc.call(arr[i],i,arr[i]);
}
}
return arr;
},
map : function(arr,fnc){
var i,tmp,res=[];
if(arr instanceof Array || arr.length >= 0){
for(i =0;i<arr.length;i++){
//这边的tmp的值是这边fnc的返回值,如果说fnc这个函数里面没有返回值的话(return),那么tmp就是undefined
tmp = fnc(arr[i],i);
if(tmp != null){
res.push(tmp);
}
}
}else{
for(i in arr){
tmp = fnc(arr[i],i);
if(tmp != null){
res.push(tmp);
}
}
}
return res;
},
//获取到样式
getStyle : function(dom,styleName){
if(dom.currentStyle){
return dom.currentStyle[styleName];
}else{
return window.getComputedStyle(dom)[styleName];
}
},
getText : function(dom,list){
var node = dom.childNodes;
for(var i = 0;i < node.length;i ++){
if(node[i].nodeType == 3){
list.push(node[i].nodeValue);
}
if(node[i].nodeType == 1){
cc.getText(node[i],list);
}
}
}
});
//核心方法
cc.fn.extend({
//将调用该方法的对象变成数组模式
toArray : function(){
//法一:
/*var res = [];
for(var i = 0;i < this.length; i ++){
res.push(this[i]);
}
return res;*/
//法二:
//这句话的意思是:this.slice(0);--->this指的是实例对象,调用slice将其从一个伪数组变成一个数组
return slice.call(this , 0);
},
//get方法是通过索引值来返回调用该方法的对象/数组里面的对应的值
get : function(index){
if(index === undefined){
return this.toArray();
}
return this[index];
},
//这边的eq返回的是dom对象,这是与get方法的区别,简单地说就是eq返回的是一个init对象,而get返回的是一个元素
eq : function(num){
var dom;
if(num >= 0){
dom = this.get(num);
}else{
dom = this.get(this.length + num);
}
return cc(dom);
},
each : function(fnc){
return cc.each(this,fnc);
},
map : function(fnc){
return cc.map(this,fnc);
}
});
//对DOM的操作方法
cc.fn.extend({
//给cc的原型混入一个appendTo方法,注意这边的原型是与init的原型是一至的
//首先要明白,appendTo方法是将appendT之前的元素添加到appendTo的括号里
appendTo : function(selector){
//首先声明一个ccObj对象,这个对象是和this一样,是init的实例对象
//当我们将selector传入其中时,它会解析出来传入的是一个什么样的参数
//这边的selector参数,其实就是appendTo括号里面的内容
var ccObj = this.constructor(selector);
//这边声明一个新的init的实例对象,这是为了仿照jQuery里面链式原理的写法
//这边执行完该方法之后,返回的是一个dom对象
var newObj = this.constructor();
//这边循环遍历this,这个this指的就是appendTo前面的内容
for(var i = 0;i < this.length;i ++){
//这边循环遍历的是解析了传入参数selector之后得到的一个对象ccObj
for(var j = 0;j < ccObj.length;j ++){
//声明一个变量temp
var temp;
if(j == ccObj.length-1){//当j循环到最后一个的时候,进入这个循环
//将this[i]赋值给temp
temp = this[i];
}else{
//这种情况就是当j值还没有到最后一个的时候
temp = this[i].cloneNode(true);
}
//将temp里面的值,放到之前创建的newobj中,这是为了仿照jQuery里面的链式结构
push.call(newObj , temp);
//将temp添加到ccObj中,temp里面存放的是this伪数组里面的值
ccObj[j].appendChild(temp);
}
}
//这个是:即使完成了这个appendTo操作,返回值依旧是一个cc对象
return newObj;
},
//首先要明确的是:append方法是将append括号里面的加到append前面的元素中
append: function(selector){
//还是一样,先声明一个cc对象,这个对象里面是将传入的参数进行解析
var ccObj = this.constructor(selector);
//这个循环的是创建的cc对象
for(var i = 0;i < ccObj.length;i ++){
//这个循环的是this这个伪数组
for(var j = 0;j < this.length;j ++){
var temp;
if(j == this.length-1){//这边的做法可以参照appendTo的方法封装
temp = ccObj[i];
this[j].appendChild(temp);
}else{
temp = ccObj[i].cloneNode(true);
this[j].appendChild(temp);
}
}
}
return this;
},
prependTo : function(selector){
var ccObj = this.constructor(selector);
var newObj = this.constructor();
for(var i = 0;i< this.length;i ++){
for(var j = 0;j < ccObj.length;j ++){
var temp;
if(j == ccObj.length-1){
temp = this[i];
}else{
temp = this[i].cloneNode(true);
}
push.call(newObj,temp);
prependChild(ccObj[j],temp);
}
}
return newObj;
},
prepend : function(selector){
var ccObj = this.constructor(selector);
for(var i = 0;i < ccObj.length;i ++){
for(var j = 0;j < this.length;j ++){
var temp;
if(j == this.length-1){
temp = ccObj[i];
prependChild(this[j],temp);
}else{
temp = ccObj[i].cloneNode(true);
prependChild(this[j],temp);
}
}
}
return this;
}
});
//事件处理模块
cc.fn.extend({
on : function(type,fn){
if(!this.events[type]){//当this中的events属性里面没有type的时候,进入这个里面
this.events[type] = [];//给它提供一个空数组
//当cc对象中的元素被点击的时候我们应该把数组中保存的函数拿出来一一执行
//我们应该为cc对象中的元素添加事件处理函数
var iObj = this;//将this赋值给iObj,此时iObj就表示创建出来的实例对象
//这边的this指的是实例对象
this.each(function(){//调用这个实例的each方法
var fnc = function(e){//fnc执行的时机是type事件执行的时候,在这个时候跟着传入一个e,这个e是事件参数
for(var i = 0;i < iObj.events[type].length;i ++){
//iObj.events[type][i]指的是:找到iObj对象->events属性->type数组->第i个函数,将之执行
//iObj.events[type][i]指的是:函数
//在执行的时候,这边的this指的是执行点击的这个dom元素
iObj.events[type][i].call(this,e);//这边将e传入到这个执行的函数中
}
}
//如果系统支持addEventListener方法就用它添加事件处理函数f,否则使用attachEvent
//事件参数e是从哪里来的?就是从事件绑定的函数来的
//我们通过addEventListener绑定事件的处理函数为f,那么f就带有了事件参数e
if(this.addEventListener){
this.addEventListener(type,fnc);
}else{
this.attachEvent('on' + type,fnc);
}
});
}
this.events[type].push(fn);
return this;
},
off : function(type,fn){
var arr = this.events[type];
if(arr){
for(var i = arr.length;i >= 0;i --){
if(arr[i] == fn){
arr.splice(i,1);
}
}
}
return this;
}
});
//其他事件
//其他事件的添加是将这些字符串用split方法分隔
var arr =
("blur focus focusin focusout load resize scroll unload click dblclick " +
"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
"change select submit keydown keypress keyup error contextmenu").split(' ');
//调用cc的each方法,这个方法里面传入的一个参数是数组,一个参数是函数fnc
cc.each(arr,function(i,v){
//在这个fnc中,
cc.fn[v] = function(fn){
this.on(v,fn);
return this;
}
});
cc.fn.extend({
hover : function(fn1,fn2){
this.mouseover(fn1);
this.mouseout(fn2);
return this;
},
toggle : function(){
var i = 0;
var args = arguments;
this.on('click' , function(e){
args[i % args.length].call(this , e);
i ++;
});
}
});
//样式操作
cc.fn.extend({
css : function(option){
var args = arguments,
argsLength = arguments.length;
if(argsLength == 2){
if(cc.isString(args[0]) && cc.isString(args[1])){
return this.each(function(){
this.style[args[0]] = args[1];
})
}
}
if(argsLength == 1){
if(cc.isString(option)){
return this[0].style[option] || cc.getStyle(this[0],option)
}
if(typeof option === 'object'){
return this.each(function(){
for(var k in option){
this.style[k] = option[k];
}
})
}
}
},
addClass : function(name){
return this.each(function(){
var classText = this.className;
if(classText){
if((' ' + classText +' ').indexOf(' ' + name + ' ') ==-1){
this.className += ' ' + name;//这边是将这个name添加到dom的className中
}
}else{
this.className = name;
}
})
},
removeClass : function(name){
return this.each(function(){
var classText = this.className;
if(classText){
var arr = classText.split(' ');
for(var i = arr.length;i >= 0;i --){
if(arr[i] == name){
arr.splice(i,1);
}
}
this.className = arr.join(' ');
}
})
},
hasClass : function(name){
//法一
/*var boolean;
this.each(function(){
var classText = this.className;
if(classText){
var arr = classText.split(' ');
for(var i = 0;i < arr.length;i ++){
if(arr[i] == name){
boolean = true;
return;
}
}
boolean = false;
return;
}
boolean = false;
return;
});
return boolean;*/
//法二
for(var i = 0;i < this.length;i ++){
if((' ' + this[i].className + ' ').indexOf(' ' + name + ' ') != -1){
return true;
}
}
return false;
},
toggleClass : function(name){
if(this.hasClass(name)){
this.removeClass(name);
}else{
this.addClass(name);
}
}
});
//属性操作
cc.fn.extend({
attr: function(name,value){
//第一种情况:有value值以及value值为空时
if(value || value == ''){
//这时要传入的name以及value都要是字符串
if(cc.isString(name) && cc.isString(value)){
this.each(function(){
this.setAttribute(name,value);//设置属性
})
}
}else{//这种情况是当只传了name且name为字符串
if(cc.isString(name)){
//这个时候是获取该属性
return this[0].getAttribute(name);
}
}
//这个是当以上两种都不符合时:
return this;
},
prop : function(name,value){
if(value || value == ''){
if(cc.isString(name) && cc.isString(value)){
this.each(function(){
this[name] = value;
})
}else{
if(cc.isString(name)){
return this[name];
}
}
}
return this;
},
val : function(value){
return this.attr('value',value);
},
html : function(html){
return this.prop('innerHTML',html);
},
text : function(){
var res = [];
cc.getText(this[0],res);
return res.join(' ');
}
});
//给cc原型添加anmite属性
cc.fn.extend({
animate : function(property,time,fn,easing){
var iObj = this
flag = false;
this.each(function(){
move(this,property,time,fn,easing);
});
return this;
function move(node,property,time,fn,easing){//需要传入的参数有:元素,元素要移动的距离,动画执行的时长
var start = {};
for(var k in property){
start[k] = parseInt(cc.getStyle(node,k));
}
var startTime = + new Date;//开始的时间
iObj.timer = setInterval(function(){//设置定时器
var currentTime = + new Date,//当前时间
deltaTime = currentTime - startTime;//当前时间与开始事件的差值,这个差值可以得到的是已经过去了多久
if(deltaTime >= time){//这边如果差值大于规定的时长之后,进入这个判断里面
clearInterval(iObj.timer);//这时候要清除计时器
deltaTime = time;//将差值赋值为要求的时长
flag = true;
}
easing = easing || 'change';
for(var k in property){
node.style[k] = start[k]
+ g(deltaTime,time,start[k],parseInt(property[k]),easing)
+ 'px';
}
if(flag && fn){
fn.call(iObj);
return;
}
},20);
};
function g(deltaTime,time,start,end,easing){
if(easing == 'line'){
return ((end - start)/time)*deltaTime;
}else if(easing == 'change'){
var distance = end - start;//需要移动的距离
//法一:
//return distance*Math.sin(daleTime*Math.PI/2/time);
//法二:
return distance*(Math.log(deltaTime + 1) / Math.log(time + 1));
}
}
},
timer : null,
stop : function(){
clearInterval(this.timer);
this.timer = null;
}
})
//在桌面上可以使用I以及cc来调用沙箱内部的cc函数
window.C = window.cc = cc;
})(window);
jquery基础框架的更多相关文章
- 【JavaScript框架封装】实现一个类似于JQuery的基础框架、事件框架、CSS框架、属性框架、内容框架、动画框架整体架构的搭建
/* * @Author: 我爱科技论坛 * @Time: 20180715 * @Desc: 实现一个类似于JQuery功能的框架 * V 1.0: 实现了基础框架.事件框架.CSS框架.属性框架. ...
- jQuery基础课程
环境搭建 搭建一个jQuery的开发环境非常方便,可以通过下列几个步骤进行. 下载jQuery文件库 在jQuery的官方网站(http://jquery.com)中,下载最新版本的jQuery文件库 ...
- JQuery基础总结上
最近在慕课网学习JQuery基础课程,发现只是跟随网站的课程学习而不去自己总结扩展的话,很难达到真正学会理解的地步. 于是先在网站上草草过了一遍课程,然后借着今天的这个时间边记录边重新整理学习一下. ...
- 一个简单的、面向对象的javascript基础框架
如果以后公司再能让我独立做一套新的完整系统,那么我肯定会为这个系统再写一个前端框架,那么我到底该如何写这个框架呢? 在我以前的博客里我给大家展示了一个我自己写的框架,由于当时时间很紧张,做之前几乎没有 ...
- jquery基础知识汇总
jquery基础知识汇总 一.简介 定义 jQuery创始人是美国John Resig,是优秀的Javascript框架: jQuery是一个轻量级.快速简洁的javaScript库.源码戳这 jQu ...
- JeeSite 企业信息管理系统基础框架
1. JeeSite概述 1.1. 简介 JeeSite是一个开源的企业信息管理系统基础框架.主要定位于“企业信息管理”领域,可用作企业信息管理类系统.网站后台管理类系统等.JeeSite是非常强调开 ...
- JQuery EasyUI框架学习
前言 新项目的开发前端技术打算採用EasyUI框架(基于EasyUI较为丰富的UI组件库),项目组长将前端EasyUI这块的任务分配给了我.在进行开发之前,须要我这菜鸟对EasyUI框架进行一些基础的 ...
- 如莲开发平台(MIS基础框架、Java技术、B/S结构)
关于 「如莲」是一套MIS类系统基础框架,主要用于各类“管理信息系统”的开发,也适合做网站后台开发.可省去开发时的框架搭建.规范约定.权限管理等基础工作,直接专注于业务功能实现. 「如 ...
- jQuery 基础语法
jQuery介绍 1.jQuery是一个轻量级的.兼容多浏览器的JavaScript库. 2.jQuery使用户能够更方便地处理HTML Document.Events.实现动画效果.方便地进行Aja ...
随机推荐
- mui+vue+photoclip做APP头像裁剪上传
做APP由于项目需要,需要做用户头像上传的功能,头像上传包括拍照和相册选择图片进行上传,这里使用的技术是mui封装的plus,在进行图片裁剪的时候,使用的是photoclip来进行裁剪,由于个人在使用 ...
- python面向对象高级:Mixin多重继承
继上一篇学习笔记:python面向对象的继承与多态,本篇就Mixin扩展类的方法写下学习笔记 Mixin Mixin编程是一种开发模式,是一种将多个类中的功能单元的进行组合的利用的方式,这听起来就像是 ...
- SSL/TLS 握手优化详解
随着 HTTP/2 的逐渐普及,以及国内网络环境越来越糟糕(运营商劫持和篡改),HTTPS 已经开始成为主流.HTTPS 在 TCP 和 HTTP 之间增加了 TLS(Transport Layer ...
- QS Network---zoj1586最小生成树
Description Sunny Cup 2003 - Preliminary Round April 20th, 12:00 - 17:00 Problem E: QS Network In th ...
- Celery 分布式任务队列入门
一.Celery介绍和基本使用 Celery 是一个 基于python开发的分布式异步消息任务队列,通过它可以轻松的实现任务的异步处理, 如果你的业务场景中需要用到异步任务,就可以考虑使用celery ...
- noip做题记录+挑战一句话题解?
因为灵巧实在太弱辽不得不做点noip续下命QQAQQQ 2018 积木大赛/铺设道路 傻逼原题? 然后傻逼的我居然检查了半天是不是有陷阱最后花了差不多一个小时才做掉我做过的原题...真的傻逼了我:( ...
- Python命令行解析库argparse(转)
原文:http://www.cnblogs.com/linxiyue/p/3908623.html 2.7之后python不再对optparse模块进行扩展,python标准库推荐使用argparse ...
- 查找第K小的元素(利用中位数线性时间选择)(C)
找任意第k个小的元素 #include <stdio.h> #include <stdlib.h> #include <ctime> #include <io ...
- Qt计算器开发(三):执行效果及项目总结
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/guodongxiaren/article/details/26046543 执行效果 project ...
- Pycharm模板添加默认信息
我们在Pycharm中使用到python3.x版本的解释器,完全没有问题可以正常使用,但是有的时候多少会出现使用python2的时候 我们明明都把代码和文字注释了,为什么使用的时候还会报错呢?? 报错 ...