【zepto学习笔记02】零碎点
前言
上次我们看了zepto的选择器方面的东西,其实zepto简单很大程度是因为他用了最新的检索器querySelectorAll,
今天我们来学习下zepto的一些零碎点的地方吧,主要根据zepto官方文档顺序来
contains (parent, node)
该方法用于检测父节点是否包含给定的dom节点,如果两者相同则返回false
contains 为javascript的基本语法,首先在ie中,最后其它浏览器也扩展了,如果a包含b则返回true
p = document.getElementById('parent'),
c = document.getElementById('child');
log(p.contains(c)); //true
log(c.contains(p));//false
这个是zepto的实现,与其说实现不如说是封装
$.contains = function (parent, node) {
return parent !== node && parent.contains(node)
}
each
each这个方法我们平时用的比较多,并且感觉很好用,很多朋友使用for可能会导致这样那样的问题,但是使用each却变好了
是因为each封装了一个闭包,所以可以解决一些初学朋友的BUG,到时隐藏的BUG总会爆发,先遇到也不是什么坏事
zepto的实现如下:
$.each = function (elements, callback) {
var i, key
if (likeArray(elements)) {
for (i = 0; i < elements.length; i++)
if (callback.call(elements[i], i, elements[i]) === false) return elements
} else {
for (key in elements)
if (callback.call(elements[key], key, elements[key]) === false) return elements
}
return elements
}
如果我们的回调有一个返回了false,那么就会跳出整个循环,我曾经看到有人在里面写break,break对js有点不靠谱的
我们这里提一个可能发生的问题,代码可能没有实际意义,大概可以表达意思:
var sum1 = 0, sum2 = 0, sum3 = 0; len = 2;
var arr = [];
for (var i = 0; i < len; i++) {
arr.push(i)
}
for (var i = 0; i < len; i++) {
setTimeout(function () {
sum1 += arr[i];
}, 0);
}
$.each(arr, function (i, v) {
setTimeout(function () {
sum2 += v;
}, 0);
});
for (var i = 0; i < len; i++) {
sum3++;
}
//sum3不管,答出len=2与len=200000时,sum1,sum2的值
console.log(sum1);
console.log(sum2);
console.log(sum3);
这个例子是我昨天一个问题思考出来的,答案非常经典,因为本来我是想要说明闭包的问题,却不自主的引入了另外一个神器
settimeout
这样写的话,无论如何sum1与sum2都是0,就算把len改的很大,明明已经过了1s了答案依旧是0
由此各位可以意识到settimeout不是我最初想象那么简单了,并不是多少秒后就会执行,而是完全从主干流程脱离出来
主干如果进行复杂的代码运算,甚至耗费几秒,我们的settimeout也不会执行
比如我们说下一个例子:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<meta name="viewport" content="width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
<style>
#list { display: block; position: absolute; top: 100px; left: 10px; width: 200px; height: 100px; }
div { display: block; border: 1px solid black; height: 500px; width: 100%; }
#input { width: 80px; height: 200px; display: block; }
</style>
<script id="others_zepto_10rc1" type="text/javascript" class="library" src="/js/sandbox/other/zepto.min.js"></script>
</head>
<body>
<input type="button" value="获取焦点" id="bt" />
<div id="divBt" style="width: 100px; height: 40px; background-color: Red;">
div按钮</div>
<br />
<div id="d">
<input type="text" id="input" />
<div id="list">
</div>
</div>
</body>
<script type="text/javascript">
var list = $('#list');
var d = $('#d');
var input = $('#input');
input.tap(function (e) {
e.stopPropagation();
e.preventDefault();
input.val(new Date().getTime());
return false;
});
list.tap(function (e) {
$('body').css("pointer-events", "none");
list.hide();
console.log(e);
setTimeout(function () {
e.stopPropagation();
console.log(e);
}, 0)
setTimeout(function () {
list.show();
}, 1250);
setTimeout(function () {
$('body').css("pointer-events", "auto");
}, 50);
});
d.tap(function () {
d.append($('<p>div tap</p>'));
});
$('#bt').tap(function () {
var s = input.val() + new Date().getTime();
input.val(s)
input.focus();
});
$('#divBt').tap(function () {
input.focus();
});
</script>
</html>
这个例子是我最近遇到的一个问题,个人认为比较经典,我们点击里面的div会冒泡执行外面的div事件,但是我们可以 e.stopPropagation();
这样阻止冒泡,但是如果我们代码写成这样的话:
setTimeout(function () {
list.show();
}, 1250);
那么对不起,阻止冒泡是不起作用的
这个问题影响比较深远比如zepto的touch源码最后关键部分:
on('touchend MSPointerUp', function (e) {
// ......
else if ('last' in touch)
if (deltaX < 30 && deltaY < 30) {
tapTimeout = setTimeout(function () {
var event = $.Event('tap')
event.cancelTouch = cancelAll
touch.el.trigger && touch.el.trigger(event)
if (touch.isDoubleTap) {
touch.el.trigger && touch.el.trigger('doubleTap')
touch = {}
}
else {
touchTimeout = setTimeout(function () {
touchTimeout = null
touch.el.trigger && touch.el.trigger('singleTap')
touch = {}
}, 250)
}
}, 0)
} else {
touch = {}
}
deltaX = deltaY = 0
})
这里触发了tap事件(touch.el.trigger(event) ),但是在这个位置执行什么阻止冒泡等操作毫无意义,原因就是外层的settimeout(function(){}, 0)
好了,这里扯得有点远,我们继续刚刚的闭包问题,如果我们将最后打印改成这样,答案依旧难辨,因为我们看着题目容易臆测,而忽略实际问题:
setTimeout(function () {
console.log(sum1);
console.log(sum2);
console.log(sum3);
}, 1)
这里sum1的值居然是NaN,因为我以为他会是0undefined,所以不能臆测啊!
这里说回来大家都会知道产生了闭包,而each解决了闭包问题,而for最后i的值是2,而我们的arr自然取不到值
PS:不知道这个例子可以说明each的用途没有......
$.extend(target, [source, [source2, ...]])
该方法比较有用,用于通过源对象扩展目标对象属性,源对象属性将覆盖目标对象属性,默认为浅赋值,true的话便会连余下对象一起复制
var target
= { one:
'patridge'
},
source = {
two: 'turtle doves'
}
$.extend(target, source)
//=> { one: 'patridge',
// two: 'turtle doves' }
我们来看看源码实现:
function extend(target, source, deep) {
for (key in source)
//如果深度扩展
if (deep && (isPlainObject(source[key]) || isArray(source[key]))) {
//如果要扩展的数据是对象且target相对应的key不是对象
if (isPlainObject(source[key]) && !isPlainObject(target[key])) target[key] = {}
//如果要扩展的数据是数组且target相对应的key不是数组
if (isArray(source[key]) && !isArray(target[key])) target[key] = []
extend(target[key], source[key], deep)
} else if (source[key] !== undefined) target[key] = source[key]
}
这个代码很清晰,不是深度扩展时候仅仅是单纯的复制,由此可能可以回答一些可能被问到的问题:
源对象和复制对象有相同的属性会被覆盖吗?答案是会的
然后看这个深度拷贝,就会递归的将复制对象的对象给复制过去
PS:深度克隆与浅克隆的区别是复制对象变了源对象相关属性不会跟着改变,这就是区别(在java就是引用与值的区别)
$.grep(items, function(item){ ... })
这个方法是用于筛选数组的,新数组只包含回调函数中返回 ture 的数组项,这个代码就不关注了,他底层还是调用的javascript数组的方法
if (!Array.prototype.filter)
{
Array.prototype.filter = function(fun /*, thisp*/)
{
var len = this.length;
if (typeof fun != "function")
throw new TypeError(); var res = new Array();
var thisp = arguments[1];
for (var i = 0; i < len; i++)
{
if (i in this)
{
var val = this[i]; // in case fun mutates this
if (fun.call(thisp, val, i, this))
res.push(val);
}
}
return res;
};
} $.inArray(element, array, [fromIndex])
搜索数组中指定值并返回它的索引(如果没有找到则返回-1)。[fromIndex] 参数可选,表示从哪个索引值开始向后查找。
这个函数底层依旧是调用javascript数组原生的方法:
$.inArray = function (elem, array, i) {
return emptyArray.indexOf.call(array, elem, i)
}
$.parseJSON(string)
这个方法在最新的javascript语法出来时非常有用,我们原来一般是这样干的:
var json = eval('(' + str + ')');
后面我们就这样干了:
if (window.JSON) $.parseJSON = JSON.parse
所以这个方法,我们暂时不必关注了,因为zepto面向的是高版本浏览器,所以他基本也不关注这个问题
好了,我们看到这里有几个方法比较重要了!
add(selector, [context])
添加元素到匹配的元素集合。如果content参数存在,只在content中进行查找,否则在document中查找。
<ul>
<li>list item 1</li>
<li>list item 2</li>
<li>list item 3</li>
</ul>
<p>a paragraph</p> <script type="text/javascript">
$('li').add('p').css('background-color', 'red');
</script>
add: function (selector, context) {
return $(uniq(this.concat($(selector, context)))) //追加并去重
}, uniq = function (array) {
return filter.call(array, function (item, idx) {
return array.indexOf(item) == idx
})
}
PS:concat是数组本身的方法
我们这里来一点点搞下这个代码逻辑:
① $(selector, context)
该方法为一个dom选择器,根据我们上次的研究,他会返回我们的封装后的dom集合
② this.concat(el)
我们知道this当前指向就是被包装的dom数组对象,所以这里就将两个方法连接起来了
现在不管真实页面结构渲染是否变化,反正包装的dom结构被连接了
③ uniq(el)
稍后,这个代码读了后我整个人迷糊了!!!我们来看个例子
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script id="others_zepto_10rc1" type="text/javascript" class="library" src="/js/sandbox/other/zepto.min.js"></script>
<script src="../../zepto.js" type="text/javascript"></script>
</head>
<body>
<ul>
<li>list item 1</li>
<li>list item 2</li>
<li>list item 3</li>
</ul>
<p>
a paragraph</p>
</body>
<script type="text/javascript">
$('ul').add('p').css('background-color', 'red');
</script>
</html>
按照他的意思,我们ul就应该加到p后面,但是运行结构并不是这样的......所以该方法暂时忽略......
addClass
好了,我们来看看我们的addClass是干什么的
addClass: function (name) {
return this.each(function (idx) {
classList = []
var cls = className(this),
newName = funcArg(this, name, idx, cls)
//处理同时多个类的情况,用空格分开
newName.split(/\s+/g).forEach(function (klass) {
if (!$(this).hasClass(klass)) classList.push(klass)
}, this)
classList.length && className(this, cls + (cls ? " " : "") + classList.join(" "))
})
},
这个each是可以理解的,就是操作每一个dom结构,所以我们将代码看成这个样子:
classList = []
var cls = className(this),
newName = funcArg(this, name, idx, cls)
//处理同时多个类的情况,用空格分开
newName.split(/\s+/g).forEach(function (klass) {
if (!$(this).hasClass(klass)) classList.push(klass)
}, this)
classList.length && className(this, cls + (cls ? " " : "") + classList.join(" ")) 这里有使用了className方法,所以我们来看看: function className(node, value) {
var klass = node.className, svg = klass && klass.baseVal !== undefined
if (value === undefined) return svg ? klass.baseVal : klass
svg ? (klass.baseVal = value) : (node.className = value)
}
多余的东西也不管,意思就是没有value就是获取值,有就是设置,这里是原生的dom操作
然后是funcArg方法
//这个函数在整个库中取着很得要的作用,处理arg为函数或者值的情况
//下面很多设置元素属性时的函数都有用到
function funcArg(context, arg, idx, payload) {
return isFunction(arg) ? arg.call(context, idx, payload) : arg
}
这个第二个参数可以是一个函数,如果是就执行,并使用本身作为作用域,如果不是就自己返回,我们现在的做法就直接返回class名了
下面的代码就比较简单了,就是拼接字符串,组成新的class,然后赋给dom就结束了,所以addClass也就结束了,removeClass我们就不管了
append
这个方法非常庞大,虽然只有这么一个方法,但是before、after等都在这里实现了
adjacencyOperators = ['after', 'prepend', 'before', 'append']
adjacencyOperators.forEach(function (operator, operatorIndex) {
var inside = operatorIndex % 2 //=> prepend, append
$.fn[operator] = function () {
// arguments can be nodes, arrays of nodes, Zepto objects and HTML strings
var argType, nodes = $.map(arguments, function (arg) {
argType = type(arg)
return argType == "object" || argType == "array" || arg == null ? arg : zepto.fragment(arg)
}),
parent, copyByClone = this.length > 1 //如果集合的长度大于集,则需要clone被插入的节点
if (nodes.length < 1) return this
return this.each(function (_, target) {
parent = inside ? target : target.parentNode
//通过改变target将after,prepend,append操作转成before操作,insertBefore的第二个参数为null时等于appendChild操作
target = operatorIndex == 0 ? target.nextSibling : operatorIndex == 1 ? target.firstChild : operatorIndex == 2 ? target : null
nodes.forEach(function (node) {
if (copyByClone) node = node.cloneNode(true)
else if (!parent) return $(node).remove()
//插入节点后,如果被插入的节点是SCRIPT,则执行里面的内容并将window设为上下文
traverseNode(parent.insertBefore(node, target), function (el) {
if (el.nodeName != null && el.nodeName.toUpperCase() === 'SCRIPT' && (!el.type || el.type === 'text/javascript') && !el.src) window['eval'].call(window, el.innerHTML)
})
})
})
}
// after => insertAfter
// prepend => prependTo
// before => insertBefore
// append => appendTo
$.fn[inside ? operator + 'To' : 'insert' + (operatorIndex ? 'Before' : 'After')] = function (html) {
$(html)[operator](this)
return this
}
})
这里inside只会取到0,1两种值,然后就开始初始化方法了,比如:
$.fn.append = function() {};
因为我们调用一般是这样干的:
$('$id').append($('dom'))
这里的this就是前面的dom集合,因为可能不止一个节点,所以每个节点都会被插入新节点,但是我们一般只给一个节点插东西
这里用到了map方法,我们来看看:
//遍历elements,将每条记录放入callback里进宪处理,保存处理函数返回值不为null或undefined的结果
//注意这里没有统一的用for in,是为了避免遍历数据默认属性的情况,如数组的toString,valueOf
$.map = function (elements, callback) {
var value, values = [],
i, key
//如果被遍历的数据是数组或者nodeList
if (likeArray(elements)) for (i = 0; i < elements.length; i++) {
value = callback(elements[i], i)
if (value != null) values.push(value)
} else
//如果是对象
for (key in elements) {
value = callback(elements[key], key)
if (value != null) values.push(value)
}
return flatten(values)
}
我们从代码看来,这个方法是用于数组过滤,与filter有点类似
所以,这里的使用map函数保证了nodes是比较靠谱的dom节点集合,如果长度为0 就直接返回了
然后下面开始遍历我们的this dom节点,依次做操作,这里有个需要注意的地方,如果this包含的节点不止一个,那么每个节点都会被插入
所以他这里提供了一个克隆的功能,可能出来节点,因为dom上只有一个节点,被不断的append也只是移动位置
cloneNode是javascript dom 本身的一个方法,直接使用即可,但是要注意id不要重复
然后根据inside不同而选取不同的parentNode,这应该与插入点有关系了,因为原生javascript只支持appendChild与insertBefore
这里调用traverseNode方法前,就将dom操作结束了,
这里还区分了是不是script标签,这里又有一个较关键的方法:traverseNode,他会执行我们的javascript
function traverseNode(node, fun) {
fun(node)
for (var key in node.childNodes) traverseNode(node.childNodes[key], fun)
}
这里有两个循环,外层each里层forEach,所以节点就全部插入了......至此这个方法也基本结束
值得一提的是最后这个代码段:
$.fn[inside ? operator + 'To' : 'insert' + (operatorIndex ? 'Before' : 'After')] = function (html) {
$(html)[operator](this)
return this
}
//相当于:
$.fn.insertAfter = function(html) {
$(html).prepend(this);
retrun;
}
其中,this指的是包装的dom集合,html为我们传入的dom对象或者dom字符串,下面的方法就是我们上面定义的
attr(name, value)
该方法,比较常用,我们一般用他来为dom元素设置属性,获取属性,但是他还可以传入函数哦......
attr = function (name, value) {
var result
//当只有name且为字符串时,表示获取第一条记录的属性
return (typeof name == 'string' && value === undefined) ?
//集合没有记录或者集合的元素不是node类型,返回undefined
(this.length == 0 || this[0].nodeType !== 1 ? undefined :
//如果取的是input的value
(name == 'value' && this[0].nodeName == 'INPUT') ? this.val() :
//注意直接定义在node上的属性,在标准浏览器和ie9,10中用getAttribute取不到,得到的结果是null
//比如div.aa = 10,用div.getAttribute('aa')得到的是null,需要用div.aa或者div['aa']这样来取
(!(result = this[0].getAttribute(name)) && name in this[0]) ? this[0][name] : result) :
this.each(function (idx) {
if (this.nodeType !== 1) return
//如果name是一个对象,如{'id':'test','value':11},则给数据设置属性
if (isObject(name)) for (key in name) setAttribute(this, key, name[key])
//如果name只是一个普通的属性字符串,用funcArg来处理value是值或者function的情况最终返回一个属性值
//如果funcArg函数返回的是undefined或者null,则相当于删除元素的属性
else setAttribute(this, name, funcArg(this, value, idx, this.getAttribute(name)))
})
}
获取代码比较简单,值得注意的是,他只会获取我们第一个dom属性的值
this[0].getAttribute(name)
设置值的时候当然又是一个循环了(setAttribute)
css(property, value)
这个方法也比较常用,很大情况下雨attr比较类似,看源码前我们先思考下,为什么没有removeCss
为什么没有removeCss?
当然是因为,我们样式表问题,所以removeCss就没有意义了
好了,现在我们来看看源码:
css: function (property, value) {
//获取指定的样式
if (arguments.length < 2 && typeof property == 'string') return this[0] && (this[0].style[camelize(property)] || getComputedStyle(this[0], '').getPropertyValue(property))
//设置样式
var css = ''
if (type(property) == 'string') {
if (!value && value !== 0) //当value的值为非零的可以转成false的值时如(null,undefined),删掉property样式
this.each(function () {
//style.removeProperty 移除指定的CSS样式名(IE不支持DOM的style方法)
this.style.removeProperty(dasherize(property))
})
else css = dasherize(property) + ":" + maybeAddPx(property, value)
} else {
//当property是对象时
for (key in property)
if (!property[key] && property[key] !== 0)
//当property[key]的值为非零的可以转成false的值时,删掉key样式
this.each(function () {
this.style.removeProperty(dasherize(key))
})
else css += dasherize(key) + ':' + maybeAddPx(key, property[key]) + ';'
}
//设置
return this.each(function () {
this.style.cssText += ';' + css
})
}
camelize是将aa-bb这种明明改为aaBb这种驼峰命名,首先比较简单,会从style里面获取style的值,不行就看样式表
具代码,是对象情况还要做其它处理,其中好像给css设置为null时候可以取消样式,我们来试试(IE不管)
最后试验证明是不靠谱的,所以我们不要向去removeCss了吧:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<meta name="viewport" content="width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
<style>
#list { display: block; position: absolute; top: 100px; left: 10px; width: 200px; height: 100px; background-color: black; }
</style>
<script src="../../zepto.js" type="text/javascript"></script>
</head>
<body>
<div id="list">
</div>
</body>
<script type="text/javascript">
$('#list').css('background-color', false);
alert($('#list').css('background-color'))
</script>
</html>
width/height
这个与el.css('width')类似:
['width', 'height'].forEach(function (dimension) {
$.fn[dimension] = function (value) {
var offset, el = this[0],
//将width,hegiht转成Width,Height,用于取window或者document的width和height
Dimension = dimension.replace(/./, function (m) {
return m[0].toUpperCase()
})
//没有参数为获取,获取window的width和height用innerWidth,innerHeight
if (value === undefined) return isWindow(el) ? el['inner' + Dimension] :
//获取document的width和height时,用offsetWidth,offsetHeight
isDocument(el) ? el.documentElement['offset' + Dimension] : (offset = this.offset()) && offset[dimension]
else return this.each(function (idx) {
el = $(this)
el.css(dimension, funcArg(this, value, idx, el[dimension]()))
})
}
})
ready
该方法也比较常用,在页面dom加载结束后执行里面的方法
DOMContentLoaded事件是文档加载结束后执行,老浏览器不支持就是load
ready: function (callback) {
if (readyRE.test(document.readyState)) callback($)
else document.addEventListener('DOMContentLoaded', function () {
callback($)
}, false)
return this
},
结语
今天暂时到这,我们下次看看zepto事件相关的实现
【zepto学习笔记02】零碎点的更多相关文章
- 软件测试之loadrunner学习笔记-02集合点
loadrunner学习笔记-02集合点 集合点函数可以帮助我们生成有效可控的并发操作.虽然在Controller中多用户负载的Vuser是一起开始运行脚本的,但是由于计算机的串行处理机制,脚本的运行 ...
- 机器学习实战(Machine Learning in Action)学习笔记————02.k-邻近算法(KNN)
机器学习实战(Machine Learning in Action)学习笔记————02.k-邻近算法(KNN) 关键字:邻近算法(kNN: k Nearest Neighbors).python.源 ...
- OpenCV 学习笔记 02 使用opencv处理图像
1 不同色彩空间的转换 opencv 中有数百种关于不同色彩空间的转换方法,但常用的有三种色彩空间:灰度.BRG.HSV(Hue-Saturation-Value) 灰度 - 灰度色彩空间是通过去除彩 ...
- SaToken学习笔记-02
SaToken学习笔记-02 如果排版有问题,请点击:传送门 常用的登录有关的方法 - StpUtil.logout() 作用为:当前会话注销登录 调用此方法,其实做了哪些操作呢,我们来一起看一下源码 ...
- Redis:学习笔记-02
Redis:学习笔记-02 该部分内容,参考了 bilibili 上讲解 Redis 中,观看数最多的课程 Redis最新超详细版教程通俗易懂,来自 UP主 遇见狂神说 4. 事物 Redis 事务本 ...
- OGG学习笔记02
实验环境:源端:192.168.1.30,Oracle 10.2.0.5 单实例目标端:192.168.1.31,Oracle 10.2.0.5 单实例 1.模拟源数据库业务持续运行 2.配置OGG前 ...
- 《Master Bitcoin》学习笔记02——比特币的交易模型
比特币的交易模型 模型基本描述 前面一篇学习笔记01提到了一个交易模型(第三章的内容),在第五章中,除了对这个模型做个详细介绍之外,其实和我上一篇理解的交易模型差不多,一个交易包含输入与输出,比特币是 ...
- [Golang学习笔记] 02 命令源码文件
源码文件的三种类型: 命令源文件:可以直接运行的程序,可以不编译而使用命令“go run”启动.执行. 库源码文件 测试源码文件 面试题:命令源码文件的用途是什么,怎样编写它? 典型回答: 命令源码文 ...
- [原创]java WEB学习笔记02:javaWeb开发的目录结构
本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...
随机推荐
- 如何下载android官网Lib包
例如:https://dl-ssl.google.com/android/repository/sources-23_r01.zip
- 深入理解CSS元素可见性visibility
× 目录 [1]定义 [2]属性 [3]display[4]JS[5]transition [6]API[7]DEMO 前面的话 visibility属性常见于与display属性的比较中.但实际上, ...
- Angular从0到1:function(上)
1.前言 Angular作为最流行的前端MV*框架,在WEB开发中占据了重要的地位.接下来,我们就一步一步从官方api结合实践过程,来学习一下这个强大的框架吧. Note:每个function描述标题 ...
- 基于Metronic的Bootstrap开发框架经验总结(7)--数据的导入、导出及附件的查看处理
在很多系统模块里面,我们可能都需要进行一定的数据交换处理,也就是数据的导入或者导出操作,这样的批量处理能给系统用户更好的操作体验,也提高了用户录入数据的效率.我在较早时期的EasyUI的Web框架上, ...
- Office Visio简介
Office Visio,是VISIO公司在91年推出的用于制作图表的软件(现在微软收购),在早期它主要用作商业图表制作,后来随着版本的不断提高,新增了许多功能.大多数图形软件程序依赖于艺术技能.Of ...
- exp/imp 参数说明,中英对照
在任意可用exp/imp(导出/导入)命令的主机上,都可以通过exp/imp help=y查看所有的参数说明. 1.exp参数说明 2.imp参数说明 3.exp参数说明(中文) 4.imp参数说明( ...
- web基础---->request的请求参数分析
当contentType为application/json的时候,在servlet中通过request.getParameter得到的数据为空.今天我们就java的请求,分析一下request得到参数 ...
- 【原创】利用typeface实现不同字体的调用显示及String转换为Unicode
最近工作用到,就写个小demo demo实现从assets中利用typeface调用不同字体,并在editText中显示出来 1.layout中创建activity_main.xml文件 布局代码如下 ...
- SQL Server代理(5/12):理解SQL代理错误日志
SQL Server代理是所有实时数据库的核心.代理有很多不明显的用法,因此系统的知识,对于开发人员还是DBA都是有用的.这系列文章会通俗介绍它的很多用法. 如我们在这个系列的前几篇文章所见,SQL ...
- Android开发中遇到的requestFeature() must be called before adding content异常
缘起 上一篇博文中讲到了几种实现全屏显示Activity内容的方法.然而实际在实现中发现了一些问题,在本篇博文中进行总结下.首先交代一下开发环境,本人使用的是Android Studio 1.5.1, ...