harleywang93 / learning Goto Github PK
View Code? Open in Web Editor NEW学习
学习
ECMAScript 规定了三种声明函数方式
var sayHello = new Function("console.log('hello world');");
//函数声明
function sayHello(){
console.log('hello')
}
//函数调用
sayHello()
声明不必放到调用的前面
var sayHello = function(){
console.log('hello');
}
sayHello()
声明必须放到调用的前面
getName()//oaoafly
var getName = function() {
console.log('wscat')
}
getName()//wscat
function getName() {
console.log('oaoafly')
}
getName()//wscat
因为变量提升,上面的代码等同于下面的形式
var getName//undefined
function getName() {
console.log('oaoafly')
}//虽然函数声明在最后,但是被提升到前面了
getName()//oaoafly
var getName = function() {
console.log('wscat')
}//此时函数表达式覆盖了函数声明的值
getName()//wscat
getName()//wscat
变量的声明前置:指的是 JavaScript 解析器将当前作用域内声明的所有变量放到作用域的开始处,但是,只有变量的声明被前置了(值都为undefined),而赋值操作被保留在原处。
函数的声明前置:JavaScript 解释器允许在函数声明之前使用函数,此时不仅仅是函数名被前置了,整个函数定义也被前置了,所以可以直接调用函数。
arguments[1、2、3]
,我们可以获取到相应的传入参数。 function printPeopleInfo(name, age, sex){
if(name){
console.log(name);
}
if(age){
console.log(age);
}
if(sex){
console.log(sex);
}
}
printPeopleInfo('Byron', 26);
printPeopleInfo('Byron', 26, 'male');
(function(){
var a = 1;
})()
console.log(a); //undefined
其他写法:
[function fn2() {
alert(22)
}()];// 在数组初始化器内只能是表达式
1, function fn3() {
alert(33)
}();// 逗号也只能操作表达式
function factor(n){
if( n === 1 || n ===0 ) {
return 1;
} else if ( n < 0 ){
return;
} else {
return n*factor(n-1);
}
}
function getInfo(name, age, sex){
console.log('name:',name);
console.log('age:', age);
console.log('sex:', sex);
console.log(arguments);
arguments[0] = 'valley';
console.log('name', name);
}
getInfo('饥人谷', 2, '男');
getInfo('小谷', 3);
getInfo('男');
name:饥人谷 age:2 sex:男 ['饥人谷',2,'男'] name vally
name:小谷 age:3 sex:undefined ['小谷',3] name vally
name:男 age:undefined sex:undefined ['男'] name vally
function sumOfSquares(){
var result = 0;
for (var i = 0; i < arguments.length; i++) {
result = result + arguments[i] * arguments[i];
}
console.log(result)
}
var result = sumOfSquares(2,3,4)
var result2 = sumOfSquares(1,3)
console.log(result) //29
console.log(result2) //10
console.log(a);
var a = 1;
console.log(b);
由于变量的声明前置,上面的代码等同于下面的形式:
var a;//undefined
console.log(a);//undefined
a=1;
console.log(b);//报错,b没有进行变量声明。
sayName('world');
sayAge(10);
function sayName(name){
console.log('hello ', name);
}
var sayAge = function(age){
console.log(age);
}
因为函数的声明前置,上面的代码等同于下面的形式:
function sayName(name){
console.log('hello ', name);
}
sayName('world');//hello,world
sayAge(10);//报错,因为函数表达式放必须在调用前面
var sayAge = function(age){
console.log(age);
}
var x = 10
bar()
function foo() {
console.log(x)
}
function bar(){
var x = 30
foo()
}
globalContext = {
AO: {
x: 10
foo: function
bar: function
}
}
f00.[[scope]] = globalContext.AO
bar.[[scope]] = globalContext.AO
barContext = {
AO: {
x: 30
},
Scope: bar.[[scope]] = globalContext.AO
}
fooContext = {
AO : {},
Scope: foo.[[scope]] = globalContext.AO
}
输出 10
var x = 10;
bar()
function bar(){
var x = 30;
function foo(){
console.log(x)
}
foo();
}
globalContext = {
AO: {
x: 10
bar: function
}
}
bar.[[scope]] = globalContext.AO
barContext = {
AO: {
x: 30
foo: function
},
Scope: bar.[[scope]] = globalContext.AO
}
foo.[[scope]] = barContext.AO
fooContext = {
AO: {},
Scope: foo.[[scope]] = barContext.AO
}
输出 30
var x = 10;
bar()
function bar(){
var x = 30;
(function (){
console.log(x)
})()
}
globalContext = {
AO: {
x: 10
bar: function(){}
}
}
bar.[[scope]] = globalContext.AO
barContext = {
AO: {
x: 30
IIFE: function(){}
},
Scope: barContext.AO
}
IIFE.[[scope]] = barContext.AO
IIFEContext = {
AO: {}
Scope: barContext.AO
}
输出 30
var a = 1;
function fn(){
console.log(a)
var a = 5
console.log(a)
a++
var a
fn3()
fn2()
console.log(a)
function fn2(){
console.log(a)
a = 20
}
}
function fn3(){
console.log(a)
a = 200
}
fn()
console.log(a)
globalContext = {
AO: {
a: 200
fn: function(){}
fn3: function(){}
}
}
fn.[[scope]] = globalContext.AO
fn3.[[scope]] = globalContext.AO
fnContext = {
AO: {
a: 20
fn2: function(){}
},
Scope: globalContext.AO
}
fn2.[[scope]] = fnContext.AO
fn3Context = {
AO: {},
Scope: globalContext.AO
}
fn2Context = {
AO: {},
Scope: fnContext.AO
}
输出 undefined 5 1 6 20 200
<link rel="stylesheet" href="" />
,浏览器再向服务器发起请求,服务器返回字符串和Content-Type=text/css,浏览器就把返回的字符串当 CSS 进行解析;<script src="" />
,浏览器向服务器发起请求,服务器返回字符串和Content-Type=text/javascript,浏览器就把字符串当 JS 进行解析,返回给用户。var prod = {
name: '女装',
styles: ['短款', '冬季', '春装']
};
function getTpl(data){
//todo...
};
var result = getTplStr(prod); //result为下面的字符串
<dl class="product"><dt>女装</dt><dd>短款</dd><dd>冬季</dd><dd>春装</dd></dl>
方法一:
var product = {
name: '女装',
styles: ['短款', '冬季', '春装']
}
function getTpl(product) {
var str = '<dl class="product">'
str += ' <dt>' + product.name + '</dt>'
for(var i = 0; i < product.styles.length; i++) {
str += ' <dd>' + product.styles[i] + '</dd>'
}
str += ' </dl>'
return str;
}
var result = getTpl(product)
console.log(result)
方法二:
var product = {
name: '女装',
styles: ['短款', '冬季', '春装']
}
function getTpl(product) {
var html = []
html.push('<dl class="product">')
html.push(' <dt>' + product.name + '</dt>')
for(var i = 0; i < product.styles.length; i++) {
html.push(' <dd>' + product.styles + '</dd>')
}
html.push(' <dl>')
return html.join('');
}
var result = getTpl(product)
console.log(result)
例如:
var str = 'abcdeabcdeabcdeancdeabcdeabcdeabcdeancdeabcdeabcdeabcdeancdeabcdeabcdeabcdeancde'
方法一(不推荐使用)
var str = 'abcdeabcdeabcdeancde\
abcdeabcdeabcdeancde\
abcdeabcdeabcdeancde\
abcdeabcdeabcdeancde';
方法二
var str = 'abcdeabcdeabcdeancde\nabcdeabcdeabcdeancde\nabcdeabcdeabcdeancde\nabcdeabcdeabcdeancde'
方法三
var str = 'abcdeabcdeabcdeancde\n'
+ 'abcdeabcdeabcdeancde\n'
+ 'abcdeabcdeabcdeancde\n'
+ 'abcdeabcdeabcdeancde\n'
方法四
(function (){/*
abcdeabcdeabcdeancde
abcdeabcdeabcdeancde
abcdeabcdeabcdeancde
abcdeabcdeabcdeancde
*/}).toString().split('\n').slice(1,-1).join('\n');
var str = 'hello\\\\饥人谷'
console.log(str)
var str = 'jirengu\nruoyu'
console.log(str.length)//13 \n 为转义字符,转义字符只占据一个字符,且空格不算在字符长度里。
function isPalindrome(str) {
return str === str.split('').reverse().join('')
}
var str1 = 'abcdcba'
var str2 = 'abcdcbb'
isPalindrome(str1)//true
isPalindrome(str2)//false
var str = 'I must find a fucking nooooooooooob job in autumn!'
var dict = {}
var count = 0
var maxValue
for(var i = 0; i < str.length; i++){
if(dict[str[i]]){
++dict[str[i]]
}else{
dict[str[i]] = 1
}
}
for(key in dict){
if(dict[key] > count){
maxValue = key
count = dict[key]
}
}
console.log(count,maxValue)
camelize("background-color") == 'backgroundColor'
camelize("list-style-image") == 'listStyleImage'
function camelize(str) {
var arr = str.split('-')
for(var i = 1; i < arr.length; i++){
arr[i] = arr[i][0].toUpperCase() + arr[i].substr(1)
}
return arr.join('')
}
console.log( camelize("background-color"))
console.log( camelize("list-style-image"))
ucFirst("hunger") == "Hunger"
function ucFirst(str){
return str[0].toUpperCase() + str.substr(1)
}
truncate("hello, this is hunger valley,", 10) == "hello, thi...";
truncate("hello world", 20) == "hello world"
function truncate(str,maxlength){
if(str.length <= maxlength){
return str
}else{
return str.substr(0,maxlength) + '...'
}
}
console.log(truncate("hello, this is hunger valley,", 10))
console.log(truncate("hello world", 20))
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式。它基于JavaScript(Standard ECMA-262 3rd Edition - December 1999)的一个子集。 JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C, C++, C#, Java, JavaScript, Perl, Python等)。这些特性使 JSON 成为理想的数据交换语言。 易于人阅读和编写,同时也易于机器解析和生成(网络传输速度)。
JSON 语法是 JavaScript 对象表示语法的子集。
JSON 数据的书写格式是:名称/值对,名称/值对组合中的名称写在前面(在双引号中),值对写在后面(同样在双引号中),中间用冒号隔开:
var json1 = {"name": "Byron", "age": "24"}
var json2 = [
{"name": "Byron", "age": "24"},
{"name": "Byron2", "age": "25"}
]
IE8以上浏览器都支持了一个对象JSON,JSON对象主要有两个『静态』函数
JSON 格式的字符串转换为 JS 对象:
var str = '{"name": "jirengu", "age": "24"}'
var json=JSON.parse(str); //{name: "jirengu", age: "24"}
JS 对象转换为 JSON 格式的字符串:
var obj={name:"jirengu", age:24, "128":"blahblah"}
var str=JSON.stringify(obj);//"{"128":"blahblah","name":"jirengu","age":24}"
@charset "utf-8";
h1 {
color: red;
font-size: 20px;
/*这是注释*/
}
a:hover{
color: red;
}
也叫行内样式,样式直接写在HTML标签中。但现在按照“内容 样式 行为 分离”的原则,基本不再使用。
<h1 style="color: red; font-size: 20px;"></h1>
在 HTML 的 head 部分,加入一个 style 标签,在其中书写样式,称为内部样式。
<style type="text/css">
h1 {
color: red;
font-size: 20px;
}
</style>
<h1>...</h1>
目前最常用的 CSS 引入方式,即单独一个 css 文件来写样式,HTML 文件在执行的时候,通过外部引用的方式来获取 CSS 。外部引用有 link 和 @import 两种方式。
<head>
<link rel="stylesheet" type="text/css" href="index.css">
</head>
<style>
@import url("hello.css");
@import "world.css";
</style>
在外观和预想不一样的时候,要考虑到这一点。
css/a.css
当前目录下 css
文件夹中的 a.css
文件
./css/a.css
等价于css/a.css
,./
代表当前文件夹
b.css
当前文件夹下的 b.css
../imgs/a.png
上一级文件夹下的 imgs
文件夹中的 a.png
文件
/Users/hunger/project/css/a.css
本地文件的绝对地址
/static/css/a.css
网站路径,此时寻找的是根目录下 static 文件夹下 css 文件夹中 a.css 文件
css/a.css
在网页打开时为相对路径,为和 HTML 页面同级下 css 文件夹下的 a.css 文件
http://cdn.jirengu.com/kejian1/8-1.png
网络路径,表示cdn.jirengu.com上面的图片地址
function random(min, max) {
return Math.floor(Math.random() * (max - min)) + min;
}
function random(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function random(min, max) {
return Math.floor(Math.random() * (max - min)) + min;
}
function getRandStr(length){
var dict = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
var str = ''
for(var i = 0; i < length; i++) {
str += dict[random(0, 62)]
}
return str
}
function random(min, max) {
return Math.floor(Math.random() * (max - min)) + min;
}
function getRandIP() {
var arr = []
for(var i = 0; i < 4; i++) {
arr.push(random(0, 256))
}
return arr.join('.')
}
var ip = getRandIP()
console.log(ip)
function random(min, max) {
return Math.floor(Math.random() * (max - min)) + min
}
function getRandColor() {
var color = '#'
var dict = '0123456789abcdef'
for(var i = 0; i < 6; i++) {
color += dict[random(0, 16)]
}
return color
}
var color = getRandColor()
console.log(color)
push
push 方法用于在数组的末端添加一个或多个元素,并返回添加新元素后的数组长度。注意,该方法会改变原数组。
pop
pop 方法用于删除数组的最后一个元素,并返回该元素。注意,该方法会改变原数组。
join
join 方法以参数作为分隔符,将所有数组成员组成一个字符串返回。如果不提供参数,默认用逗号分隔。
shift
shift 方法用于删除数组的第一个元素,并返回该元素。注意,该方法会改变原数组。
unshift
unshift 方法用于在数组的第一个位置添加元素,并返回添加新元素后的数组长度。注意,该方法会改变原数组。
splice
splice 方法用于删除原数组的一部分成员,并可以在被删除的位置添加入新的数组成员,返回值是被删除的元素。注意,该方法会改变原数组。
splice 的第一个参数是删除的起始位置,第二个参数是被删除的元素个数。如果后面还有更多的参数,则表示这些就是要被插入数组的新元素。
// 格式
arr.splice(index, count_to_remove, addElement1, addElement2, ...);
// 用法
var a = ['a', 'b', 'c', 'd', 'e', 'f'];
a.splice(4, 2) // ["e", "f"]
a // ["a", "b", "c", "d"]
上面代码从原数组4号位置,删除了两个数组成员。
var a = ['a', 'b', 'c', 'd', 'e', 'f'];
a.splice(4, 2, 1, 2) // ["e", "f"]
a // ["a", "b", "c", "d", 1, 2]
上面代码除了删除成员,还插入了两个新成员。
起始位置如果是负数,就表示从倒数位置开始删除。
var a = ['a', 'b', 'c', 'd', 'e', 'f'];
a.splice(-4, 2) // ["c", "d"]
上面代码表示,从倒数第四个位置c开始删除两个成员。
如果只是单纯地插入元素,splice方法的第二个参数可以设为0。
var a = [1, 1, 1];
a.splice(1, 0, 2) // []
a // [1, 2, 1, 1]
如果只提供第一个参数,等同于将原数组在指定位置拆分成两个数组。
var a = [1, 2, 3, 4];
a.splice(2) // [3, 4]
a // [1, 2]
//push
function spliceToPush(arr, elements) {
arr.splice(arr.length, 0, elements)
return arr
}
//pop
function spliceToPop(arr) {
arr.splice(arr.length - 1, 1)
return arr
}
//shift
function spliceToShift(arr) {
arr.splice(0, 1)
return arr
}
//unshift
function spliceToUnshift(arr, elements) {
arr.splice(0, 0, elements)
return arr
}
var arr = [1, 2, 3]
console.log(spliceToPush(arr, 'Deadpool'))//[1, 2, 3, "Deadpool"]
console.log(spliceToPop(arr))//[1, 2, 3]
console.log(spliceToShift(arr))//[2, 3]
console.log(spliceToUnshift(arr, 'Deadpool'))//["Deadpool", 2, 3]
function squareArr(arr){
for(var i = 0; i < arr.length; i++) {
arr.splice(i, 1, (arr[i] * arr[i]))
}
}
var arr = [2, 4, 6]
squareArr(arr)
console.log(arr) // [4, 16, 36]
function filterPositive(arr){
var newArr = []
for(var i = 0; i < arr.length; i++) {
if(typeof arr[i] === 'number' && arr[i] > 0) {
newArr.push(arr[i])
}
}
return newArr
}
var arr = [3, -1, 2, '饥人谷', true]
var newArr = filterPositive(arr)
console.log(newArr) //[3, 2]
console.log(arr) //[3, -1, 2, '饥人谷', true]
function getChIntv(dateStr) {
var targetDate = new Date(dateStr)
var curDate = new Date()
var offset = Math.abs(targetDate - curDate)
var totalSeconds = Math.floor(offset / 1000)
var second = totalSeconds % 60
var totalMinutes = Math.floor(totalSeconds / 60)
var minutes = totalMinutes % 60
var totalHours = Math.floor(totalMinutes / 60)
var hours = totalHours % 24
var totalDays = Math.floor(totalHours / 24)
return totalDays + ' 天 ' + hours + ' 小时 ' + minutes + ' 分 ' + second + ' 秒 '
}
var str = getChIntv("2017-09-01");
console.log(str)
function getChsDate(str) {
var dict = ["零","一","二","三","四","五","六","七","八","九","十","十一","十二","十三","十四","十五","十六","十七","十八","十九","二十","二十一","二十二","二十三","二十四","二十五","二十六","二十七","二十八","二十九","三十","三十一"]
var arr = str.split('-')
var year = arr[0]
var month = arr[1]
var day = arr[2]
var yearStr = ''
for(var i = 0; i < year.length; i++) {
yearStr += dict[year[i]]
}
var monthStr = dict[parseInt(month)]
var dayStr = dict[parseInt(day)]
return yearStr + "年" + monthStr + "月" + dayStr + "日"
}
var str = getChsDate('2015-01-08');
console.log(str); // 二零一五年一月八日
刚刚( t 距当前时间不到1分钟时间间隔)
3分钟前 (t距当前时间大于等于1分钟,小于1小时)
8小时前 (t 距离当前时间大于等于1小时,小于24小时)
3天前 (t 距离当前时间大于等于24小时,小于30天)
2个月前 (t 距离当前时间大于等于30天小于12个月)
8年前 (t 距离当前时间大于等于12个月)
function friendlyDate(time){
var curDate = new Date().getTime()
var offset = Math.abs(curDate - time)
var seconds = Math.floor(offset / 1000)
var minutes = Math.floor(seconds / 60)
var hours = Math.floor(minutes / 60)
var days = Math.floor(hours / 24)
var months = Math.floor(days / 30)//这里有一个问题,每个月的天数不同,有28、29、30、31天,怎样能够精确的计算呢?
var years = Math.floor(months / 12)
if(seconds < 60) {
return "刚刚"
}else if(1 <= minutes && minutes < 60) {
return "3分钟前"
}else if(1 <= hours && hours < 24) {
return "8小时前"
}else if(1 <= days && days < 30) {
return "3天前"
}else if(1 <= months && months < 12) {
return "2个月前"
}else if(1 <= years) {
return "8年前"
}
}
var str = friendlyDate('1484286699422') //2个月前
var str2 = friendlyDate('1483941245793') //2个月前
var button = documen.getElementById('button')
button.onclick = function(){} // on+事件名称
button.onclick = null
button.onclick = function(){
console.log(1)
}
button.onclick = function(){
console.log(2) // 会覆盖
}
addEventListener()
、 removeEventListener()
var button = documen.getElementById('button')
button.addEventListener('click',fn)
button.removeEventListener('click',fn)
button.attachEvent('onclick',fn)
button.addEventListener('click',fn)
参数个数不相同,这个最直观,addEventListener有三个参数,attachEvent只有两个,attachEvent添加的事件处理程序只能发生在冒泡阶段,addEventListener第三个参数可以决定添加的事件处理程序是在捕获阶段还是冒泡阶段处理(我们一般为了浏览器兼容性都设置为冒泡阶段)
第一个参数意义不同,addEventListener第一个参数是事件类型(比如click,load),而attachEvent第一个参数指明的是事件处理函数名称(onclick,onload)
事件处理程序的作用域不相同,addEventListener的作用域是元素本身,this是指的触发元素,而attachEvent事件处理程序会在全局变量内运行,this是window,所以刚才例子才会返回undefined,而不是元素id
为一个事件添加多个事件处理程序时,执行顺序不同,addEventListener添加会按照添加顺序执行,而attachEvent添加多个事件处理程序时顺序无规律(添加的方法少的时候大多是按添加顺序的反顺序执行的,但是添加的多了就无规律了),所以添加多个的时候,不依赖执行顺序的还好,若是依赖于函数执行顺序,最好自己处理,不要指望浏览器。
var button = documen.getElementById('button')
button.onclick = function(e){
console.log('hello')
e.stopPropagation() // 标准
}
button.onclick = function(){
console.log('hello')
window.event.cancelBubble = true // IE
}
button.addEventListener('click',function(){
console.log('world')
},false) // 标准 第三个参数为false或者不写
button.attachEvent('onclick',function(e){
e.cancelBubble = true // IE
})
button.onclick = function(e){
e.preventDefault()
}
// 或者
button.onclick = function(e){
return false
}
// 或者HTML中
<button onclick="return false;"></button>
button.onclick = function(event){
window.event.returnValue = false
}
<ul class="container">
<li>这里是</li>
<li>饥人谷</li>
<li>前端6班</li>
</ul>
<script>
var container = document.querySelector('.container');
container.addEventListener('click', function(e) {
console.log(e.target.innerText);
});
</script>
<ul class="ct">
<li>这里是</li>
<li>饥人谷</li>
<li>任务班</li>
</ul>
<input class="ipt-add-content" placeholder="添加内容"/>
<button id="btn-add-start">开头添加</button>
<button id="btn-add-end">结尾添加</button>
<script>
function $(str) {
return document.querySelector(str)
}
var ct = $('.ct')
var addStart = $('#btn-add-start')
var addEnd = $('#btn-add-end')
var input = $('.ipt-add-content')
ct.addEventListener('click',function(e){
console.log(e.target.innerText)
})
addStart.addEventListener('click',function(){
var li = document.createElement('li')
if(/\S/.test(input.value)){
li.innerText = input.value
ct.insertBefore(li,ct.firstChild)
}else{
alert('请输入内容')
}
})
addEnd.addEventListener('click',function(){
var li = document.createElement('li')
if(/\S/.test(input.value)){
li.innerText = input.value
ct.appendChild(li)
}else{
alert('请输入内容')
}
})
</script>
<ul class="ct">
<li data-img="1.png">鼠标放置查看图片1</li>
<li data-img="2.png">鼠标放置查看图片2</li>
<li data-img="3.png">鼠标放置查看图片3</li>
</ul>
<div class="img-preview"></div>
<script>
var ct = document.querySelector('.ct')
var preview = document.querySelector('.img-preview')
ct.addEventListener('mouseover',function(e){
var dataImg = e.target.getAttribute('data-img')
preview.innerHTML = '<img src="' + dataImg + '">'
})
</script>
Markdown是一个简单的标记语言,这些标记和 HTML 的一些标签对应
通过一些转换库可以把 Markdown 转换成 HTML 或者把 HTML 转换成 Markdown
用来在网页上展示文章,省去排版布局的烦恼
# 一级标题 h1
## 二级标题 h2
### 三级标题 h3
#### 四级标题 h4
##### 五级标题 h5
1. 有序列表
2. 有序列表
3. 有序列表
- 无序列表
- 无序列表
- 无序列表
[显示文本](链接地址)
![](图片链接地址)
> 引用测试
> > 引用内引用测试
引用测试
引用内引用测试
```
var a = 1
var b = 2
```
var a = 1
var b = 2
**粗体测试**
*斜体测试*
~~删除线测试~~
粗体测试
斜体测试
删除线测试
Markdown使用|
和-
来绘制表格,:
可控制左对齐、居中及右对齐。
| 表头测试 | 表头测试 | 表头测试 |
| :--- | :---: | ---: |
| 内容 | 内容 | 内容 |
| 内容 | 内容 | 内容 |
表头测试 | 表头测试 | 表头测试 |
---|---|---|
内容 | 内容 | 内容 |
内容 | 内容 | 内容 |
Markdown利用\
字符来转义一些在语法中有特殊意义的符号。
$(document).ready()
是什么意思?当 DOM 准备就绪时,指定一个函数来执行。
虽然 JavaScript 提供了 load 事件,当页面呈现时用来执行这个事件,直到所有的东西,如图像已被完全接收前,此事件不会被触发。
在大多数情况下,只要 DOM 结构已完全加载时,脚本就可以运行。传递处理函数给.ready()
方法,能保证 DOM 准备好后就执行这个函数,因此,这里是进行所有其它事件绑定及运行其它 jQuery 代码的最佳地方。
如果执行的代码需要在元素被加载之后才能使用时,(例如,取得图片的大小需要在图片被加载完后才能知道),就需要将这样的代码放到 load 事件中。
下面两种语法全部是等价的:
$(document).ready(handler)
$(handler)
经常这么使用
$(function(){
console.log('ready');
});
$node.html()
和 $node.text()
的区别?$node.html()
返回所有选择元素内的 HTML 内容,包含 html
标签和文本内容。
如果选择器匹配多个元素,那么只有第一个匹配元素的 HTML 内容会被获取。
$node.text()
返回所选择元素内的文本内容,包括他们的后代,不包含 html
标签。
eg:
<div class="wrapper">
<p>1</p>
<p>2</p>
<p>3</p>
</div>
console.log($('.wrapper').html()) // <p>1</p> <p>2</p> <p>3</p>
console.log($('p').html()) // 1
console.log($('.wrapper').text()) // 1 2 3
$.extend
的作用和用法?$.extend()
可以将多个对象合并到一起,可以传入多个参数。当我们提供两个或多个对象给$.extend()
,对象的所有属性都添加到目标对象( target 参数)。
如果只有一个参数提供给$.extend()
,这意味着目标参数被省略。在这种情况下, jQuery 对象本身被默认为目标对象。这样,我们可以在 jQuery 的命名空间下添加新的功能。这对于插件开发者希望向 jQuery 中添加新函数时是很有用的。
eg:
var obj1 = {a:1}
var obj2 = {b:2, c:3}
var obj3 = {b:3, d:5}
var obj4 = {}
$extend(obj1, obj2) // {a:1, b:2, c:3}
$extend(obj1, obj2, obj3) //{a:1, b:3, c:3, d:5}
$extend(obj4, obj1, obj2, obj3) //{a:1, b:3, c:3, d:5}
var obj5 = $extend({}, obj1, obj2, obj3) // {a:1, b:3, c:3, d:5}
分步骤的对 jQuery 对象使用方法后继续调用方法, 而不用再次选择 jQuery 对象。
原理:通过对象上的方法最后 return this 把对象再返回回来,对象就可以继续调用方法。
作用:使代码排版更清晰,便于查看执行流程。
eg:
$(#test).css('color', 'blue').show(400).fadeOut(200);
data()
函数用于在当前 jQuery 对象所匹配的所有元素上存取数据。data()
函数存取的数据都是临时数据,一旦页面刷新,之前存放的数据都将不复存在。data()
函数存放的数据, 请使用removeData()
函数。.data(key, value)
.data(key)
eg:
$("body").data("foo", 52);
$("body").data("bar", { myType: "test", count: 40 });
$("body").data({ baz: [ 1, 2, 3 ] });
$("body").data("foo"); // 52
$("body").data(); // { foo: 52, bar: { myType: "test", count: 40 }, baz: [ 1, 2, 3 ] }
$node
添加 class active
,给元素 $node
删除 class active
$node.addClass('active');
$node.removeClass('active');
$node
, 隐藏元素$node
$node.show();
$node.hide();
$node
的 属性: id
、src
、title
, 修改以上属性//获取属性
$node.attr('id')
$node.attr('src')
$node.attr('title')
//修改属性
$node.attr('id','newId')
$node.attr('src','newSrc')
$node.attr('title','newTitle')
$node
添加自定义属性 data-src
$node.attr('data-src', 'src')
$ct
内部最开头添加元素 $node
$ct.prepend($node)
//or
$node.prependTo($ct)
$ct
内部最末尾添加元素 $node
$ct.append($node)
//or
$node.appendTo($ct)
$node
$node.remove()
$ct
里内容清空$ct.empty()
$ct
里设置 html <div class="btn"></div>
$ct.html('<div class="btn"></div>')
$node
的宽度、高度(分别不包括内边距、包括内边距、包括边框、包括外边距)//不包括内边距
$node.width();//获取宽度
$node.height();//获取高度
$node.width('100');//设置宽度,如果没有规定长度单位,默认 px
$node.height('200');//设置高度
$node.css({width:'100px',height:'300px'})//设置宽度、高度
//包括内边距
$node.innerWidth();//获取包括内边距的宽度
$node.innerHeight();//获取包括内边距的高度
$node.innerWidth('100');//设置包括内边距的宽度
$node.innerHeight('300');//设置包括内边距的高度
//包括边框
$node.outerWidth();//获取包括边框宽度
$node.outerHeight();//获取包括边框高度
$node.outerWidth('50');//设置包括边框宽度
$node.outerHeight('100');//设置包括边框高度
//包括外边距
$node.outerWidth(true);//获取包括外边距宽度
$node.outerHeight(true);//获取包括外边距高度
$node.outerWidth(60,true)//设置包括外边距宽度
$node.outerHeight(80,true)//设置包括外边距高度
$(window).scrollTop()
$node
到根节点水平、垂直偏移距离$node.offset().left
$node.offset().top
$node
的样式,字体颜色设置红色,字体大小设置 14 px$node.css({
'color': 'red',
'font-size': '14px';
})
$node.each(function(){
let str = $(this).text();
$(this).text(str + str);
})
$ct
里查找 class 为 .item
的子元素$ct.find('.item')
$ct
里面的所有孩子$ct.children()
$node
,向上找到 class 为.ct
的父亲,在从该父亲找到.panel
的孩子$node.parents('.ct').find('.panel')
$node.length
$node.index()
$btn
时,让 $btn
的背景色变为红色再变为蓝色$div
上,把 $div
背景色改为红色,移出鼠标背景色变为白色字符 | 含义 |
---|---|
\d | 数字字符 |
\w | 单词字符,包括字母(小写、大写)、数字和下划线 |
\s | 空白字符 |
[a-zA-Z0-9] | 字母(小写、大写)、数字 |
\b | 单词边界 |
. | 除了回车符和换行符之外的所有字符 |
* | 出现零次或多次(任意次) |
+ | 出现一次或多次(至少出现一次) |
? | 出现零次或一次(最多出现一次) |
x{3} | 出现3次 |
^ | 以xxx开头 |
$ | 以xxx结尾 |
function trim(str) {
return str.replace(/^\s+|\s+$/g, '')
}
function isEmail(str){
var reg = /^\w+@\w+[.]\w+$/;
return reg.test(str);
}
function isPhoneNumber(str) {
return /^1\d{10}$/.test(str)
}
function isValidUsername(str) {
var reg = /^\w{6,20}$/
return reg.test(str)
}
function isValidPassword(str) {
if(!/^\w{6,20}$/.test(str)) return false
if(/^[a-z]{6,20}$/.test(str)) return false
if(/^[A-Z]{6,20}$/.test(str)) return false
if(/^\d{6,20}$/.test(str)) return false
if(/^_{6,20}$/.test(str)) return false
return true
}
var subj = "color: #121212; background-color: #AA00ef; width: 12px; bad-colors: f#fddee "
var colorReg = /#([0-9a-fA-F]{6}|[0-9a-fA-F]{3})(?=;)/g
console.log( subj.match(colorReg) ) // ['#121212', '#AA00ef']
var str = 'hello "hunger" , hello "world"';
var pat = /".*"/g;
str.match(pat);//[""hunger" , hello "world""]
//字符 . 的含义是除了回车符和换行符之外的所有字符。
//量词在默认下是尽可能多的匹配的,也就是贪婪模式。
//首先从 " 开始匹配 ,所以 " 之前的 'hello 并没有匹配到。
//然后匹配除了回车符和换行符之外的所有字符
//但是仍有剩余的正则需要匹配,即 "
//因此正则开始倒回来回溯,换句话说,就是一个字符一个字符缩减匹配。
//回溯遇到的第一个字符就是 "
//所以最终匹配到的是 '"hunger" , hello "world"'
//改写
var str = 'hello "hunger" , hello "world"';
var pat = /".*?"/g;
//首先 " 被匹配上
//之后是重点:正则引擎尝试用最小可能的重复次数来进行匹配。
//因此在.匹配了 h 后,它立即尝试 " 的匹配
//但可惜下个字符是 u ,并没有匹配上
//所以继续向后面匹配,一直到 "hunger" 才匹配上了。
//又因为是global全局匹配的,所以匹配上了 "world"
str.match(pat);//[""hunger"", ""world""]
JavaScript 语言的每一个值,都属于某一种数据类型。JavaScript 的数据类型:
原始类型(primitive type)
通常,我们将数值、字符串、布尔值称为原始类型(primitive type)的值,即它们是最基本的数据类型,不能再细分了。
复杂类型(合成类型 complex type)
将对象称为合成类型(complex type)的值,因为一个对象往往是多个原始类型的值的合成,可以看作是一个存放各种值的容器。
对象的细分
typeof
和 instanceof
的作用和区别?首先,JavaScript 有三种方法,可以确定一个值到底是什么类型。
typeof 运算符
instanceof 运算符
Object.prototype.toString 方法
typeof运算符可以返回一个值的数据类型,可能有以下结果。
(1)原始类型
数值、字符串、布尔值分别返回number
、string
、boolean
。
typeof 123 // "number"
typeof '123' // "string"
typeof false // "boolean"
(2)函数
函数返回function
。
function f() {}
typeof f
// "function"
(3)undefined
undefined
返回undefined
。
typeof undefined
// "undefined"
利用这一点,typeof
可以用来检查一个没有声明的变量,而不报错。
v
// ReferenceError: v is not defined
typeof v
// "undefined"
上面代码中,变量v
没有用var
命令声明,直接使用就会报错。但是,放在typeof
后面,就不报错了,而是返回undefined
。
实际编程中,这个特点通常用在判断语句。
// 错误的写法
if (v) {
// ...
}
// ReferenceError: v is not defined
// 正确的写法
if (typeof v === "undefined") {
// ...
}
(4)其他
除此以外,其他情况都返回object
。
typeof window // "object"
typeof {} // "object"
typeof [] // "object"
typeof null // "object"
那么这里就有个问题了,既然typeof
对数组(array
)和对象(object
)的显示结果都是object
,那么怎么区分它们呢?instanceof
运算符可以做到。
区分数组和对象
var o = {};
var a = [];
o instanceof Array // false
a instanceof Array // true
typeof
来判断eg:
typeof 123 // "number"
typeof '123' // "string"
typeof false // "boolean"
有三个函数可以把非数值转换为数值
Number()
parseInt()
parseFloat()
Number
函数(强制转换),可以将任意类型的值转化成数值。Number
函数将字符串转为数值,要比parseInt
函数严格很多。基本上,只要有一个字符无法转成数值,整个字符串就会被转为NaN
。parseInt
方法用于将字符串转为整数。parseFloat
方法用于将一个字符串转为浮点数。==
近似相等,会将两边的值,转换成同一数据类型,再比较。===
是严格意义上的相等,不会转换数据类型,数据类型不一样,会直接返回false
。(实际工作中尽量使用===
)break
与 continue
有什么区别break
用于强制退出循环体,执行循环后面的语句continue
用于退出本次循环,继续执行下次循环void 0
和 undefined
在使用场景上有什么区别undefined
可以在局部作用域中被覆写,而void
运算返回都是undefined
。console.log(1+1); // 1 的类型为数值,所以做加法运算,结果为 2 。
console.log("2"+"4"); // "2""4" 的类型为字符串,所以将两个字符拼接起来,结果为 "24" 。
console.log(2+"4"); // 2 的类型为数值,"4" 的类型为字符串。所以会先将 2 的类型强制转换为字符串类型 "2",再与 4 拼接,结果为 "24" 。
console.log(+"4"); // 参数中只有字符串"4",会将字符串强制转化为数字 4,结果为 4 。
var a = 1;
a+++a; // (a++)+a 首先是 (a++) 的运算:这里 (a++) 的值为 1 ,a 的值为 2 。那么 (a++)+a 的运算为 1+2 ,所以这里的结果为 3 。
typeof a+2; // (typeof a)+2 首先是 (typeof a) 的运算:a 的值为 2,数据类型为 number,那么 (typeof a) 的结果为 number。 (typeof a)+2 的结果为 "number2" 。
var a = 1;
var b = 3;
console.log( a+++b ); //首先是 a+++b 的运算: (a++)+b 。 (a++) 的运算:a 的值为 2,但 (a++) 的值为 1。 所以 (a++)+b 的运算为 1+3 ,结果为 4
var arr = [3,4,5];
for (i=0;i<arr.length;i+=1) {
console.log(arr[i]*arr[i]); //console.log(Math.pow(arr[i],2));
}
var obj = {
name: 'hunger',
sex: 'male',
age: 28
}
for (i in obj) {
console.log(i,":",obj[i])
}
var a = 1, b = 2, c = 3; //赋值
var val = typeof a + b || c >0 //"="的优先级最低,那么整体来看就是赋值。根据优先级,typeof a + b || c > 0 的运算:先进行(typeof a) + b的运算,结果为"number2";由于逻辑或的运算规则:如果第一个运算子的布尔值为 true ,则返回第一个运算子的值,且不再对第二个运算子求值;如果第一个运算子的布尔值为 false ,则返回第二个运算子的值。所以 typeof a + b || c >0 输出的结果为"number2" ;最后赋值给 val ;所以结果为"number2"。
console.log(val) // "number2"
var d = 5; //赋值
var data = d ==5 && console.log('bb') // "="优先级最低,那么整体来看就是赋值。d ==5 && console.log('bb') 的运算:由于逻辑与的运算规则:如果第一个运算子的布尔值为 true,则返回第二个运算子的值(注意是值,不是布尔值);如果第一个运算子的布尔值为 false,则直接返回第一个运算子的值,且不再对第二个运算子求值。d==5 的值为 true;console.log('bb')的值为 undefined,所以 d ==5 && console.log('bb') 的值为 undefined;最后赋值给 data;所以结果为 undefined 。
console.log(data) // undefined
var data2 = d = 0 || console.log('haha') //整体为两次赋值。0 || console.log('haha')的运算:由于逻辑或,第一个运算子是 false,则返回第二个运算子的值,也就是 console.log('haha')的值 undefined,所以 undefined 赋值给 d,d 再 赋值给 data2,所以结果为 undefined 。
console.log(data2) // undefined
var x = !!"Hello" + (!"world", !!"from here!!"); //整体来看为一次赋值。!!"Hello" + (!"world", !!"from here!!") 的运算: !!"Hello" 的值为 true;!"world" 的值为 flase, !!"from here!!" 的值为 true,而逗号运算符用于对两个表达式求值,并返回后一个表达式的值,所以 (!"world", !!"from here!!") 的值为 true;然后 true+true 的值为2,最后赋值给x。
console.log(x) // 2
取反运算符形式上是一个感叹号,用于将布尔值变为相反值,即 true 变成 false,false 变成 true。
对于非布尔值的数据,取反运算符会自动将其转为布尔值。规则是,以下六个值取反后为 true,其他值取反后都为 false 。
undefined
null
false
0(包括+0和-0)
NaN
空字符串('')
渐进增强和优雅降级
渐进增强(progressive enhancement): 针对低版本浏览器进行构建页面,保证最基本的功能,然后再针对高级浏览器进行效果、交互等改进和追加功能达到更好的用户体验
优雅降级 (graceful degradation): 一开始就构建完整的功能,然后再针对低版本浏览器进行兼容。
#几种浏览器兼容的写法
<!--[if IE 6]-->
<p>You are using Internet Explorer 6.</p>
<![endif]-->
div{
color:blue;
*color:red; /*如果在IE6或者7中,字体颜色为红色,否则为蓝色*/
}
div\9{
color:yellow
}
<!DOCTYPE html>
<!--[if IEMobile 7 ]> <html dir="ltr" lang="en-US"class="no-js iem7"> <![endif]-->
<!--[if lt IE 7 ]> <html dir="ltr" lang="en-US" class="no-js ie6 oldie"> <![endif]-->
<!--[if IE 7 ]> <html dir="ltr" lang="en-US" class="no-js ie7 oldie"> <![endif]-->
<!--[if IE 8 ]> <html dir="ltr" lang="en-US" class="no-js ie8 oldie"> <![endif]-->
<!--[if (gte IE 9)|(gt IEMobile 7)|!(IEMobile)|!(IE)]><!--><html dir="ltr" lang="en-US" class="no-js"><!--<![endif]-->
<html class=" js no-flexbox canvas canvastext no-webgl no-touch geolocation
postmessage no-websqldatabase no-indexeddb hashchange no-history
draganddrop no-websockets rgba hsla multiplebgs backgroundsize
no-borderimage borderradius boxshadow no-textshadow opacity
no-cssanimations no-csscolumns no-cssgradients no-cssreflections
csstransforms no-csstransforms3d no-csstransitions fontface
generatedcontent video audio localstorage sessionstorage
no-webworkers no-applicationcache svg inlinesvg smil svgclippaths">
transition: transform 1s;
-moz-transition: transform 1s; /* Firefox 4 */
-webkit-transition: transform 1s; /* Safari 和 Chrome */
-o-transition: transform 1s; /* Opera */
inline-block: >=ie8
min-width/min-height: >=ie8
:before,:after: >=ie8
div:hover: >=ie7
inline-block: >=ie8
background-size: >=ie9
圆角: >= ie9
阴影: >= ie9
动画/渐变: >= ie10
<!--[if IE 6]>
<p>You are using Internet Explorer 6.</p>
<![endif]-->
<!--[if !IE]><!-->
<script>alert(1);</script>
<!--<![endif]-->
<!--[if IE 8]>
<link href="ie8only.css" rel="stylesheet">
<![endif]-->
项目 | 范例 | 说明 |
---|---|---|
! | [if !IE] | 非IE |
lt | [if lt IE 5.5] | 小于IE 5.5 |
lte | [if lte IE 6] | 小于等于IE6 |
gt | [if gt IE 5] | 大于 IE5 |
gte | [if gte IE 7] | 大于等于IE7 |
针对IE浏览器编写不同的CSS,使得在IE浏览器中也能得到我们想要的页面效果
能力检测的目标不是识别特定的浏览器,而是识别浏览器的能力。使用这种方式无需顾及浏览器如何如何,只需确定浏览器是否支持特定的能力,就可以给出相关的方案。
用于解决IE9以下版本浏览器对HTML5新增标签不识别,并导致CSS不起作用的问题,使用Javascript来使不支持HTML5的浏览器支持HTML标签。
让不支持 css3 Media Query 的浏览器包括 IE6-IE8 等其他浏览器支持查询。
早期的 CSS Reset 的作用就是清除所有浏览器默认样式,这样更易于保持各浏览器渲染的一致性。
这样暴力清零会带来一些问题,eg:
是一个可定制的 CSS 文件,使浏览器呈现的所有元素,更一致和符合现代标准;是在现代浏览器环境下对于CSS reset的替代。
该项目依赖于研究浏览器默认元素风格之间的差异,精确定位需要重置的样式。相比于传统的CSS Reset,Normalize.css是一种现代的、为HTML5准备的优质替代方案。Normalize.css现在已经被用于Twitter Bootstrap、HTML5 Boilerplate、GOV.UK、Rdio、CSS Tricks 以及许许多多其他框架、工具和网站上。
作用:
一个 JavaScript 库,用于检测用户浏览器的 HTML5 与 CSS3 特性。Modernizr 会在页面加载后立即检测特性;然后创建一个包含检测结果的 JavaScript 对象,同时在 html 元素加入方便你调整 CSS 的 class 名。
PostCSS 是一个使用 JS 插件来转换 CSS 的工具。这些插件可以支持使用变量,混入(mixin),转换未来的 CSS 语法,内联图片等操作。
inline
元素设置浮动,改变 inline
的display
使得它像个block-level
block-level
元素的背景,不会遮盖inline
元素。内边界:指盒模型中的content边界。外边界:指盒模型中的margin边界。
inline-level
)会无视浮动元素的存在,从而占据浮动元素的"原来的位置"。inline-level
)级的元素会环绕浮动元素,表现的像是察觉到浮动元素一样。清除浮动指元素的侧边不允许出现浮动元素,从而使得浮动元素的不占据普通文档流空间的使得父元素的高度塌陷问题得到解决,主要通过clear
属性实现。
clear
:指定一个元素是否可以在它之前的浮动元素旁边,或者必须向下移动(清除浮动) 在它的下面。clear
属性适用于浮动和非浮动元素。
当应用于非浮动块时,它将非浮动块的边框边界移动到所有相关浮动元素外边界的下方。这个行为作用时会导致margin collapsing
不起作用。
当应用于浮动元素时,它将元素的外边界移动到所有相关的浮动元素外边界的下方。这会影响后面浮动元素的布局,后面的浮动元素的位置无法高于它之前的元素。
height
值:after
伪元素,然后在伪元素上设置clear
属性来实现:after
清除 (推荐使用).clearfix{ *zoom:1; } /*兼容IE6、7 (现在基本上不用写这行了,基本淘汰了)*/
.clearfix:after {
content:"";
display: block;
clear: both;
}
clear
属性float
影响整体布局,overflow:hidden
影响内容的展示等等inherit
position
属性的值static
默认值,没有定位,元素出现在正常的流中(忽略 top
, bottom
, left
, right
或者 z-index
声明)relative
left
, top
,right
,bottom
absolute
offset parent
)进行定位left
, top
,right
,bottom
fixed
left
, top
,right
,bottom
sticky
和
position:fixed`的合体,目标区域在屏幕中可见时,它的行为就像`position:relative;` 而当页面滚动超出目标区域时,它的表现就像`position:fixed`,它会固定在目标位置。z-index
有什么作用? 如何使用?z-index
规定了元素在 Z 轴(距离用户远近)上的顺序,值越大则越靠近用户,表现就是元素在最上面。
z-index
仅在设置了position
非static
属性的元素生效,且z-index
的值只能在兄弟元素之间比较。
Z-index
默认值为auto
,则不建立层叠上下文。设置为 0
则会建立层叠上下文。
position:relative
和负margin
都可以使元素位置发生偏移?二者有什么区别position:relative
相对自己原本的位置偏移,不影响其它普通流中元素的位置。margin
:除了让元素自身发生偏移还影响其它普通流中的元素。float
不是 none
)position
为 absolute
或 fixed
)inline-block
(元素具有 display: inline-block
)display: table-cell
,HTML 表格单元格默认属性)display: table-caption
, HTML 表格标题默认属性)overflow
,且值不是 visible
display: flow-root
float:left|right
overflow:hidden|auto|scroll
display:inline-block|table-caption|table-cell
position:absolute|fiexd
float
元素的效果margin
都是正值的时候,取两者的最大值;margin
都是负值的时候,取的是其中绝对值较大的,然后,从0
位置,负向位移;margin
中绝对值中最大的,然后,和正 margin
值中最大的 margin
相加。margin
要一起参与运算,不能分步进行。padding
、border
或 clear
分隔开。margin
在垂直方向上不毗邻。top
margin
与第一个子box的top
margin
bottom
margin
与最后一个子box的bottom
margin
,但须在该box的height
为auto
的情况下bottom
margin
与紧接着的下一个box的top
margin
top
margin
与其自身的bottom
margin
,但须满足没创建BFC、零min-height
、零或者“auto
”的height
、没有普通流的子元素。说起跨域,我们就要先了解一下同源策略。同源策略是针对浏览器的,不是针对 JS。
同源策略限制从一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的关键的安全机制。
换句话说,浏览器出于安全方面的考虑,只允许与本域下的接口交互。不同源的客户端脚本在没有明确授权的情况下,不能读写对方的资源。
同协议:如都是http
或者https
同域名:如都是http://github.com/a
和http://github.com/b
同端口:如都是80端口
以http://harleywang93.com/
为例
该 url 的协议为 http,域名是 harleywang93.com,端口为443,默认端口可以省略。
http://harleywang93.com/
和http://harleywang93.com/about
(同源,协议、域名、端口都相同)
http://harleywang93.com/
和https://harleywang93.com
(不同源,协议不同)
http://harleywang93.com/
和http://other.harleywang93.com
(不同源,域名不同)
http://harleywang93.com/
和http://harleywang93.com:442
(不同源,端口不同)
需要注意的是: 对于当前页面来说页面存放的 JS 文件的域不重要,重要的是加载该 JS 页面所在什么域
那么,我就是想访问其他域(非同源)的资源 — 即跨域,该怎么做呢?
HTML 中 Script 通过 src 属性可以引入其他域下的 JS,比如引入线上的 jQuery库。也可以引入非 JS 的文件,利用这个特性,可实现跨域访问接口。该方法需要后端支持。
_fun
callback=_fun
fun(data)
字符串。fun(data)
会放到 Script 标签做为 JS 执行。此时会调用 fun 函数,将 data 做为参数。//b.html
<ul>
<li>十九大10月18日在北京召开 喜迎十九大</li>
<li>***欢迎塔吉克斯坦总统 世界之问的**答案</li>
<li>丁来杭中将履新空军司令员 接替马晓天上将</li>
</ul>
<button>换一组</button>
<script>
var $ = function (str) {
return document.querySelector(str);
};
$('button').addEventListener('click', function () {
var script = document.createElement('script');
script.src = 'http://a.jrg.com:8080/getNews?callback=fn';
document.head.appendChild(script);
document.head.removeChild(script);
});
var fn = function (news) {
for(var i=0; i<3; i++)
$('ul>li').remove();
for(var i=0; i<news.length; i++){
var li = document.createElement('li');
li.innerText = news[i];
$('ul').appendChild(li);
}
};
</script>
//router.js
app.get('/getNews', function (req, res) {
var news = [
'**公民在美购敏感材料获刑3年 疑遭钓鱼执法',
'十九大10月18日在北京召开 喜迎十九大',
'***欢迎塔吉克斯坦总统 世界之问的**答案',
'丁来杭中将履新空军司令员 接替马晓天上将',
'上海警察"一招擒拿"抱娃妇女摔落孩子 已被停职',
'技校学生拳击玻璃致身亡 家属抬棺材堵校门',
'女博士被人推下几十级台阶 男子自首称"想听尖叫"'
];
var data = [];
for(var i=0; i<3; i++){
var index = parseInt(Math.random()*news.length);
data.push(news[index]);
news.splice(index, 1);
}
var cb = req.query.callback;
if(cb)
res.send(cb + '(' + JSON.stringify(data) + ')');
else
res.send(data);
});
CORS 全称是跨域资源共享(Cross-Origin Resource Sharing),是一种 ajax 跨域请求资源的方式,支持现代浏览器,IE支持10以上。 实现方式很简单,当你使用 XMLHttpRequest 发送请求时,浏览器发现该请求不符合同源策略,会给该请求加一个请求头:Origin,后台进行一系列处理,如果确定接受请求则在返回结果中加入一个响应头:Access-Control-Allow-Origin
; 浏览器判断该相应头中是否包含 Origin 的值,如果有则浏览器会处理响应,我们就可以拿到响应数据,如果不包含浏览器直接驳回,这时我们无法拿到响应数据。所以 CORS 的表象是让你觉得它与同源的 ajax 请求没啥区别,代码完全一样。
简单请求
比如发送了一个 origin 的头部
Origin : http://www.nczonline.net
如果服务器认为这个请求可以接受,就在Access-Control-Allow-Origin
头部回发相同的源信息
Access-Control-Allow-Origin
: http://www.nczonline.net
复杂请求
复杂请求是那种对服务器有特殊要求的请求,比如请求方法是 PUT 或 DELETE ,或者Content-Type 字段的类型是 application/json 。
复杂请求的 CORS 请求,会在正式通信之前,增加一次 HTTP 查询请求,称为“预检”请求(preflight)。
浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些 HTTP 动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的 XMLHttpRequest 请求,否则就报错。
//a.html
<ul>
<li>十九大10月18日在北京召开 喜迎十九大</li>
<li>***欢迎塔吉克斯坦总统 世界之问的**答案</li>
<li>丁来杭中将履新空军司令员 接替马晓天上将</li>
</ul>
<button>换一组</button>
<script>
var $ = function (str) {
return document.querySelector(str);
};
$('button').addEventListener('click', function () {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if(xhr.readyState === 4 && xhr.status === 200)
fn(JSON.parse(xhr.responseText));
};
xhr.open('get', 'http://b.jrg.com:8080/getNews', true);
xhr.send();
});
var fn = function (news) {
for(var i=0; i<3; i++)
$('ul>li').remove();
for(var i=0; i<news.length; i++){
var li = document.createElement('li');
li.innerText = news[i];
$('ul').appendChild(li);
}
};
</script>
//router.js
app.get('/getNews', function (req, res) {
var news = [
'**公民在美购敏感材料获刑3年 疑遭钓鱼执法',
'十九大10月18日在北京召开 喜迎十九大',
'***欢迎塔吉克斯坦总统 世界之问的**答案',
'丁来杭中将履新空军司令员 接替马晓天上将',
'上海警察"一招擒拿"抱娃妇女摔落孩子 已被停职',
'技校学生拳击玻璃致身亡 家属抬棺材堵校门',
'女博士被人推下几十级台阶 男子自首称"想听尖叫"'
];
var data = [];
for(var i=0; i<3; i++){
var index = parseInt(Math.random()*news.length);
data.push(news[index]);
news.splice(index, 1);
}
res.header('Access-Control-Allow-Origin', 'http://a.jrg.com:8080');
res.send(data);
});
当两个页面不同域,但是它们的父域之上都相同(端口),那么可以使用降域的方法来实现跨域。
对于主域相同而子域不同的情况下,可以通过设置 document.domain
的办法来解决,
具体做法是可以在 url 为 a.github.com:8080
下的 a.html
和b.github.com:8080
下的 b.html
两个文件分别加上 document.domain = “github.com”
;然后通过 a.html
文件创建一个 iframe
,去控制 iframe
的 window
,从而进行交互,当然这种方法只能解决主域相同、而二级域名不同的情况。
//a.html
<input type="text">
<iframe src="http://b.jrg.com:8080/b.html" frameborder="0"></iframe>
<script>
var $ = function (str) {
return document.querySelector(str);
};
$('input').addEventListener('input', function () {
window.frames[0].$('input').value = this.value;
});
document.domain = 'jrg.com';
</script>
//b.html
<input type="text">
<script>
var $ = function (str) {
return document.querySelector(str);
};
$('input').addEventListener('input',function () {
window.parent.$('input').value = this.value;
});
document.domain = 'jrg.com';
</script>
window.postMessage 是一个安全的跨源通信的方法。一般情况下,当且仅当执行脚本的页面使用相同的协议(通常都是 http )、相同的端口( http 默认使用80端口)和相同的 host(两个页面的
document.domain
的值相同)时,才允许不同页面上的脚本互相访问。 window.postMessage 提供了一个可控的机制来安全地绕过这一限制,当其在正确使用的情况下。
window.postMessage 解决的不是浏览器与服务器之间的交互,解决的是浏览器不同的窗口之间的通信问题,可以做的就是同步两个网页,当然这两个网页应该是属于同一个基础域名。
//a.html
<input type="text">
<iframe src="http://b.jrg.com:8080/b.html" frameborder="0"></iframe>
<script>
var $ = function (str) {
return document.querySelector(str);
};
$('input').addEventListener('input', function () {
window.frames[0].postMessage(this.value, 'http://b.jrg.com:8080');
});
</script>
//b.html
<input type="text">
<script>
var $ = function (str) {
return document.querySelector(str);
};
window.addEventListener('message',function (e) {
$('input').value = e.data;
});
</script>
div h1 h2 h3 h4 h5 h6 p hr
form ul dl ol pre table
li dd dt tr td th
em strong span a br img
button input label select textarea
code script
行内元素和 inline-block
元素水平方向上默认情况下是按基线对齐。
行内元素和 inline-block
元素默认是不占据一行,块级元素默认占据一行。
行内元素的高度是由 line-height
来决定,宽度由具体的内容来决定,设置 height
和 width
无效。
行内元素设置上下 margin
, padding
, border
不占据空间。
行内元素的上下 padding
, border
存在颜色,则颜色会显示。
行内元素可以"感受"到浮动元素的存在。
padding
padding
代表内边距,有四个方向的值,可以合写,值可以是数值也可以是百分比(相对于父容器、不是自身)
padding-top
padding-right
padding-bottom
padding-left
padding: 20px; /* padding: 20px 20px 20px 20px; */
padding: 10px 20px; /* padding: 10px 20px 10px 20px; */
padding: 10px 20px 30px; /* padding: 10px 20px 30px 20px; */
margin
margin
代表外边距,有四个方向的值,可以合写,值可以是数值也可以是百分比(相对于父容器、不是自身)。还可以是负值
margin-top
margin-right
margin-bottom
margin-left
margin: 20px; /* margin: 20px 20px 20px 20px; */
margin: 10px 20px; /* margin: 10px 20px 10px 20px; */
margin: 10px 20px 30px; /* margin: 10px 20px 30px 20px; */
margin: 0 auto
对于块级元素,设置 margin: 0 auto
可达到居中目的
.box {
/* margin: 0 auto; 实际上是下面两个起作用 */
margin-left: auto;
margin-right: auto;
}
*
margin
padding
*{
margin: 0;
padding: 0;
}
display、margin、border、padding、background、height、min-height、max-height、width、min-width、max-width、overflow、position、left、right、top、bottom、z-index、float、clear、table-layout、vertical-align、page-break-after、page-bread-before和unicode-bidi
visibility
和cursor
letter-spacing、word-spacing、white-space、line-height、color、font、font-family、font-size、font-style、font-variant、font-weight、text-decoration、text-transform、direction
text-indent
和text-align
list-style、list-style-type、list-style-position、list-style-image
border-collapse
margin:0 atuto;
块级元素text-align:center;
行内元素 (text-align:center;
仅作用在块级元素上,所以 text-align:center;
这个属性应该设置在行内元素的block
级父元素上).tri{
width: 0px;
height: 0px;
border-top: 20px solid transparent;
border-right: 20px solid transparent;
border-bottom:20px solid transparent;
border-left: 20px solid red;
}
or
width: 0;
height: 0;
border: 50px solid transparent;
border-bottom: 100px solid #000000;
E{
white-space: nowrap;/*不折行*/
overflow: hidden;/*超出部分隐藏*/
text-overflow: ellipsis;/*显示省略符号(ellipsis)代表隐藏部分的文本*/
}
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
三者缺一不可px
、 em
、 rem
有什么区别?px
在缩放页面时无法调整那些使用它作为单位的字体、按钮等的大小。em
的值并不是固定的,会继承父级元素的字体大小,代表倍数。rem
的值并不是固定的,始终是基于根元素 (HTML) 的,也代表倍数。 font: 12px/1.5 tahoma,arial,'Hiragino Sans GB','\5b8b\4f53',sans-serif;
12px
,字体行高1.5
,字体先看浏览器或者服务器上有没有tohoma
,有则设置为tohoma
;如果没有,再看浏览器或者服务器上有没有arial
,以此类推。\5b8b\4f53
是使用 Unicode 编码的字体名,\5b8b
为Unicode的“宋”,\4f53 为Unicode的“体”,所以这个编码就是指“宋体”。%u
替换成 \
就是对应字体的UnicodejQuery 对象和 DOM 原生对象是两种不同的对象类型,两者不等价。
jQuery 无法使用 DOM 对象的任何方法,同理 DOM 对象也不能使用jQuery 里的方法。
DOM 原生对象转化为 jQuery 对象:
$(document.querySelector('.div1'))
jQuery对象转化为DOM原生对象:
$('.div1>li')[index]
在1.7之前的版本中 jQuery 处理事件有多个方法,( google 搜索: jQuery live bind degelate)作用各不相同,后来统一的使用 on/off 方法。
bind(type,[data],fn)
为每个匹配元素的特定事件绑定事件处理函数。jQuery 3.0 已弃用。
unbind(type,[data|fn]])
bind()的反向操作,从每一个匹配的元素中删除绑定的事件。jQuery 3.0 已弃用。
delegate(selector,[type],[data],fn)
指定的元素(属于被选元素的子元素)添加一个或多个事件处理程序,并规定当这些事件发生时运行的函数。jQuery 3.0已弃用。
live(type, [data], fn)
jQuery 给所有匹配的元素附加一个事件处理函数,即使这个元素是以后再添加进来的也有效。这个方法是基本是的 .bind() 方法的一个变体。
on(events,[selector],[data],fn)
在选择元素上绑定一个或多个事件的事件处理函数。
off(events,[selector],[fn])
在选择元素上移除一个或多个事件的事件处理函数。
绑定事件使用事件代理的写法举例:
<div class="box">
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
</div>
<input id="ipt" type="text"> <button id="btn">添加</button>
<div id="wrap">
</div>
<script>
$('.box li').on('click', function(){
console.log(1)
var str = $(this).text()
$('#wrap').text(str)
})
//等同于
$('.box>ul>li').click(function(){
console.log(2)
var str = $(this).text()
$('#wrap').text(str)
})
//也可以这样写
$('.box li').on('click.hello', function(){
console.log(3)
var str = $(this).text()
$('#wrap').text(str)
})
//命名空间没什么特别的作用,只不过在解绑事件时便于区分绑定的事件
$('.box li').off('click.hello')
//可是用如下方法新增的元素是没绑定事件的
$('#btn').on('click', function(){
var value = $('#ipt').val()
$('.box>ul').append('<li>'+value+'</li>')
})
//我们可以用事件代理
$('.box ul').on('click', 'li', function(){
var str = $(this).text()
$('#wrap').text(str)
})
//上面代码相当于原生 js 的
document.querySelector('.box ul').addEventListener('click', function(e){
if(e.target.tagName.toLowerCase() === 'li'){
//do something
}
})
//绑定事件的时候我们也可以给事件附带些数据,只不过这种用法很少见
$('.box').on('click', {name: 'hunger'}, function(e){
console.log(e.data)
})
.hide
用于隐藏元素,没有参数的时候等同于直接设置 display 属性。.show
用于显示元素,用法和 hide 类似。.toggle
用来切换元素的隐藏、显示,类似于 toggleClass ,用法和 show、hide 类似。举例:
//HTML
<div id="box"></div>
<button id="button 1">hide</button>
<button id="button 2">show</button>
<button id="button 3">toggle</button>
//jQuery
$("#button 1").on("click",function(){
$(".box").hide()
})
$("#button 2").on("click",function(){
$(".box").show()
})
$("#button 3").on("click",function(){
$(".box").toggle()
})
$('div').html();//不传参则获取 HTML 内容
$('div').html('<p>hello</p>');//传参则改变元素内部 HTML 内容为所传参数
$('div').text();//不传参则获取元素内部的文字信息
$('div').text('hello');//元素内部文字信息设置为 'hello'
$('input').val(); // 获取
$('input').val('想要设置的内容')
$(selector).attr('id'); // 获取元素属性
$(selector).attr('id', '设置的元素属性值');
1
的小数前面的 0
(例如,.5
代替 0.5
;-.5px
代替 -0.5px
)。#fff
input[type="text"]
margin: 0;
代替margin: 0px;
margin:15px 16px;
代替margin: 15px 16px 15px 16px;
.wrap
或.wrapper
-- 用于外侧包裹
.container
或 .ct
-- 包裹容器
.header
-- 用于头部
.body
-- 页面 body
.footer
-- 页面尾部
aside
、sidebar
-- 用于侧边栏
.content
-- 和header footer
对应,用于主要内容
.navigation
-- 导航元素
.pagination
-- 分页
.tabs
> .tab
-- tab 切换
.breadcrumbs
-- 导航列表、面包屑
.dropdown
-- 下拉菜单
.article
-- 文章
.main
-- 用于主体
.thumbnail
-- 头像,小图像
.media
-- 媒体资源
.panel
-- 面板
.tooltip
-- 鼠标放置上去的提示
.popup
-- 鼠标点击弹出的提示
.button
、.btn
-- 按钮
.ad
-- 广告
.subnav
-- 二级导航
.menu
-- 菜单
.tag
-- 标签
.message
或者.notice
-- 提示消息
.summary
-- 摘要
.logo
-- logo
.search
-- 搜索框
.login
-- 登录
.register
-- 注册
.username
-- 用户名
.password
-- 密码
.banner
-- 广告条
.copyright
-- 版权
.modal
或者 .dialog
-- 弹窗
var 名字 = {
状态: [
'inverse',
'toggled',
'switched',
'original',
'initial',
'identified',
'disabled',
'loading',
'pending',
'syncing',
'default'
],
修饰: [
'dark',
'light',
'shaded',
'flat',
'ghost',
'maroon',
'pale',
'intense',
'twisted',
'narrow',
'wide',
'smooth',
'separate',
'clean',
'sharp',
'aligned'
],
元素: [
'pagination',
'modal',
'popup',
'article',
'story',
'flash',
'status',
'state',
'media',
'block',
'card',
'teaser',
'badge',
'label',
'sheet',
'poster',
'notice',
'record',
'entry',
'item',
'figure',
'square',
'module',
'bar',
'button',
'action',
'knob'
],
布局: [
'navigation',
'wrapper',
'inner',
'header',
'footer',
'aside',
'section',
'divider',
'content',
'container',
'panel',
'pane',
'construct',
'composition',
'spacing',
'frame'
]
}
class
和 id
的使用场景?选择器 | 含义 |
---|---|
* |
通用元素选择器,匹配页面任何元素(这也就决定了我们很少使用) |
#id |
id选择器,匹配特定id的元素 |
.class |
类选择器,匹配class包含(不是等于)特定类的元素 |
element |
标签选择器 |
选择器 | 含义 |
---|---|
E,F | 多元素选择器,用,分隔,同时匹配元素E或元素F |
E F | 后代选择器,用空格分隔,匹配E元素所有的后代(不只是子元素、子元素向下递归)元素F |
E>F | 子元素选择器,用>分隔,匹配E元素的所有直接子元素 |
E+F | 直接相邻选择器,匹配E元素之后的相邻的同级元素F |
E~F | 普通相邻选择器(弟弟选择器),匹配E元素之后的同级元素F(无论直接相邻与否) |
.class1.class2 | id和class选择器和选择器连写的时候中间没有分隔符,. 和 # 本身充当分隔符的元素 |
element#id | id和class选择器和选择器连写的时候中间没有分隔符,. 和 # 本身充当分隔符的元素 |
选择器 | 含义 |
---|---|
E[attr] |
匹配所有具有属性attr的元素,div[id]就能取到所有有id属性的div |
E[attr = value] |
匹配属性attr值为value的元素,div[id=test],匹配id=test的div |
E[attr ~= value] |
匹配所有属性attr具有多个空格分隔、其中一个值等于value的元素 |
E[attr ^= value] |
匹配属性attr的值以value开头的元素 |
E[attr $= value] |
匹配属性attr的值以value结尾的元素 |
E[attr *= value] |
匹配属性attr的值包含value的元素 |
选择器 | 含义 |
---|---|
E:first-child | 匹配作为长子(第一个子女)的元素E |
E:link | 匹配所有未被点击的链接 |
E:visited | 匹配所有已被点击的链接 |
E:active | 匹配鼠标已经其上按下、还没有释放的E元素 |
E:hover | 匹配鼠标悬停其上的E元素 |
E:focus | 匹配获得当前焦点的E元素 |
E:lang(c) | 匹配lang属性等于c的E元素 |
E:enabled | 匹配表单中可用的元素 |
E:disabled | 匹配表单中禁用的元素 |
E:checked | 匹配表单中被选中的radio或checkbox元素 |
E::selection | 匹配用户当前选中的元素 |
E:root | 匹配文档的根元素,对于HTML文档,就是HTML元素 |
E:nth-child(n) | 匹配其父元素的第n个子元素,第一个编号为1 |
E:nth-last-child(n) | 匹配其父元素的倒数第n个子元素,第一个编号为1 |
E:nth-of-type(n) | 与:nth-child()作用类似,但是仅匹配使用同种标签的元素 |
E:nth-last-of-type(n) | 与:nth-last-child() 作用类似,但是仅匹配使用同种标签的元素 |
E:last-child | 匹配父元素的最后一个子元素,等同于:nth-last-child(1) |
E:first-of-type | 匹配父元素下使用同种标签的第一个子元素,等同于:nth-of-type(1) |
E:last-of-type | 匹配父元素下使用同种标签的最后一个子元素,等同于:nth-last-of-type(1) |
E:only-child | 匹配父元素下仅有的一个子元素,等同于:first-child:last-child或 :nth-child(1):nth-last-child(1) |
E:only-of-type | 匹配父元素下使用同种标签的唯一一个子元素,等同于:first-of-type:last-of-type或 :nth-of-type(1):nth-last-of-type(1) |
E:empty | 匹配一个不包含任何子元素的元素,文本节点也被看作子元素 |
E:not(selector) | 匹配不符合当前选择器的任何元素 |
1,2,3,4,5
2n+1, 2n, 4n-1
odd, even
选择器 | 含义 |
---|---|
E::first-line | 匹配E元素内容的第一行 |
E::first-letter | 匹配E元素内容的第一个字母 |
E::before | 在E元素之前插入生成的内容 |
E::after | 在E元素之后插入生成的内容 |
#test p.class1 {...}
#test .class1.class2 {...}
行内样式 <div style="xxx"></div>
==> a
ID 选择器 ==> b
类,属性选择器和伪类选择器 ==> c
标签选择器、伪元素 ==> d
* {} /* a=0 b=0 c=0 d=0 -> 0,0,0,0 */
p {} /* a=0 b=0 c=0 d=1 -> 0,0,0,1 */
a:hover {} /* a=0 b=0 c=0 d=2 -> 0,0,0,2 */
ul li {} /* a=0 b=0 c=0 d=2 -> 0,0,0,2 */
ul ol+li {} /* a=0 b=0 c=0 d=3 -> 0,0,0,3 */
h1+input[type=hidden]{} /* a=0 b=0 c=1 d=2 -> 0,0,1,1 */
ul ol li.active {} /* a=0 b=0 c=1 d=3 -> 0,0,1,3 */
#ct .box p {} /* a=0 b=1 c=1 d=1 -> 0,1,1,1 */
div#header:after {} /* a=0 b=1 c=0 d=2 -> 0,1,0,2 */
style="" /* a=1 b=0 c=0 d=0 -> 1,0,0,0 */
div {color: #333;}
....
div {color: #666;}
div
文案的颜色明显会是#666
a:link
, a:hover
, a:active
, a:visited
的顺序是怎样的? 为什么?a:link
a:visited
a:hover
a:active
:link
代表为访问链接的样式,所以只要你是超链接,且未被访问过,则链接都会按照你设定的样式显示,所以它的位置顺序无所谓。:visited
代表链接访问后的样式,则链接一旦被访问,则之后它的样式就会是你所设置的 visited
样式:active
选择器用于选择活动链接。当您在一个链接上点击时,它就会成为活动的(激活的)。:hover
代表的是你光标经过某一元素时的样式,如果将此样式放在 :active
之后,则当链接激活时,显示 :active
样式,当光标经过此链接时,会显示 hover
的样式,因为 hover
排在后,会覆盖 active
样式。如果 :hover
排在前,:active
排在后,则当光标激活时显示 :active
的样式,但当光标经过链接时,样式并未显示:hover
的样式,而是:active
的样式,因为应用的active
样式在hover
之后,覆盖了前面的样式。a:visited
在链接访问过一次之后永久生效,如果放在最后会覆盖掉其他的样式,a:hover
和 a:active
就会被覆盖,不会再产生它们的预期效果。 #header{
} /* id为header的css样式 */
.header{
}/* class为header的css样式 */
.header .logo{
}/* class为header的元素后代中所有class为logo的元素的css样式 */
.header.mobile{
}/* class包含header和mobile的元素的css样式 */
.header p, .header h3{
}/* class为header的元素后代中p元素和h3元素的css样式 */
#header .nav>li{
}/* id为header元素后代中有class为nav的元素的直接子元素li的css样式 */
#header a:hover{
}/* id为header元素的后代中a元素的状态为鼠标悬停其上的css样式 */
#header .logo~p{
}/* id为header元素的所有后代元素中,class为logo的元素之后的所有同级元素p的css样式 */
#header input[type="text"]{
}/* id为header元素的所有后代元素中,所有type="text"的input标签的css样式 */
div:first-child
、div:first-of-type
、div :first-child
和div :first-of-type
的作用和区别 (注意空格的作用)div:first-child
匹配父元素下,作为第一个子元素的div元素div:first-of-type
匹配父元素的子元素中,第一个div元素div :first-child
匹配所有div元素内所有元素中属于其父元素的首个子元素div :first-of-type
匹配所有div元素内所有元素中属于其父元素的首个类型的子元素<style>
.item1:first-child{
color: red;
}
.item1:first-of-type{
background: blue;
}
</style>
<div class="ct">
<p class="item1">aa</p>
<h3 class="item1">bb</h3>
<h3 class="item1">ccc</h3>
</div>
aa
字体为红色: .item1:first-child
匹配元素class
包含item1
的第一个子元素 aa
,所以为颜色变为红色aa
bb
的背景色为蓝色: .item1:first-of-type
匹配的是class
包含item1
其父元素下相同类型子元素中的第一个,所以第一个p
第一个h3
变蓝var obj1 = {a:1, b:2};
var obj2 = {a:1, b:2};
console.log(obj1 == obj2); //false 因为 obj1 和 obj2 所指向的地址不相等
console.log(obj1 = obj2); //Object {a: 1, b: 2} 因为 obj2 把地址赋值给了 obj1
console.log(obj1 == obj2); //true 因为现在 obj1 和 obj2 指向的是同一个地址
var a = 1
var b = 2
var c = { name: '饥人谷', age: 2 }
var d = [a, b, c]
var aa = a
var bb = b
var cc = c
var dd = d
a = 11
b = 22
c.name = 'hello'
d[2]['age'] = 3
console.log(aa) //1 因为 a 和 aa 为基本类型值-数值,赋值给 a 并不会影响 aa
console.log(bb) //2 因为 b 和 bb 为基本类型值-数值,赋值给 b 并不会影响 bb
console.log(cc) // Object {name: "hello", age: 3} 首先 name:"hello" 是因为 c 的地址赋值给了 cc ,c 和 cc 的地址为同一个地址; age:3 是因为 d[2]['age'] = 3 中,3 赋值给了 c 中的 age 。
console.log(dd) // [1,2,{name: "hello", age: 3}] 原因结合上面几点可以得出
var a = 1
var c = { name: 'jirengu', age: 2 }
function f1(n){
++n
}
function f2(obj){
++obj.age
}
f1(a) // a 和 n 都为基本类型值。把 a 赋值给 n 进行运算,不会影响 a 的值。
f2(c) // c 为引用类型值。把 c 的地址赋值给了 obj ,c 和 obj 都指向同一个地址。所以运算后 c = { name: 'jirengu', age: 3 } 。
f1(c.age) // c.age 是基本类型值。把 c.age 赋值给 n 进行运算,不会影响 c.age 的值。
console.log(a) // 1
console.log(c) // Object {name: "jirengu", age: 3}
var arr = [3,1,0,-1,-3,2,-5]
function filter(arr){
for (var i = 0; i < arr.length; i++){
if (arr[i] <= 0) {
arr.splice(i,1);
i--;
}
}
}
filter(arr)
console.log(arr) // [3,1,2]
var arr = [3,1,0,-1,-3,2,-5]
function filter(arr){
var arr2 = [];
for (var i = 0; i < arr.length; i++) {
if (arr[i] > 0) {
arr2.push(arr[i]);
}
}
return arr2;
}
var arr2 = filter(arr)
console.log(arr2) // [3,1,2]
console.log(arr) // [3,1,0,-1,-2,2,-5]
function deepcopy(obj){
var newObj={};
for (var key in obj){
if(obj.hasOwnProperty(key)){
if(typeof obj[key] === 'number' || typeof obj[key] === 'string' ||
typeof obj[key] === 'boolean' ||typeof obj[key] === 'string' || obj[key] === udefinded ||
obj[key] === null ){
newObj[key]=obj[key];
}else{
newobj[key]=copy(obj[key]);
}
}
}
return newObj;
}
function deepCopy(obj) {
var newObj = JSON.parse(JSON.stringify(obj));
return newObj;
}
年份 | 版本 |
---|---|
1997.1 | HTML 3.2 |
1997.12 | HTML 4.0 |
1999.12 | HTML 4.01 |
2014.10 | HTML 5 |
HTML 指的是内容结构;CSS 指的是样式;JavaScript 指的是行为。
- ASCII
American Standard Code for Information Interchange(美国信息交换代码),是基于拉丁字母的一套电脑编码系统,为美国英语通信所设计。它由128个字符组成,包括大小写字母、数字0-9、标点符号、非打印字符(换行符、制表符等4个)以及控制字符(退格、响铃等)组成,每个字符占7位(1字节是8位)。它主要用于显示现代英语,而其扩展版本EASCII则可以部分支持其他西欧语言,并等同于国际标准ISO/IEC 646。
- ISO Latin-1
ISO/IEC 8859-1,正式编号为ISO/IEC 8859-1:1998,又称Latin-1或“西欧语言”,是国际标准化组织内ISO/IEC 8859的第一个8位字符集。它以ASCII为基础,加入96个字母及符号,藉以供使用附加符号的拉丁字母语言使用。可以认为ASCII是美国发明针对英语设计的,但欧洲人在用的时候出现了问题。对于一些特殊的拉丁字符,比如法文德文里某些字符,ASCII字符集就不包括。于是欧洲人发明了一种8位字符集是ISO 8859-1 Latin 1,也简称为ISO Latin-1。它对ASCII做了个扩充,对于0-127之间的字符还使用ASCII里的字符不变, 把位于128-255之间的字符(也就是空置的0xA0-0xFF的范围内的字符)表示拉丁字母表中特殊语言字符。
- Unicode
Unicode(中文:万国码、国际码、统一码、单一码)是计算机科学领域里的一项业界标准。它对世界上大部分的文字系统进行了整理、编码,使得电脑可以用更为简单的方式来呈现和处理文字。Unicode的实现方式不同于编码方式。一个字符的Unicode编码是确定的。但是在实际传输过程中,由于不同系统平台的设计不一定一致,以及出于节省空间的目的,对Unicode编码的实现方式有所不同。Unicode的实现方式称为Unicode转换格式(Unicode Transformation Format,简称为UTF)。
- UTF-8
UTF-8(8-bit Unicode Transformation Format)是一种针对Unicode的可变长度字符编码,也是一种前缀码。它可以用来表示Unicode标准中的任何字符,且其编码中的第一个字节仍与ASCII兼容,这使得原来处理ASCII字符的软件无须或只须做少部分修改,即可继续使用。因此,它逐渐成为电子邮件、网页及其他存储或发送文字的应用中,优先采用的编码。
- GBK
汉字内码扩展规范,称GBK,全名为《汉字内码扩展规范(GBK)》1.0版。用2个字节来表示一个汉字,总共可以覆盖2万多个文字。英文保留和UTF-8同样的方式使用一个字节来表示。
- UNICODE只是给字符一个代号,而GBK和UTF-8使用不同的规则来表示同一个代号。
我们使用编辑器进行编辑后保存的的编码格式和浏览器的解码格式不匹配,从而产生乱码。(即使编码方式和解码方式不一致,纯粹的英文也不会出现乱码问题。因为utf-8、gbk对英文都是采用1个字节的编码方式,并且使用了相同的码字。)
直接告知浏览器通过指定的方式解码。如果文件保存为utf-8格式,那么一定要在html的<head>
里添加<meta charset="utf-8">
。同理,如果文件保存为gbk格式,一定要在文件里添加<meta charset="gbk">
。
颜色有几种写法?
<integer>
(整数)或3个<percentage>
(百分比)值。<number>
(整数)给出。定义 red=0=360,其它颜色分散于圆环,所以 green=120, blue=240,以此类推。作为一个角度,它隐含像 -120=240 和 480=120 这样的回环。红色、绿色、蓝色、白色、黑色如何表示?
颜色 | 色彩关键字 | rgb | hsl |
---|---|---|---|
红色 | red | rgb(255,0,0) #FF0000 | hsl(0,100%,50%) |
绿色 | green | rgb(0,255,0) #00FF00 | hsl(120,100%,25%) |
蓝色 | blue | rgb(0,0,255) #0000FF | hsl(240,100%,50%) |
白色 | white | rgb(255,255,255) #FFFFFF | hsl(0,0%,100%) |
黑色 | black | rgb(0,0,0) #000000 | hsl(0,0%,0%) |
颜色 | rgba | hsla |
---|---|---|
透明黑色 | rgb(0%,0%,0%,0.6) | hsl(0,0%,0%,0.6) |
此透明黑色的alpha值(透明度)为0.6,也就是为40%的透明。
#ccc
、#eee
、#333
的颜色?
#ccc
表示浅灰色#eee
表示灰色#333
表示深灰色<!doctype html>
的作用是什么?文档声明,让浏览器按w3c所规定的html5标准渲染这个页面。
<!doctype>
,浏览器进行解码时,按照此声明的规范来呈现页面。<!doctype>
,浏览器按照自己的默认方式解码来呈现页面。meta
有什么作用,常见的值有哪些?meta
的定义和用法
<meta>
元素可提供有关页面的元信息(meta-information),比如针对搜索引擎和更新频度的描述和关键词。
<meta>
标签位于文档的头部,不包含任何内容。<meta>
标签的属性定义了与文档相关联的名称/值对。
<meta>
是用来在HTML文档中模拟HTTP协议的响应头报文,它提供用户不可见的信息。<meta>
标签用于网页的<head>
与</head>
中。<meta>
标签的用处很多
<meta>
常见的属性和值属性 | 值 | 描述 |
---|---|---|
content |
some_text | 定义与http-equiv 或name 属性相关的元信息 |
可选的属性和值
属性 | 值 | 描述 |
---|---|---|
http-equiv |
content-type expires refresh set-cookie |
把content 属性关联到 HTTP 头部 |
name |
author description keywords generator revised others |
把content 属性关联到一个名称 |
scheme |
some_text | 定义用于翻译content 属性值的格式 |
<meta http-equiv="X-UA-compatible"content="IE=edge,chrome=1"
有什么作用?强制浏览器按照最新的标准去渲染,而chrome=1
将允许站点在使用了谷歌浏览器内嵌框架(Chrome Frame)的客户端渲染,对于没有使用的,则没有任何影响。
X-UA-Compatible
是针对 IE8 版本的一个特殊文件头标记,用于为 IE8 指定不同的页面渲染模式,对于ie8之外的浏览器是不识别的。
浏览器 | 内核 |
---|---|
Chrome | WebKit(Chromium)>Blink |
Safari | WebKit |
IE | Trident |
Firefox | Gecko |
Opera | Presto>WebKit(Chromium)>Blink |
360、QQ | Webkit+Trident |
h1
~h6
标题
h1
代表页面最大的标题
h2
二级标题
h3
... 更弱的标题
p
段落,表示大段文字
a
链接,链到一个地址
<a href="http://github.com" target="_blank" title="Github">github.com</a>
<a href="#">github.com</a>
<a href="#about">github.com</a>
<a href="/getCourse">github.com</a>
img
展示一张图片
<img src="a.png" alt="头像">
只闭合标签,最后不需要加 /
div
语义为“一大块”,用于给页面划分区块,让结构更清晰
<div id="header">...</div>
<div id="content">...</div>
<div id="footer">...</div>
ul
li
ul
: unsort list 无序列表
用于表示并列的内容
ul
的直接子元素是li
可以嵌套
<ul class="nav">
<li><a href="#">首页</a></li>
<li><a href="#">关于</a></li>
<li>
<a href="#">更多</a>
<ul>
<li>联系</li>
<li>地址</li>
</ul>
</li>
</ul>
ol
li
ol
: order list 有序序列表 用于表示带步骤或者编号的并列内容 ol
的直接子元素只能是li
可以嵌套
<h2>把大象关到冰箱的步骤</h2>
<ol>
<li>把大象变小</li>
<li>打开冰箱</li>
<li>把大象塞进去</li>
</ol>
dl
dt
dd
用于展示一系列 “标题:内容... ”的场景
<dl>
<dt>商品名称:</dt>
<dd>青花瓷</dd>
<dt>特征:</dt>
<dd>白色</dd>
<dd>圆口</dd>
<dt>商品介绍</dt>
<dd>这是一个年代久远的瓷器,很贵,易碎</dd>
</dl>
button
按钮
<button>点我</button>
strong
em
em
需要强调一下
strong
很重要、强调性更强
<p>优惠 <strong>100</strong> 元</p>
<p>WHV <em>成功</em> 了</p>
iframe
用于嵌入一个页面 注意跨域操作问题
<iframe src="http://jirengu.com" name="myPage"></iframe>
<p><a href="http://www.w3cschool.cc" target="myPage">W3Cschool.cc</a></p>
table
用于展示表格,不要用来做布局 thead tbody tfoot可省略,浏览器会自动添加 border-collapse: collapse;用于合并边框
<table>
<thead>
<tr>
<th>姓名</th>
<th>年纪</th>
</tr>
</thead>
<tbody>
<tr>
<th>姓名</th>
<th>年纪</th>
</tr>
<tr>
<td>小明</td>
<td>18</td>
</tr>
<tr>
<td>小花</td>
<td>20</td>
</tr>
</tbody>
<tfoot></tfoot>
</table>
<table>
<tr>
<th>姓名</th>
<th>年纪</th>
</tr>
<tr>
<td>小明</td>
<td>18</td>
</tr>
<tr>
<td>小花</td>
<td>20</td>
</tr>
</table>
overflow: hidden
隐藏其他不可见图。overflow: hidden
隐藏其他图片。overflow: hidden
形成 BFC,防止因浮动产生高度坍塌。具体实现:
在 img 容器中,clone 最后一个元素至第一张图片的前面,clone 第一个元素至最后一张图片的后面,通过计算
(imgCount+2) * imgWidth
得到 img 容器的宽度,imgCount
为初始 li 元素的个数。
先确定好第一张展示图片的位置为$imgWrapper.css({left: -imgWidth})
,当图片左右切换,img 容器位置左右加减。当移动到 clone 的首图片时,立即跳转到原来的尾图片,设置 CSS 属性$imgWrapper.css({left: -imgWidth})
。当运动到 clone 尾图片时,立即跳转到原来的首图片 $imgCt.css({left: -imgCount*imgWidth})
,从而达到无限左右滚动效果,CSS 属性切换在人眼看来是连贯的,达到欺骗效果。
imgCount-1
,通过不同的标记位 img 容器移动对应的位置,实现跳转图片。text-align: center
的作用是什么,作用在什么元素上?能让什么元素水平居中?text-align
CSS 属性定义行内内容(例如文字)如何相对它的块父元素对齐,text-align
并不控制块元素自己的对齐,只控制它的行内内容的对齐。text-align:center
的意思是块级元素中的行内内容居中。block-level
元素上(包括了block
和inline-block
)block-level
的元素中的行内元素,替换元素和inline-block
元素居中。padding
、border
所占的空间不在width
、height
范围内,大家俗称的 IE 的盒模型width
包括content
尺寸+padding
+border
*{ box-sizing: border-box;}
的作用是什么?width
,height
包括content
尺寸 + padding
+ border
border
、padding
、content
。我们可以使用box-sizing:border-box;
达到 IE 盒模型的效果,可以省略很多计算。line-height: 2
和line-height: 200%
有什么区别?line-height: 2
根据自身元素的字体大小来计算,会较为美观。line-height: 200%
根据父元素的字体大小来计算。line-height: 2
继承给子元素的是2这个缩放因子。line-height: 200%
继承给子元素的是200%计算后的值,比如父元素的行高为1px,那么所有子元素都继承为2px,子元素的字体大小不一样时行高也都为2px,这样会导致或宽或窄,不好看甚至影响阅读。inline-block
有什么特性?如何去除缝隙?高度不一样的inline-block
元素如何顶端对齐?inline
特性(不占据一整行,宽度由内容宽度决定)block
特性 (可设置宽高,内外边距)eg:
<li>按钮</li>
<li>按钮</li>
<li>按钮</li>
写成
<li>按钮</li><li>按钮</li><li>按钮</li>
给inline-block
的父元素设置font-size:0
,再给设置了inline-block
的元素重新设置font-size
就可以了。
设置负margin
值
元素设置浮动
inline-block
元素如何顶端对齐inline-block
元素设置为vertical-align:top;
原理:把多个小icon合成一个大的图片,使用的时候,元素以这张合成后的大图为背景,通过设置background-position的属性来获取指定icon。
优点:合并原来图片的请求,减少http的性能消耗。
缺点:CSS sprite不能太大,不然下载图片的时间会过长。
应用:
域名发散和域名收敛
display:none;
visibility:hidden;
opacity:0;
height:0;width:0;padding:0;margin:0;border:0; ... etc
position:absolute; left:1000000px; top:100000px; ...etc;
z-index:-1000;...etc
background-color:rgba(0,0,0,0);
function isVisible($node) {
var scrollTop = $(window).scrollTop()//滚动高度
var windowHeight = $(window).height()//窗口高度
var offsetTop = $node.offset().top
if(offset < scrollTop + windowHeight && offsetTop > scrollTop) {
return true
}
return false
}
lazyLoad()
$(window).on('scroll',function(){
console.log('true')
lazyLoad()
})
function lazyLoad(){
$('.ct img').each(function(){
if(isVisible($(this)) && !isLoaded($(this)) ){
loadImg($(this))
}
})
}
lazyLoad()
var clock
$(window).on('scroll',function(){
if(clock){
clearTimeout(clock)
}
clock = setTimeout(function(){
console.log('true')
lazyLoad()
}, 300)
})
function lazyLoad(){
$('.ct img').each(function(){
if(isVisible($(this)) && !isLoaded($(this)) ){
loadImg($(this))
}
})
}
如果一个页面中有大量的图片(比如电商网站),打开页面后一次性全部加载完的话,流量消耗巨大,而且打开速度很慢,甚至卡死。
图片懒加载就是用来解决这些问题,提升用户体验。
img
标签,把真实的地址放入自定义属性data-src
。<img src="/static/loading.gif" data-src="http://真正的图片地址/xxx.jpg">
<img src="xxx">
可以为空,但在一些浏览器中会显示x的符号,影响体验。所以可以用空白图片或者加载动画代替。
img
标签,看看这个标签是否出现到我们的视野中或者说出现在屏幕中,之后再去判断它是否已经加载过,如果没有加载过,就利用 jQuery 把<img>
的src
属性替换为data-src
的内容,浏览器就会实时加载。var request = new XMLHttpRequest()
request.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
console.log(request.responseText)
}
};
第三行的 request.responseText
就是服务器返回的内容了(默认是字符串)
request.open("GET", "filename", true);
request.send();
这 4 步看起来是有些复杂的,不要紧,jQuery.ajax 对这 4 步进行了封装,只需要一步就可以了:
$.get('filename').then(function(response){
// 这里的 response 就是返回的内容
})
更好的用户体验(不用刷新页面,或者说只需要刷新部分页面)
//状态锁伪代码
var lock = false;
btn.addEventListener("click",function(){
if(lock){
return; //如果没有收到数据 就不往下执行
}else{
lock = true;
ajax({
....
lock = false; //收到响应之后才把 false 赋值给 lock
})
}
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>加载更多</title>
<style>
.ct{
list-style: none;
padding: 0;
}
.ct li{
margin-bottom: 10px;
border: 1px solid;
cursor: pointer;
height: 38px;
padding-top: 10px;
}
.ct li:hover{
background: green;
color:white;
}
.button {
display: block;
width: 100px;
height: 40px;
line-height: 40px;
margin: 0 auto;
border: 1px solid red;
text-align: center;
text-decoration: none;
color: red;
}
</style>
</head>
<body>
<ul class="ct">
<li>内容1</li>
<li>内容2</li>
</ul>
<a href="#" class="button">加载更多</a>
<script>
var button = document.querySelector('.button')
var content = document.querySelector('.ct')
var xhr = new XMLHttpRequest()
var index = 2
var sendEnd = false
button.addEventListener('click', function (e) {
e.preventDefault()
if (sendEnd){
return
}
xhr.onreadystatechange = function () {
if(xhr.readyState === 4 && (xhr.status == 200||xhr.status == 304)){
//获取数据
var data = JSON.parse(xhr.responseText)
var fragment = document.createDocumentFragment()
for (var i in data){
//创建元素
var li = document.createElement('li')
//将内容放入元素
li.innerText = data[i]
fragment.appendChild(li)
}
content.appendChild(fragment)
sendEnd = false
}
}
xhr.open('get', '/loadMore?index=' + index + '&length=5', true)
xhr.send()
sendEnd = true
index += 5
})
</script>
</body>
</html>
// router.js
app.get('/loadMore', function(req, res) {
var curIdx = req.query.index;
var len = req.query.length;
var data = [];
for(var i = 0; i < len; i++) {
data.push('新闻' + (parseInt(curIdx) + i))
}
res.send(data);
});
喜欢写 Blog 的人,会经历三个阶段。
第一阶段,刚接触 Blog,觉得很新鲜,试着选择一个免费空间来写。
第二阶段,发现免费空间限制太多,就自己购买域名和空间,搭建独立博客。
第三阶段,觉得独立博客的管理太麻烦,最好在保留控制权的前提下,让别人来管,自己只负责写文章。
这是阮一峰在博客中写到的关于 Blog 的想法,而这里的第三阶段的实现就是利用 GitHub Pages 搭建博客。
使用 GitHub Pages 功能搭建博客的好处有:
Hexo 是基于 Node.js 的一款静态博客框架,如果想要搭建博客,不想自己写页面的话可以考虑用 Hexo,其中有很多的简洁主题可供选择,同时 Hexo 支持 Markdown 语法,编辑文章更加方便,快捷。
注:此篇分享以 Mac 为例
Hexo 文档有对 Hexo 安装及使用的详细介绍,推荐阅读。这里我主要写自己安装的步骤、踩过的坑以及一些优化的方法。
在正式安装 Hexo 之前,我们需要确认电脑中是否已安装下列应用程序:
当然,我们还需要 GitHub 账号,如果没有请注册。
注册之后记得一定要前往邮箱确认注册,否则无法使用 GitHub Pages。
所有必备的应用程序安装完成后,即可使用 npm 安装 Hexo。终端输入如下命令:
sudo npm install -g hexo-cli
输入管理员密码( Mac 登录密码)即开始安装。
这里有个小坑:Hexo 官网上的安装命令是
npm install -g hexo-cli
,安装时不要忘记前面加上sudo
,否则会因为权限问题报错。
使用终端cd
到一个您指定的目录,执行以下命令(命令中的blog
是您将要建立的文件夹的名称):
hexo init blog
使用终端cd
到blog
文件夹下,执行以下命令,安装npm:
npm install
好了,现在可以试试看是否已经初始化成功,执行如下命令,开启本地 Hexo 服务器:
hexo s
此时,浏览器中打开网址(默认是4000端口) http://localhost:4000 ,能看到如下页面:
这里我踩了个不算坑的坑,终端输入hexo s
后没有成功,我也在网上搜到了很多解决办法,但是都没有奏效,后来我尝试改了下端口就成功了,也就是说默认的4000端口无法连接。如果您的情况跟我一样,尝试了网上的很多解决办法之后依然无效,那您也许可以尝试输入命令hexo s -p 5000
改一下端口试试看。
您的用户名.github.io
的仓库。假设我的 GitHub 账号的用户名是 luxun
,那么我就应该新建名称为luxun.github.io
的仓库。Description
可写可不写,随意。Initialize this repository with a README
。Create Repository
完成创建。点击Settings
,你将会打开这个库的 Settings 页面,向下拖动,直到看见 GitHub Pages,如图:
Hexo 官方文档中有对全局配置的详细说明,推荐阅读。
小坑提醒,修改本地所有的配置文件时,注意所有的冒号
:
后边都要加一个空格,否则执行 Hexo 命令时会报错,一定注意。
找到本地blog
文件夹下_config.yml
,打开后滑到最后,修改成下边的样子:
deploy:
type: git
repository: https://github.com/xxx/xxx.github.io.git
branch: master
您需要将repository
后的所有xxx
换成你自己的用户名,或者也可以在下图位置获取:
然后,您需要为自己配置身份信息,终端输入yourname
和youremail
换成您自己的 GitHub 用户名和邮箱):
git config --global user.name "yourname"
git config --global user.email "youremail"
终端cd
到blog
文件夹下执行生成静态页面命令:
hexo g
此时若出现如下报错:
ERROR Local hexo not found in ~/blog
ERROR Try runing: 'npm install hexo --save'
尝试执行命令:
npm install hexo --save
若无报错,自行忽略此步骤。
然后在当前目录下,终端输入:
hexo d
这里踩了个坑,如果您执行命令hexo d
仍然报错:无法连接 git 或找不到 git,则执行如下命令来安装hexo-deployer-git
:
npm install hexo-deployer-git --save
完成安装之后,再次执行hexo g
和hexo d
命令。
随后按照提示,分别输入自己的 GitHub 用户名和密码,开始上传。
完成上传之后,通过http://xxx.github.io/
(xxx
换成您自己的仓库名,也就是用户名)来访问自己刚刚上传的网站。
添加ssh key 到 GitHub
进行优化hexo new "postName" //新建文章
hexo new page "pageName" //新建页面
hexo g //生成静态页面至public目录
hexo server //开启预览访问端口(默认端口4000,'ctrl + c'关闭server)
hexo deploy //将.deploy目录部署到GitHub
hexo clean
hexo g
hexo d
hexo d -g #生成部署
hexo s -g #生成预览
终端cd
到blog
文件夹下,执行如下命令新建文章:
hexo new "xxx"
名为xxx.md
的文件会建在目录.../blog/source/_posts
下。
所有的文章都会以md
形式保存在_post
文件夹中,只要在_post
文件夹中新建md
类型的文档,就能在执行hexo g
的时候被渲染。新建的文章头需要添加一些信息,如下所示:
---
title: xxx //在此处添加你的标题。
date: 2016-10-07 13:38:49 //在此处输入编辑这篇文章的时间。
tags: xxx //在此处输入这篇文章的标签。
categories: xxx //在此处输入这篇文章的分类。
---
文章编辑完成后,终端cd
到blog
文件夹下,依次执行如下命令来发布:
hexo g
hexo d
至此,Mac 上搭建基于 GitHub Pages + Hexo 的博客就完成了。
下面的内容是介绍安装 Themes 、个性化设置以及优化。
如果您喜欢 Hexo 默认的主题的话,可以跳过这部分。如果您想换一个主题的话,可以到Hexo 主题挑选自己中意的主题。
这里以nexT 主题为例。
终端cd
到blog
目录下执行如下命令(这是目前的稳定版本,不是最新版。最新版有一些新特性,但是可能会不稳定,所以这里推荐选择安装稳定版):
git clone --branch v5.1.2 https://github.com/iissnan/hexo-theme-next themes/next
如果想尝试最新版,请执行如下命令:
git clone https://github.com/iissnan/hexo-theme-next themes/next
打开blog
目录下的_config.yml
,找到theme: landscape
修改为theme: next
。
终端cd
到blog
目录下,依次执行如下命令(每次部署文章的步骤):
hexo clean
hexo g
hexo d
至于更改博客的名称、描述、头像等,只需要修改blog/_config.yml
文件和blog/themes/next/_config.yml
文件中对应的属性名称即可(不要忘记冒号:
后加空格)。
这里以 Next 主题为例(其他主题也差不多),添加 GitHub 丝带:在blog\themes\next\layout\_layout.swig
中加入相关代码,记得修改自己的链接。
每个项目仓库下一般都有一个 README.md
文件,但是使用 hexo 部署到仓库后,项目仓库中是没有 README.md
文件的。
在 blog
目录下的 source
目录下添加一个 README.md
文件,修改站点配置文件 _config.yml
,将 skip_render
参数的值设置为 README.md
。
skip_render: README.md
保存退出即可。
在主题配置文件中添加下面这段代码(添加之前先看看您的主题配置文件是否已经包含这段代码,已经包含就不用添加了,因为重复会报错),LICENSE 会显示在侧边栏。
# Creative Commons 4.0 International License.
# http://creativecommons.org/
# Available: by | by-nc | by-nc-nd | by-nc-sa | by-nd | by-sa | zero
creative_commons: by-nc-sa
#creative_commons:
#
号的标签如果您觉得#
不好看,想改成图标,那么请按照下面修改。
打开/themes/next/layout/_macro/post.swig
,搜索(组合键command
+f
)rel="tag">#
,将#
换成<i class="fa fa-tag"></i>
。
很多人将文章标题下的 阅读次数 改为了 热度,如果您喜欢的话可以这样修改。
打开blog/themes/next/languages/zh-Hans
文件,查找阅读次数
这几个字,可以看到,在post
中的visitors
被定义为阅读次数
,把这里的阅读次数
改为热度
:
visitors: 热度
那么怎么在页面中显示呢?打开Next主题文件夹中blog/themes/next/layout/_macro/post.swig
,在这个文件里加上摄氏度的标志,在<span class="leancloud-visitors-count"></span>
下面增加一行<span>℃</span>
即可:
<span class="leancloud-visitors-count"></span>
<span>℃</span>
替换文件blog/node_modules/hexo-generator-index/lib/generator.js
内的代码为:
'use strict';
var pagination = require('hexo-pagination');
module.exports = function(locals){
var config = this.config;
var posts = locals.posts;
posts.data = posts.data.sort(function(a, b) {
if(a.top && b.top) { // 两篇文章top都有定义
if(a.top == b.top) return b.date - a.date; // 若top值一样则按照文章日期降序排
else return b.top - a.top; // 否则按照top值降序排
}
else if(a.top && !b.top) { // 以下是只有一篇文章top有定义,那么将有top的排在前面(这里用异或操作居然不行233)
return -1;
}
else if(!a.top && b.top) {
return 1;
}
else return b.date - a.date; // 都没定义按照文章日期降序排
});
var paginationDir = config.pagination_dir || 'page';
return pagination('', posts, {
perPage: config.index_generator.per_page,
layout: ['index', 'archive'],
format: paginationDir + '/%d/',
data: {
__index: true
}
});
};
在文章 Front-matter 中添加 top 值,数值越大文章越靠前,如:
---
title: xxx
date: 2015-04-02 14:36:04
categories: xxx
tags: xxx
top: 10
---
这里只说一个方法:编辑文章时,在您希望显示 加载更多
按钮的地方,加上<!--more-->
:
在 \themes\next\source\css\_custom\custom.styl
文件中添加以下代码,可以修改博客首页中每篇文章的分割线样式,width
是长度,height
是宽度。
//index页面中每篇文章相隔的那条线
.posts-expand {
.post-eof {
display: block;
margin: $post-eof-margin-top auto $post-eof-margin-bottom;
width: 100%;
height: 3px;
background: $grey-light;
text-align: center;
}
}
博客中一切小图标都可以在fontawesome 图标库自行搜索(qq、微博、微信等图标是有的,但知乎、豆瓣等图标目前还没有)。
blog/themes/next/layout/_partials/footer.swig
,找到这段代码进行修改(还是在fontawesome 图标库找自己喜欢的图标):<span class="with-love">
<i class="fa fa-share-alt"></i>
</span>
准备一张 icon 图标文件,放在 source 目录下就可以了,在主题配置文件
中找到 favicon 的设置:
# Put your favicon.ico into `hexo-site/source/` directory.
favicon: /favicon.ico
具体实现方法
打开blog\themes\next\source\css\_custom\custom.styl
文件,添加以下代码:
//主页文章添加阴影效果
.post {
margin-top: 60px;
margin-bottom: 60px;
padding: 25px;
-webkit-box-shadow: 0 0 5px rgba(202, 203, 203, .5);
-moz-box-shadow: 0 0 5px rgba(202, 203, 204, .5);
}
打开blog/themes/next/layout/_partials/footer.swig
,使用<!--
-->
隐藏符号之间的代码即可,或者直接将这段代码删除。位置如图:
终端执行如下命令,检查SSH keys是否存在。
ls ~/.ssh
如果显示如下信息(下面是我个人的显示,也许您跟我显示的不一样,但重点是只要有id_rsa
和id_rsa.pub
),就说明 SSH keys 已经存在了:
id_rsa id_rsa.pub known_hosts
如果存在,则直接跳过下一个步骤进入将 SSH key 添加到 GitHub 中
,否则请继续下一步骤 生成新的 SSH key
。
终端执行如下命令生成新的 SSH key,注意将[email protected]
换成你自己注册 GitHub 的邮箱地址。
ssh-keygen -t rsa -C "[email protected]"
默认会在相应路径~/.ssh
下生成id_rsa
和id_rsa.pub
两个文件。
1.3.将 SSH key 添加到 GitHub 中
终端依次输入:
cd ~/.ssh
cat id_rsa.pub
复制所有显示的内容
进入GitHub –> Settings –> SSH and GPG keys –> NEW SSH key,如下图所示:
Title 里任意添一个标题,将复制的内容粘贴到 Key 里,点击下方 Add SSH key 绿色按钮即可,如下图所示:
然后,我们需要配置一下域名解析。推荐使用DNSPod的服务,免费稳定,解析速度也比较快。在域名注册商处(Godaddy 或万网)修改 NS 服务器地址为:
f1g1ns1.dnspod.net
f1g1ns2.dnspod.net
域名解析详细的步骤这里我就不写了,给个图:
图中设置国内国外的原因是想让博客加载速度更快,方法请阅读后文 将个人博客同时部署到 GitHub 和 Coding。
进入 blog/source
目录下,添加并打开 CNAME
文件,输入您的域名,重新上传您的博客。
在 GitHub 中打开您自己的博客仓库,进入库的 Settings 界面,如果看到了如下提示,说明配置成功了。
在这一系列的操作中,修改 NS 服务器、设置解析等等,都需要一定的时间。短则10分钟,长则24小时,最长不会超过72小时。如果超过72小时,请检查自己的配置过程,或者修改自己本地的 DNS 服务器。
Coding 可以理解为国内的 GitHub。通过将博客同时部署到 GitHub 和 Coding,可以提升博客的加载速度。
这里有个提醒,Coding 会强制用户在网站上挂推广图标,通过 Coding 加载博客还会有5s广告,如果觉得这样不好,可以选择放弃部署在 Coding 上。还有一个选择,就是花钱成为 Coding 的会员,这样上述的问题就都没有了。
首先到Coding注册。创建仓库跟 GitHub 上创建仓库的要求一样。
打开本地 blog
目录下的 _config.yml
文件,滑到最下面,修改如下(xxx换成自己的用户名):
deploy:
type: git
repository:
github: https://github.com/xxx/xxx.github.io.git
coding: https://git.coding.net/xxx/xxx.git
branch: master
然后执行命令hexo clean
hexo g
hexo d
个人域名添加两条 CNAME 解析。将 GitHub 的地址 解析为 国外
,将 Coding 的地址 解析为 国内
:
Pages 服务
界面,添加域名绑定,输入个人域名就 OK 了,可能需要耐心等待几分钟。这样就可以实现从国内访问就通过 Coding 加载博客项目,从国外访问就通过 GitHub 加载博客项目,从而提升加载博客的速度。
压缩代码也是一个优化加载速度的方法。
目前知道的有两个插件可以压缩博文,hexo-all-minifier 插件和 gulp 插件。hexo-all-minifier 使用比较简单,也可以压缩图片,不过对文章缩进不支持。如果您对文章缩进有要求,可以暂时使用 gulp 压缩手段。
安装 hexo-all-minifier,在站点的根目录下执行以下命令:
npm install hexo-all-minifier --save
hexo g
编译的时候就会自动压缩 HTML、JS、图片。详情参考插件介绍 hexo-all-minifier。
Hexo 依赖 gulp 插件安装,在站点的根目录下执行以下命令:
npm install gulp -g
npm install gulp-minify-css gulp-uglify gulp-htmlmin gulp-htmlclean gulp --save
在blog
目录下,新建 gulpfile.js
并填入以下内容:
var gulp = require('gulp');
var minifycss = require('gulp-minify-css');
var uglify = require('gulp-uglify');
var htmlmin = require('gulp-htmlmin');
var htmlclean = require('gulp-htmlclean');
// 压缩 public 目录 css
gulp.task('minify-css', function() {
return gulp.src('./public/**/*.css')
.pipe(minifycss())
.pipe(gulp.dest('./public'));
});
// 压缩 public 目录 html
gulp.task('minify-html', function() {
return gulp.src('./public/**/*.html')
.pipe(htmlclean())
.pipe(htmlmin({
removeComments: true,
minifyJS: true,
minifyCSS: true,
minifyURLs: true,
}))
.pipe(gulp.dest('./public'))
});
// 压缩 public/js 目录 js
gulp.task('minify-js', function() {
return gulp.src('./public/**/*.js')
.pipe(uglify())
.pipe(gulp.dest('./public'));
});
// 执行 gulp 命令时执行的任务
gulp.task('default', [
'minify-html','minify-css','minify-js'
]);
生成博文时执行 hexo g && gulp
就会根据 gulpfile.js
中的配置,对 public 目录中的静态资源文件进行压缩。
验证方式有几种,推荐最简单的两种:文件验证和 CNAME 验证。
source
文件下站点配置文件
中找到skip_render:
[xxx.html, xxx.html]
,比如: skip_render: [googleff0226f76d5f451b.html, baidu_verify_vHC5EAW09E.html]
hexo clean
hexo d -g
zz.baidu.com
安装 Hexo 的 sitemap 网站地图生成插件,终端cd
到blog
:
npm install hexo-generator-sitemap --save
npm install hexo-generator-baidu-sitemap --save
在站点配置文件
中任意位置添加如下代码,但要看清您的 Hexo 版本。
如果您的 Hexo 版本是 2.x.x
sitemap:
path: sitemap.xml
baidusitemap:
path: baidusitemap.xml
如果您的 Hexo 版本是 3.x.x
sitemap:
path: sitemap.xml
baidusitemap:
path: baidusitemap.xml
配置成功后,会生成sitemap.xml
和baidusitemap.xml
,前者适合提交给谷歌搜素引擎,后者适合提交百度搜索引擎。
百度 sitemap 提交如图,Google 也是一样的:
验证成功之后就可以开始推送了。Google 的收录比较快,通常第二天就能搜得到,百度就比较慢了。
安装主动推送插件,终端cd
到blog
:
npm install hexo-baidu-url-submit --save
在根目录下,把以下内容配置到站点配置文件中:
baidu_url_submit:
count: 3 ## 比如3,代表提交最新的三个链接
host: xxx ## 在百度站长平台中注册的域名
token: xxx ## 请注意这是您的秘钥,请不要发布在公众仓库里!
path: baidu_urls.txt ## 文本文档的地址,新链接会保存在此文本文档里
至于上面提到的token
可在百度站长如下位置找到:
其次,记得查看站点配置文件
中的url
,必须包含站长平台注册的域名,比如:
url: http://harleywang93.com
root: /
permalink: :year/:month/:day/:title/
接下来添加一个新的 deploy
类型:
deploy:
- type: baidu_url_submitter
- type: git
repository:
github: https://github.com/xxx/xxx.github.io.git
coding: https://git.coding.net/xxx/xxx.git
branch: master
执行hexo d
的时候,新的链接就会被推送了。原理:
hexo g
会产生一个文本文件,里面包含最新的链接。hexo d
会从上述文件中读取链接,提交至百度搜索引擎。把 NexT 主题配置文件中的baidu_push:
设置为true
,就可以了。
在blog/source/
目录下新建一个robots.txt
文件,添加下面的一段代码(可根据自己的需要修改):
#hexo robots.txt
User-agent: *
Allow: /
Allow: /archives/
Disallow: /vendors/
Disallow: /js/
Disallow: /css/
Disallow: /fonts/
Disallow: /vendors/
Disallow: /fancybox/
Sitemap: http://xxx/sitemap.xml
Sitemap: http://xxx/baidusitemap.xml
然后到站长(这里以百度为例,Google 一样)更新一下,就像这样:
自己搭建博客时,很是折腾了一番,也学习到了很多知识,阅读了很多相关的博文,在此向相关博文的作者表示感谢,谢谢你们的文章让我进步。同时,我看到有很多人想拥有自己的博客或者优化自己的博客,期间可能会遇到很多问题,我也是这么一个坑一个坑踩过来的,所以我就写了这么一篇自己折腾博客的分享,希望可以在帮助自己的同时帮助到别人。(如果踩了新坑的话,一定会更新的。)
搭建一个免费的,无限流量的Blog-阮一峰
Hexo搭建博客教程
基于Hexo+Node.js+github+coding搭建个人博客——进阶篇(从入门到入土)
<head>
标签之内<script>...</script>
<script src=”index.js”></script>
外部引用body
标签的最后面,即闭合标签</body>
之前。白屏的根本原因是浏览器在渲染的时候请求时间过长造成的。
如果把样式放在底部:
<script src="script.js"></script>
没有 defer 或 async,浏览器会立即加载并执行指定的脚本,“立即”指的是在渲染该 script 标签之下的文档元素之前,也就是说不等待后续载入的文档元素,读到就加载并执行。
<script async src="script.js"></script>
有 async,加载和渲染后续文档元素的过程将和 script.js 的加载与执行并行进行(异步)。
<script defer src="script.js"></script>
有 defer,加载后续文档元素的过程将和 script.js 的加载并行进行(异步),但 script.js 的执行要在所有元素解析完成之后,DOMContentLoaded 事件触发之前完成。
defer 和 async 的区别
defer: 脚本延迟到文档解析和显示后执行,有顺序
async: 不保证顺序
github.com
就是域名。github.com
到底是什么东西,需要查找 github.com 网站所在服务器的IP地址,才能找到目标。8.8.8.8 —— Google 提供的免费 DNS 服务器的 IP 地址
114.114.114.114 —— 是国内第一个、全球第三个开放的 DNS 服务地址,又称114DNS
DNS劫持:DNS劫持又称域名劫持,是指在劫持的网络范围内拦截域名解析的请求,分析请求的域名,把审查范围以外的请求放行,否则返回假的IP地址或者什么都不做使请求失去响应,其效果就是对特定的网络不能反应或访问的是假网址。
视图(view)
视图是用户看到并与之交互的界面。这是前端工作的主力部分。
模型(model)
模型是将实际开发中的业务规则和所涉及的数据格式模型化,应用于模型的代码只需写一次就可以被多个视图重用。在MVC的三个部件中,模型拥有最多的处理任务。一个模型能为多个视图提供数据。
控制器(controller)
控制器接受用户的输入并调用模型和视图去完成用户的需求。Controller处于管理角色,从视图接收请求并决定调用哪个模型构件去处理请求,然后再确定用哪个视图来显示模型处理返回的数据。
fnArr[i]()
输出 i 。使用 两种以上的方法var fnArr = [];
for (var i = 0; i < 10; i ++) {
fnArr[i] = function(){
return i;
};
}
console.log( fnArr[3]() ); //10
var fnArr = [];
for (var i = 0; i < 10; i ++) {
fnArr[i] = (function(i){
return function() {
return i;
}
})(i);
}
console.log( fnArr[3]() );//3
var fnArr = [];
for (var i = 0; i < 10; i ++) {
!function(i) {
fnArr[i] = function(){
return i;
};
}(i)
}
console.log( fnArr[3]() ); //3
var fnArr = [];
for (let i = 0; i < 10; i ++) {
fnArr[i] = function(){
return i;
};
}
console.log( fnArr[3]() );//3
var Car = (function(){
var speed = 0;
function setSpeed(s){
speed = s
}
...
return {
setSpeed: setSpeed,
...
}
})()
Car.setSpeed(30);
Car.getSpeed(); //30
Car.accelerate();
Car.getSpeed(); //40;
Car.decelerate();
Car.decelerate();
Car.getSpeed(); //20
Car.getStatus(); // 'running';
Car.decelerate();
Car.decelerate();
Car.getStatus(); //'stop';
//Car.speed; //error
var Car = (function(){
var speed = 0;
function setSpeed(s){
speed = s
}
function getSpeed() {
return speed
}
function accelerate() {
speed += 10
}
function decelerate() {
if(speed > 10){
speed -= 10
}
}
function getStatus() {
if(speed > 0){
return 'running'
}else{
return 'stop'
}
}
return {
setSpeed: setSpeed,
getSpeed: getSpeed,
accelerate: accelerate,
decelerate: decelerate,
getStatus: getStatus
}
})()
Car.setSpeed(30);
Car.getSpeed(); //30
Car.accelerate();
Car.getSpeed(); //40;
Car.decelerate();
Car.decelerate();
Car.getSpeed(); //20
Car.getStatus(); // 'running';
Car.decelerate();
Car.decelerate();
Car.getStatus(); //'stop';
//Car.speed; //error
var a = 1;
setTimeout(function(){
a = 2;
console.log(a);
}, 0);
var a ;
console.log(a);
a = 3;
console.log(a);
//输出结果:
//1
//3
//2
//因为 setTimeout() 函数会在本次所有代码全部执行完毕以后才会去执行。
//所以会先执行 setTimeout() 函数外部的 2 个 console.log(a),最后再执行 setTimeout() 函数。
var flag = true;
setTimeout(function(){
flag = false;
},0)
while(flag){}
console.log(flag);
// 声明 flag 并赋值为 true 之后,进行 while 循环,因为条件一直为 true,所以无限循环,不会退出。
// 因为无限循环,所以不会执行之后的 console.log(flag) 和 setTimeout()函数。
//所以没有输出,无结果。
for(var i=0;i<5;i++){
setTimeout(function(){
console.log('delayer:' + i );
}, 0);
console.log(i);
}
//输出: 0 1 2 3 4 5次delayer:5
for(var i=0;i<5;i++){
!function(i) {
setTimeout(function(){
console.log('delayer:' + i );
}, 0);
console.log(i);
}(i)
}
for(var i=0;i<5;i++){
setTimeout((function(i) {
return function() {
console.log('delayer:' + i );
}
})(i), 0);
console.log(i);
}
function getStyle(element) {
return element.getComputedStyle() ? window.getComputedStyle(element) : element.currentStyle }
let trueWidth = getStyle(element).width;
let trueHeight = getStyle(element).height;
//低版本IE
function getStyle(element,pseduoElement){
return element.currentStyle ? element.currentStyle : window.getComputedStyle(element,pseduoElement);
}
let trueWidth = getStyle(element).width;
let trueHeight = getStyle(element).height;
// 编码
encodeURI()
encodeURIComponent()
// 解码
decodeURI()
decodeURIComponent()
encodeURI方法不会对下列字符编码
ASCII字母
数字
~!@#$&*()=:/,;?+'
encodeURIComponent方法不会对下列字符编码
ASCII字母
数字
~!*()'
所以encodeURIComponent比encodeURI编码的范围更大。
实际例子来说,encodeURIComponent 会把 http://
编码成 http%3A%2F%2F
而 encodeURI 却不会。
如果你需要编码整个URL,然后需要使用这个URL,那么用encodeURI。
encodeURI("http://www.cnblogs.com/season-huang/some other thing"); //"http://www.cnblogs.com/season-huang/some%20other%20thing";
其中,空格被编码成了%20。但是如果你用了encodeURIComponent,那么结果变为
"http%3A%2F%2Fwww.cnblogs.com%2Fseason-huang%2Fsome%20other%20thing"
当你需要编码URL中的参数的时候,那么encodeURIComponent是最好方法。
var param = "http://www.cnblogs.com/season-huang/"; //param为参数
param = encodeURIComponent(param);
var url = "http://www.cnblogs.com?next=" + param;
console.log(url) //"http://www.cnblogs.com?next=http%3A%2F%2Fwww.cnblogs.com%2Fseason-huang%2F"
参数中的 "/" 可以编码,如果用encodeURI肯定要出问题,因为后面的/是需要编码的
function isAndroid(){
return /android/i.test(navigator.userAgent);
}
function isIphone(){
return /iphone/i.test(navigator.userAgent);
}
function isIpad(){
return /ipad/i.test(navigator.userAgent);
}
function isIOS(){
return /iphone|ipad/i.test(navigator.userAgent);
}
form
表单有什么作用?有哪些常用的input
标签,分别有什么作用?标签 | 功能 |
---|---|
<input type="text"> |
定义单行输入文本框 |
<input type="password"> |
定义密码字段 |
<input type="radio"> |
定义单选按钮,用name分组 |
<input type="checkbox"> |
定义多选按钮 |
<input type="submit"> |
定义提交表单数据至表单处理程序的按钮 |
<input type="button"> |
定义按钮 |
<input type="reset"> |
定义重置按钮 |
<input type="number"> |
用于应该包含数字值的输入字段 |
<input type="date"> |
用于应该包含日期的输入字段 |
<input type="color"> |
用于应该包含颜色的输入字段 |
post
和 get
方式的区别?get
把参数包含在 URL 中,post
通过 request body 传递参数。
get
比 post
更不安全,因为参数直接暴露在 URL 上,所以不能用来传递敏感信息。
传输给后台数据量很大,post
可以防止数据传输不完整
数据量小 get
需要向后台查询数据 get
传输数据给后台 post
input
里,name
有什么作用?name
属性规定input
元素的名称,达到区分多个表单的目的,从而防止了表单提交到后台程序之后出现混乱,也只有设置了name
属性的表单元素才能在提交表单时传递它们的值。
radio
如何 分组?通过 name
属性分组,eg(name="sex1"
的为一组,name="sex2"
的为一组):
<input type="radio" name="sex1" value="male">男
<input type="radio" name="sex1" value="female" >女
<input type="radio" name="sex2" value="male">男
<input type="radio" name="sex2" value="female" >女
placeholder
属性有什么作用?placeholder
属性能够在文本框里显示提示信息,提示信息会在输入字段时消失,在没有字段输入时显示。
type=hidden
隐藏域有什么作用? 举例说明form
<form action="提交到服务器地址" method="get">
...
...
</form>
action
:提交表单的地址
method
:提交表单使用的方法,get
或者post
input
type
属性来设置不同的 input
类型。text
<div class="username">
<label for="username">姓名</label>
<input id="username" type="text" name="username" placeholder="用户名">
</div>
password
<div class="password">
<label for="password">密码</label>
<input id="password" type="password" name="password" placeholder="请输入密码">
</div>
button
提交按钮,不会提交
<input type="buttom" value="按钮">
submit
提交按钮,会提交
<input type="submit" value="提交">
reset
重置输入按钮
<input type="reset" value="重置">
radio
单选,通过 name
属性分组
<div class="sex">
<label>性别</label>
<input type="radio" name="sex" value="male">男
<input type="radio" name="sex" value="female">女
</div>
checkbox
<div class="hobby">
<label for="hobby">爱好</label>
<input type="checkbox" name="hobby" value="dota">dota
<input type="checkbox" name="hobby" value="travel">旅游
<input type="checkbox" name="hobby" value="pet">宠物
</div>
file
<div class="file">
<input type="file" name="myfile" accept="image/png">
</div>
此例中image/png
意思是只能选择此格式的图片上传
hidden
<input type="hidden" name="..." value="...">
label
在介绍 input
元素时,label
元素已出现多次,eg:
<div class="username">
<label for="username">姓名</label>
<input id="username" type="text" name="username" placeholder="用户名">
</div>
label
元素为 input
元素定义标注,当鼠标选择该标签时,关联的元素控件会获得焦点,for
属性与关联元素的 id
属性要相同。
select
元素和嵌套的option
元素<div class="section">
<label for="car">My Car</label>
<select id="car" name="car">
<option value="TT">TT</option>
<option value="SAAB" selected>萨博</option>
<option value="GTR">GTR</option>
</select>
</div>
textarea
<textarea name="comment"></textarea>
<div id="parent">
<div id="child">text</div>
</div>
#child {
line-height: 200px;
}
<div id="parent">
<img src="img.png" alt="">
</div>
#parent {
line-height: 200px;
}
#parent img {
vertical-align: middle;
}
#parent:before {
content: '';
display: inline-block;
height: 100%;
vertical-align: middle;
}
注:该方法的重点在于 line-height
的高度等于块级元素的内容框高度(一般都是指: height 值)
line-height
的垂直居中不是纯粹的垂直居中,会有点差异,需要调节 vertical-align
.
padding
<div class="layout">
<span>Imagine there's no heaven.It's easy if you try.No hell below us.Above us only sky.</span>
</div>
.layout>span {
display: inline-block;
padding: 100px;
}
<div id="parent">
<div id="child">content</div>
</div>
#parent {
position: relative;
}
#child {
position: absolute;
/*top: 50%;
transform: translateY(-50%);*/
left: 0;
top: 0;
right: 0;
bottom: 0;
width: 50%;
height: 30%;
margin: auto;
}
vertical-align
实现居中<div class="layout">
<span class="layout1">content</span>
<span class="layout2">content</span>
</div>
.layout1 {
font-size: 100px;
vertical-align: middle;
}
.layout2 {
font-size: 20px;
vertical-align: middle;
}
table-cell
实现居中<div class="layout">Content</div>
.layout {
display: table-cell;
vertical-align: middle;
width: 150px;
height: 150px;
color: #fff;
background-color: red;
}
innerText
是一个可写属性,返回元素内包含的文本内容,忽略掉了 HTML 标签,在多层次的时候会按照元素由浅到深的顺序拼接其内容<div>
<p>
123
<span>456</span>
</p>
</div>
外层div
的innerText
返回内容是 "123456"
innerHTML
属性作用和innerText
类似,但是不是返回元素的文本内容,而是返回元素的 HTML 结构,包括 HTML 标签和文本内容,在写入的时候也会自动构建 DOM<div>
<p>
123
<span>456</span>
</p>
</div>
外层div
的innerHTML
返回内容是 "<p>123<span>456</span></p>"
Element.children
Element.children 属性返回一个 HTMLCollection 对象,包括当前元素节点的所有子元素。它是一个类似数组的动态对象(实时反映网页元素的变化)。如果当前元素没有子元素,则返回的对象包含零个成员。
Node.childNodes
childNodes属性返回一个NodeList集合,成员包括当前节点的所有子节点。注意,除了HTML元素节点,该属性返回的还包括Text节点和Comment节点。如果当前节点不包括任何子节点,则返回一个空的NodeList集合。由于NodeList对象是一个动态集合,一旦子节点发生变化,立刻会反映在返回结果之中。
var ulElementChildNodes = document.querySelector('ul').childNodes;
getElementById 方法返回匹配指定 ID 属性的元素节点。如果没有发现匹配的节点,则返回 null。这也是获取一个元素最快的方法。
var elem = document.getElementById("test");
getElementsByClassName方法返回一个类似数组的对象(HTMLCollection类型的对象),包括了所有class名字符合指定条件的元素(搜索范围包括本身),元素的变化实时反映在返回结果中。这个方法不仅可以在document对象上调用,也可以在任何元素节点上调用。
var elements = document.getElementsByClassName(names);
getElementsByClassName方法的参数,可以是多个空格分隔的class名字,返回同时具有这些节点的元素。
document.getElementsByClassName('red test');
getElementsByTagName方法返回所有指定标签的元素(搜索范围包括本身)。返回值是一个HTMLCollection对象,也就是说,搜索结果是一个动态集合,任何元素的变化都会实时反映在返回的集合中。这个方法不仅可以在document对象上调用,也可以在任何元素节点上调用。
var paras = document.getElementsByTagName("p");
getElementsByName方法用于选择拥有name属性的HTML元素,比如form、img、frame、embed和object,返回一个NodeList格式的对象,不会实时反映元素的变化。
// 假定有一个表单是<form name="x"></form>
var forms = document.getElementsByName("x");
forms[0].tagName // "FORM"
querySelector方法返回匹配指定的CSS选择器的元素节点。如果有多个节点满足匹配条件,则返回第一个匹配的节点。如果没有发现匹配的节点,则返回null。
var el1 = document.querySelector(".myclass");
var el2 = document.querySelector('#myParent > [ng-click]');
querySelectorAll方法返回匹配指定的CSS选择器的所有节点,返回的是NodeList类型的对象。NodeList对象不是动态集合,所以元素节点的变化无法实时反映在返回结果中。
elementList = document.querySelectorAll(selectors);
querySelectorAll方法的参数,可以是逗号分隔的多个CSS选择器,返回所有匹配其中一个选择器的元素。
var matches = document.querySelectorAll("div.note, div.alert");
上面代码返回class属性是note或alert的div元素。
elementFromPoint方法返回位于页面指定位置的元素。
var element = document.elementFromPoint(x, y);
上面代码中,elementFromPoint方法的参数x和y,分别是相对于当前窗口左上角的横坐标和纵坐标,单位是CSS像素。
elementFromPoint方法返回位于这个位置的DOM元素,如果该元素不可返回(比如文本框的滚动条),则返回它的父元素(比如文本框)。如果坐标值无意义(比如负值),则返回null。
var newDiv = document.createElement("div");
createElement方法的参数为元素的标签名,即元素节点的tagName属性。如果传入大写的标签名,会被转为小写。如果参数带有尖括号(即<和>)或者是null,会报错。
var newDiv = document.createElement("div");
var newContent = document.createTextNode("Hello");
上面代码新建一个div节点和一个文本节点
var docFragment = document.createDocumentFragment();
DocumentFragment对象是一个存在于内存的DOM片段,但是不属于当前文档,常常用来生成较复杂的DOM结构,然后插入当前文档。这样做的好处在于,因为DocumentFragment不属于当前文档,对它的任何改动,都不会引发网页的重新渲染,比直接修改当前文档的DOM有更好的性能表现。
var node = document.getElementById("div1");
node.setAttribute("my_attrib", "newVal");
node.removeAttribute('id');
var newDiv = document.createElement("div");
var newContent = document.createTextNode("Hello");
newDiv.appendChild(newContent);
var newDiv = document.createElement("div");
var newContent = document.createTextNode("Hello");
newDiv.insertBefore(newContent, newDiv.firstChild);
newDiv.replaceChild(newElement, oldElement);
parentNode.removeChild(childNode);
add( String [, String] )
添加指定的类值。如果这些类已经存在于元素的属性中,那么它们将被忽略。
remove( String [,String] )
删除指定的类值。
item ( Number )
按集合中的索引返回类值。
toggle ( String [, force] )
当只有一个参数时:切换 class value; 即如果类存在,则删除它并返回false,如果不存在,则添加它并返回true。
当存在第二个参数时:如果第二个参数的计算结果为true,则添加指定的类值,如果计算结果为false,则删除它
contains( String )
检查元素的类属性中是否存在指定的类值。
// div是具有class =“foo bar”的<div>元素的对象引用
div.classList.remove("foo");
div.classList.add("anotherclass");
// 如果visible被设置则删除它,否则添加它
div.classList.toggle("visible");
// 添加/删除 visible,取决于测试条件,i小于10
div.classList.toggle("visible", i < 10);
alert(div.classList.contains("foo"));
//添加或删除多个类
div.classList.add("foo","bar");
div.classList.remove("foo", "bar");
<div class="mod-tabs">
<ul>
<li>list1</li>
<li>list2</li>
<li>list3</li>
</ul>
<button class="btn">点我</button>
</div>
//选中所有的 li 元素
document.querySelectorAll('li')
document.getElementsByTagName('li')
//选中 btn 元素
document.querySelector('.btn')
document.getElementsByClassName('btn')
vim a.md
初始进入编辑器命令模式vim
和 a.md
之间有一个空格)i
进入编辑模式esc
进入命令模式:wq
保存退出:q!
不保存强制退出按键 | 功能 |
---|---|
h或← | 光标左移 |
l或→ | 光标右移 |
k或↑ | 光标上移 |
j或↓ | 光标下移 |
gg | 快速定位到文本开头 |
G(shift+g) | 快速定位到文本最后一段 |
0或home | 快速定位到当前段首 |
$或end | 快速定位到当前段首 |
Ctrl+f | 向下翻一页 |
Ctrl+b | 向上翻一页 |
Ctrl+d | 向下翻半页 |
Ctrl+u | 向上翻一页 |
/string | 查找文本中光标位置下方的string字符串,如要查找kabc则直接输入/kabc即可 |
?string | 查找文本中光标位置上方的string字符串,如要查找kabc则直接输入?kabc即可 |
yy | 复制光标所在的段落 |
y0 | 复制光标位置到段首的所有字符 |
y$ | 复制光标位置到段尾的所有字符 |
nyy | 从光标位置向下复制n段,包含光标所在的段落 |
ygg | 复制光标位置所在段落到文本开头的所有内容 |
yG | 复制光标位置所在段落到文本结尾的所有内容 |
p | 将复制的内容粘贴为光标所在段落的下一段 |
P | 将复制的内容粘贴为光标所在段落的上一段 |
dd | 删除光标所在的段落 |
d0 | 删除光标位置到段首的所有字符 |
d$ | 删除光标位置到段尾的所有字符 |
dgg | 删除光标位置所在段落到文本开头的所有内容 |
dG | 删除光标位置所在段落到文本结尾的所有内容 |
ndd | 从光标位置向下删除n段,包含光标所在的段落 |
u | 撤销上一个操作 |
Ctrl+r | 重复上一个操作 |
:w | 保存数据 |
:w! | 保存时强制写入数据,不管文件是否为只读文件 |
) | 移至下一个句子(sentence)首 (sentence 是以 . ! ? 为区格) |
( | 移至上一个句子(sentence)首 |
} | 移至下一个段落(paragraph)首 (paragraph 是以空白行为区格) |
{ | 移至上一个段落(paragraph)首 |
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.