Javascript中的函数表达式

Javascript中的函数表达式

  • 函数声明 有提升 而函数表达式没有,因此不应该通过if…else来声明函数
     
     
        if (condition) {
            function sayHi() {}
        } else {
            function sayHi() {}
        }
       
  • 在递归函数中使用arguments.callee可以避免因函数名改变产生的错误。
     
     
        function factorial(num) {
            if (num 
                return 1;
            } else {
                return num * arguments.callee(num - 1);
            }
        }
       
  • 闭包是指函数中定义的函数,闭包的作用域链中包含父函数的执行环境(变量对象),所以即使父函数退出,如果闭包仍然被引用,那么父函数的变量对象就一直存在于内存中。所以,过度的使用闭包会导致内存占用过多
  • 闭包的另外一个副作用是闭包只能取得父函数中变量的最后一个值,例如:
     
     
        function createFunctions() {
            var result = new Array();
            for(var i = 0; i < 10; i++) {
                result[i] = function() {
                    return i;
                }
            }
            return result;
        }
       

    调用result中的每个函数都会返回10

  • 闭包如果是匿名函数,则该函数中的this指向全局对象
  • 可以用定义一个立即执行函数来模仿块级作用域:
     
     
            (function(){
            //块级作用域                                   
            })();                                        
       

Javascript中的对象

属性的类型

1.1 数据类属性

数据类属性的属性——特性为:

  • [[Configurable]]: 默认为true。表示能否通过delete删除属性,能否修改属性的特性。
  • [[Enumerable]]: 默认为true。表示在用for-in迭代对象时,能否迭代出该属性。
  • [[Writable]]: 默认为true。表示能否修改属性的值。
  • [[Value]]: 默认为undefined。保存属性的值。

1.2 访问器类属性

访问器类属性的特性为:

  • [[Configurable]]: 默认为true。表示能否通过delete删除属性,能否修改属性的特性。
  • [[Enumerable]]: 默认为true。表示在用for-in迭代对象时,能否迭代出该属性。
  • [[Get]]: 默认为undefined。读取属性时调用的函数。
  • [[Set]]: 默认为undefined。写入属性时调用的函数。

使用访问器类型的属性的常用方法是写入该属性时往往会导致其他属性也跟着变化。

 

1.3 对特性的操作方法:

Object.defineProperty(Object, propertyName, {attributes}): 设置属性的特性。
Object.defineProperties(Object, {propertyName: {attributes},}): 设置多个属性的特性。
Object.getOwnPropertyDescriptor(Object, propertyName);

 

创建对象的方法

2.1 工厂模式

 
 
function createPerson(name, age, job) {
    var o = new Object();
    o.name = name;
    o.age = age;
    o.job = job;
    o.sayName = function() {
        alert(this.name);
    }
    return o;
}
var sen = createPerson('sen', 19, 'programer');

缺点:无法识别一个对象属于哪一个类

 
 
alert(sen instanceof createPerson) // false

2.2 构造函数模式

 
 
function Person(name, age, job) {
    this.name = name;
    this.age = age;
    this.job = job;
    this.sayName = function() {
        alert(this.name);
    }
}
var sen = new Person("sen", 19, "programer");
alert(sen instanceof Person) // true
alert(sen.constructor === Person) // true

缺点:每个对象都会有独立的函数定义

 
 
var sen1 = new Person("sen1", 19, "player");
alert(sen1.sayName == sen.sayName) // false

2.3 原型模式

 
 
function Person() {
}
Person.prototype.name = "sen";
Person.prototype.age = "19";
Person.prototype.job = "programer";
Person.prototype.sayName = fucntion() {
    alert(this.name);
}
var sen = new Person();
Person.prototype.constructor === Person // true
Person.prototype.isPrototypeOf(sen) // true
Object.getPrototypeOf(sen) === Person.prototype // true
sen.hasOwnProperty("name") // false
"name" in sen // true

判断属性是不是在原型对象中:

 
 
!sen.hasOwnProperty("name") && ("name" in sen)

原型模式更简洁的写法:

 
 
function Person(){};
Person.prototype = {
    constructor = Person,
    name: "sen",
    age: 19,
    job: "programer",
    sayName: function() {
        alert(this.name);
    }
}
Object.defineProperty(Person.prototype, {
    enumerable: false,
    value: Person
});

缺点:

1. 省略了传递初始化参数
2. 如果原型中的属性为引用类型,则所有对象会共用这个引用类型

2.4 组合使用构造模式和原型模式

 
 
function Person(name, age, job) {
    this.name = name;
    this.age = age;
    this.job = job;
}
Person.prototype.sayName = function() {
    alert(this.name)
}

缺点: 构造函数和原型是独立的

2.5 动态原型模式

 
 
function Person(name, age, job) {
    this.name = name;
    this.age = age;
    this.job = job;
    if (typeof this.sayName !== "function") {
        Person.prototype.sayName = function() {
            alert(this.name);
        };
    }
}

2.6 寄生构造函数模式

 
 
function Person(name, age, job) {
    var o = new Object();
    o.name = name;
    o.age = age;
    o.job = job;
    o.sayName = function() {
        alert(this.name);
    }
    return o;
}
var sen = new Person('sen', 19, 'programer');

寄生构造函数模式一般用于创建特殊的引用类型。例如,创建一个包含toPipedString方法的数组类型。

 
 
function SpecialArray() {
    var arr = new Array();
    arr.push.apply(arr, arguments);
    arr.toPipedString = function() {
        return this.join(" | ");
    }
    return arr;
}
var colors = new SpecialArray("red", "black");
alert(colors.toPipedString());

缺点和工厂模式一样,都无法被instanceof识别

2.7 稳妥构造函数模式

与寄生构造函数类似,区别在于:

  • 不使用this给类添加公共属性
  • 创建对象时不使用new关键字
 
 
  1. function Person(name, age, job) {
  2. var o = new Object();
  3. o.sayName = function() {
  4. alert(name);
  5. }
  6. return o;
  7. }
  8. var sen = Person('sen', 19, 'programer');

缺点和工厂模式一样,都无法被instanceof识别

继承

3.1 原型链

 
 
function SuperType() {
    this.property = true;
}
SuperType.prototype.getSuperValue = function() {
    return this.property;
}
function SubType() {
    this.subProperty = false;
}
SubType.prototype = new SuperType();
SubType.prototype.getSubValue = function() {
    return this.subProperty;
}
var obj = new SubType();
alert(obj instanceof SubType) // true
alert(obj instanceof SuperType) // true
alert(obj instanceof Object) // true

缺点:

  • SuperType中的属性如果为引用类型,所以的子类都会共用该属性
  • 创建子类时,如果给父类传递参数,会影响其他的子类

3.2 构造函数继承继承

 
 
function SuperType() {
    this.colors = ['black', 'red'];
}
function SubType() {
    SuperType.call(this);
}

缺点:函数无法复用

3.3 组合继承

 
 
function SuperType(name) {
    this.name = name;
    this.colors = ['black', 'red'];
}
SuperType.prototype.sayName = function() {
    return this.name;
}
function SubType(name) {
    SuperType.call(this, name);
}
SubType.prototype = new SuperType();

3.4 原型式继承

 
 
var person = {
    name: "sen"
}
var newPerson = Object.create(person, {name: {
    value: "yang"
}});

缺点: 原型式继承仅仅是对父类做了一个浅拷贝,并加入了子类自己的属性。所以问题和原型链相同,父类中的引用类型属性会被所有子类共用。

3.5 寄生式继承

 
 
function createAnother(obj) {
    var clone = Object.create(obj);
        clone.sayHi = function() {
        alert('hi');
    }
    return clone;
}

缺点: 函数不能复用

3.6 寄生组合式继承 (常用)

 
 
function inheritPrototype(subType, superType) {
    var prototype = Object.create(superType.prototype);
    prototype.constructor = subType;
    subType.prototype = prototype;
}
function SuperType(name) {
    this.name = name;
    this.colors = ['red', 'black'];
}
SuperType.prototype.sayName = function() {
    alert(this.name);
}
function SubType(name) {
    SuperType.call(this, name);
    this.age = age;
}
inheritPrototype(SubType, SuperType);

Javascript中的单体内置对象

Global

  1. encodeURI() encodeURIComponent(): 用utf-8编码替换URI中的无效字符,区别在于encodeURI并不对属于URI的特殊字符进行编码,如:// #?等
  2. eval(“var msg=’hello world'”); alert(msg);
  3. Global对象的属性:
    • undefined
    • NaN
    • Infinity
    • Object
    • Array
    • Function
    • Boolean
    • String
    • Number
    • Date
    • RegExp
    • Error
    • EvalError
    • RangeError
    • ReferenceError
    • SyntaxError
    • TypeError
    • URIError
  4. 可通过window对象来访问global对象的变量和函数
  5. var global = function(){return this;}();

Math

  • Math对象的属性:
    • Math.E
    • Math.LN10
    • Math.LN2
    • Math.LOG2E
    • Math.LOG10E
    • Math.PI
    • Math.SQRT1_2
    • Math.SQRT2
  • Math.min([1, 2, 3]) Math.max([1, 2, 3])
  • Math.ceil()
  • Math.floor()
  • Math.round()
  • Math.random():  [0-1)
  • Math.abs()
  • Math.exp()
  • Math.log()
  • Math.pow(num, power)
  • Math.sqrt()
  • Math.acos(x)
  • Math.asin(x)
  • Math.atan(x)
  • Math.atan2(y, x)
  • Math.cos(x)
  • Math.sin(x)
  • Math.tan(x)

Javascript中的基本包装类型

当读取一个基本类型(Boolean、String、Number)的值时,后台对创建一个对应的基本包装类型,从而让我们可以调用一些方法来操作这些数据。

基本包装类型与引用类型的区别:

  • 生存期。自动创建的包装类型只存在于一行代码存在的瞬间。不能在运行时为基本类型添加属性和方法。

Number类型常用的方法

  • toString()
  • toFixed(2) //小数点后两位
  • toExponential()
  • toPrecision(3)

String类型常用的属性和方法

  • length: 返回字符串的长度
  • charAt(2) charCodeAt(2): 返回字符串中第三个字符/编码
  • concat(“xxx”) 或者 + “xxx”: 字符串拼接
  • slice(start, end) subString(start, end) subStr(start, number): 字符串切片
    当start为负值时,slice和subStr会把它与字符串长度相加得到新的start;而subString则会将其转化为0
    当end/number为负值时,slice会把它与字符串长度相加得到新的end,subStr和subString会将其转化为0
  • indexOf(‘d’, start) 和lastIndexOf(‘d’, start): 从start位置开始向左(右)查找’d’在字符串中的位置
  • trim(): 返回删除字符串左右的空格的新字符串
  • trimLeft() trimRight(): 返回删除字符串左(右)的空格的新字符串
  • toLowerCase() toLocaleLowerCase() toUpperCase() toLocaleUpperCase()
  • match(pattern/RegExp): 返回的数组与RegExp.exec相同
  • search(pattern/RegExp): 返回匹配到的位置
  • replace(old, new):
    如果old为字符串时,仅替换该字符串;如果Old是带’g’标志的pattern时,会替换所有匹配的字符串
    new字符串中可以是下列特殊序列:
    $$: $
    $&: 等价于RegExp.lastMatch
    $’: RegExp.leftContext
    $`: RegExp.rightContext
    $n $nn: 第n个捕获组匹配到的字符串
    new可以是一个函数:function(match, pos, orignialText){return string}
  • var array = “string”.split(‘string/pattern’, number)

Javascript中的函数

函数的定义

  1.  var foo = fucntion(a, b) {}; //函数表达式
  2. function foo(a, b) {}; //函数声明
  3. var foo = new Function(“a”, “b”, “return false”); //不推荐

对于函数声明,可以在声明之前调用该函数;而对于函数表达式,不可以在表达式之前调用该函数。

函数的属性

  • this: 引用的是函数执行的环境对象,全局作用域中的this引用的是window对象
  • arguments: 保存函数参数的数组
  • arguments.callee: 指向该函数的指针
  • caller: 函数的调用者
  • length: 函数希望接收到的命名参数的个数

函数的方法

  • call(obj, arg1, arg2…)  //设置函数的运行环境(改变this的值)
  • apply(obj, [arg1, arg2]) //设置函数的运行环境(改变this的值)
  • bind(obj) //绑定函数的运行环境

Javascript中的正则表达式

1. RegExp类型的创建

var expression = /pattern/flags; 或者

var expression = new RegExp(“pattern”, “flags”);

用创建对象的方式来创建RegExp是需要对”pattern”中的\进行转义,例如:

/\[bc\]at/  => “\\[bc\\]at”

flags 可以是:

  • g :全局匹配
  • i :忽略大小写
  • m :多行模式

2. RegExp实例的属性

  • global: true or false, 表示标志位’g’是否被设置
  • ignoreCase: true or false
  • multiline: true or false
  • lastIndex: 下一次搜索开始的字符位置
  • source: pattern的字符串表示

3. RegExp实例的方法

  • exec(“target_string”)
    • ret.index: 匹配到的字符串的起始位置
    • ret.input: “target_string”
    • ret[0]: 匹配到的字符串
    • ret[1 – n]: 匹配组1-n匹配到的字符串
  • test(“target_string”)
    • true: 匹配到字符串
    • false: 没有匹配到字符串
  • exec和test只有在设置了’g’标志位的情况下才回去更新exp.lastIndex

4. RegExp 构造函数属性

  • input ($_): 最近一次匹配成功的源字符串
  • lastMatch($&): 最近一次的匹配项
  • lastParen($+): 最近一次匹配的捕获组
  • leftContext($`): input字符串中匹配项之前的字符串
  • rightContext($*): input字符串中匹配项之后的字符串
  • $1-9: 第1-9个匹配组

附录:

正则表达式元字符表

Metacharacter Description
^ Matches the starting position within the string. In line-based tools, it matches the starting position of any line.
. Matches any single character (many applications exclude newlines, and exactly which characters are considered newlines is flavor-, character-encoding-, and platform-specific, but it is safe to assume that the line feed character is included). Within POSIX bracket expressions, the dot character matches a literal dot. For example, a.c matches “abc”, etc., but [a.c] matches only “a”, “.”, or “c”.
[ ] A bracket expression. Matches a single character that is contained within the brackets. For example, [abc] matches “a”, “b”, or “c”. [a-z] specifies a range which matches any lowercase letter from “a” to “z”. These forms can be mixed: [abcx-z] matches “a”, “b”, “c”, “x”, “y”, or “z”, as does [a-cx-z].The - character is treated as a literal character if it is the last or the first (after the ^, if present) character within the brackets: [abc-], [-abc]. Note that backslash escapes are not allowed. The ] character can be included in a bracket expression if it is the first (after the ^) character: []abc].
[^ ] Matches a single character that is not contained within the brackets. For example, [^abc] matches any character other than “a”, “b”, or “c”. [^a-z] matches any single character that is not a lowercase letter from “a” to “z”. Likewise, literal characters and ranges can be mixed.
$ Matches the ending position of the string or the position just before a string-ending newline. In line-based tools, it matches the ending position of any line.
( ) Defines a marked subexpression. The string matched within the parentheses can be recalled later (see the next entry, \n). A marked subexpression is also called a block or capturing group. BRE mode requires \( \).
\n Matches what the nth marked subexpression matched, where n is a digit from 1 to 9. This construct is vaguely defined in the POSIX.2 standard. Some tools allow referencing more than nine capturing groups.
* Matches the preceding element zero or more times. For example, ab*c matches “ac”, “abc”, “abbbc”, etc. [xyz]* matches “”, “x”, “y”, “z”, “zx”, “zyx”, “xyzzy”, and so on. (ab)* matches “”, “ab”, “abab”, “ababab”, and so on.
{m,n} Matches the preceding element at least m and not more than n times. For example, a{3,5} matches only “aaa”, “aaaa”, and “aaaaa”. This is not found in a few older instances of regexes. BRE mode requires \{m,n\}.

 

Metacharacter Description
? Matches the preceding element zero or one time. For example, ab?c matches only “ac” or “abc”.
+ Matches the preceding element one or more times. For example, ab+c matches “abc”, “abbc”, “abbbc”, and so on, but not “ac”.
| The choice (also known as alternation or set union) operator matches either the expression before or the expression after the operator. For example, abc|def matches “abc” or “def”.

 

POSIX Non-standard Perl/Tcl Vim Java ASCII Description
[:ascii:][30] \p{ASCII} [\x00-\x7F] ASCII characters
[:alnum:] \p{Alnum} [A-Za-z0-9] Alphanumeric characters
[:word:][citation needed] \w \w \w [A-Za-z0-9_] Alphanumeric characters plus “_”
\W \W \W [^A-Za-z0-9_] Non-word characters
[:alpha:] \a \p{Alpha} [A-Za-z] Alphabetic characters
[:blank:] \s \p{Blank} [ [[\t]]] Space and tab
\b \< \> \b (?<=\W)(?=\w)|(?<=\w)(?=\W) Word boundaries
\B (?<=\W)(?=\W)|(?<=\w)(?=\w) Non-word boundaries
[:cntrl:] \p{Cntrl} [\x00-\x1F\x7F] Control characters
[:digit:] \d \d \p{Digit} or \d [0-9] Digits
\D \D \D [^0-9] Non-digits
[:graph:] \p{Graph} [\x21-\x7E] Visible characters
[:lower:] \l \p{Lower} [a-z] Lowercase letters
[:print:] \p \p{Print} [\x20-\x7E] Visible characters and the space character
[:punct:] \p{Punct} [][!"#$%&'()*+,./:;<=>?@\^_`{|}~-] Punctuation characters
[:space:] \s \_s \p{Space} or \s [ \t\r\n\v\f] Whitespace characters
\S \S \S [^ \t\r\n\v\f] Non-whitespace characters
[:upper:] \u \p{Upper} [A-Z] Uppercase letters
[:xdigit:] \x \p{XDigit} [A-Fa-f0-9] Hexadecimal digits

 

常用分组语法
分类 代码/语法 说明
捕获 (exp) 匹配exp,并捕获文本到自动命名的组里
(?<name>exp) 匹配exp,并捕获文本到名称为name的组里,也可以写成(?’name’exp)
(?:exp) 匹配exp,不捕获匹配的文本,也不给此分组分配组号
零宽断言 (?=exp) 匹配exp前面的位置
(?<=exp) 匹配exp后面的位置
(?!exp) 匹配后面跟的不是exp的位置
(?<!exp) 匹配前面不是exp的位置
注释 (?#comment) 这种类型的分组不对正则表达式的处理产生任何影响,用于提供注释让人阅读

 

常用的反义代码
代码/语法 说明
\W 匹配任意不是字母,数字,下划线,汉字的字符
\S 匹配任意不是空白符的字符
\D 匹配任意非数字的字符
\B 匹配不是单词开头或结束的位置
[^x] 匹配除了x以外的任意字符
[^aeiou] 匹配除了aeiou这几个字母以外的任意字符

 

 

 

Javascript中的Date

1. Date类型的创建

  • var date = new Date() //获取当前时间
  • var date = new Date(ms) //根据Unix时间戳来创建Date对象
  • var date = new Date(Date.parse(“string”)) //string为日期时间组成的字符串,符合要求的字符串格式包括:
    • “m/d/y”
    • “January 12, 2004”
    • “Tue May 25 2004 00:00:00 GMT-0700”
    • YYYY-MM-DDTHH:mm:ss.sssZ”
  • var date = new Date(Date.UTC()) // Date.UTC的参数为年、月、日、小时、分钟、秒、毫秒

2. Date类型的操作

var date = new Date();

  • Date.now() 或者+new Date()获取当前的时间戳, “+”操作符可获取Date对象的时间戳
  • date.toDateString(); // “Thu May 17 2018”
  • date.toTimeString(); // “14:37:29 GMT+0800 (CST)”
  • date.toLocaleDateString(); // “2018/5/17”
  • date.toLocaleTimeString(); // “下午2:37:29”
  • date.toUTCString(); // “Thu, 17 May 2018 06:37:29 GMT”
  • date.toLocaleString(); // “2018/5/17 下午2:37:29”
  • date.getTime(); // 1526539049298
  • +date; // 1526539049298
  • date.setTime(1526539049300);
  • date.getFullYear(); // 2018
  • date.getUTCFullYear(); // 2018
  • date.getMonth(); // 0-11
  • date.getUTCMonth(); // 0-11
  • date.getDate(); //1-31
  • date.getUTCDate(); // 1-31
  • date.getDay(); // 0-6 0表示周日
  • date.getUTCDay(); // 0-6 0表示周日
  • date.getHours(); // 0-23
  • date.getUTCHours(); // 0-23
  • date.getMinutes(); // 0-59
  • date.getUTCMinutes(); // 0-59
  • date.getSeconds(); // 0-59
  • date.getUTCSeconds(); // 0-59
  • date.getMilliseconds(); // 0-999
  • date.getUTCMilliseconds(); // 0-999
  • date.getTimezoneOffset(); // -480

[转]A Complete Guide to Flexbox

Background

The Flexbox Layout (Flexible Box) module (currently a W3C Last Call Working Draft) aims at providing a more efficient way to lay out, align and distribute space among items in a container, even when their size is unknown and/or dynamic (thus the word “flex”).

The main idea behind the flex layout is to give the container the ability to alter its items’ width/height (and order) to best fill the available space (mostly to accommodate to all kind of display devices and screen sizes). A flex container expands items to fill available free space, or shrinks them to prevent overflow.

Most importantly, the flexbox layout is direction-agnostic as opposed to the regular layouts (block which is vertically-based and inline which is horizontally-based). While those work well for pages, they lack flexibility (no pun intended) to support large or complex applications (especially when it comes to orientation changing, resizing, stretching, shrinking, etc.).

Note: Flexbox layout is most appropriate to the components of an application, and small-scale layouts, while the Grid layout is intended for larger scale layouts.

Basics and Terminology

Properties for the Parent

display

This defines a flex container; inline or block depending on the given value. It enables a flex context for all its direct children.

.container {
  display: flex; /* or inline-flex */
}

Note that CSS columns have no effect on a flex container.

#flex-direction


This establishes the main-axis, thus defining the direction flex items are placed in the flex container. Flexbox is (aside from optional wrapping) a single-direction layout concept. Think of flex items as primarily laying out either in horizontal rows or vertical columns.

.container {
  flex-direction: row | row-reverse | column | column-reverse;
}
  • row (default): left to right in ltr; right to left in rtl
  • row-reverse: right to left in ltr; left to right in rtl
  • column: same as row but top to bottom
  • column-reverse: same as row-reverse but bottom to top

#flex-wrap

By default, flex items will all try to fit onto one line. You can change that and allow the items to wrap as needed with this property.

.container{
  flex-wrap: nowrap | wrap | wrap-reverse;
}
  • nowrap (default): all flex items will be on one line
  • wrap: flex items will wrap onto multiple lines, from top to bottom.
  • wrap-reverse: flex items will wrap onto multiple lines from bottom to top.

There are some visual demos of flex-wrap here.

#flex-flow (Applies to: parent flex container element)

This is a shorthand flex-direction and flex-wrap properties, which together define the flex container’s main and cross axes. Default is row nowrap.

flex-flow: <‘flex-direction’> || <‘flex-wrap’>

#justify-content


This defines the alignment along the main axis. It helps distribute extra free space left over when either all the flex items on a line are inflexible, or are flexible but have reached their maximum size. It also exerts some control over the alignment of items when they overflow the line.

.container {
  justify-content: flex-start | flex-end | center | space-between | space-around | space-evenly;
}
  • flex-start (default): items are packed toward the start line
  • flex-end: items are packed toward to end line
  • center: items are centered along the line
  • space-between: items are evenly distributed in the line; first item is on the start line, last item on the end line
  • space-around: items are evenly distributed in the line with equal space around them. Note that visually the spaces aren’t equal, since all the items have equal space on both sides. The first item will have one unit of space against the container edge, but two units of space between the next item because that next item has its own spacing that applies.
  • space-evenly: items are distributed so that the spacing between any two items (and the space to the edges) is equal.

#align-items


This defines the default behaviour for how flex items are laid out along the cross axis on the current line. Think of it as the justify-content version for the cross-axis (perpendicular to the main-axis).

.container {
  align-items: flex-start | flex-end | center | baseline | stretch;
}
  • flex-start: cross-start margin edge of the items is placed on the cross-start line
  • flex-end: cross-end margin edge of the items is placed on the cross-end line
  • center: items are centered in the cross-axis
  • baseline: items are aligned such as their baselines align
  • stretch (default): stretch to fill the container (still respect min-width/max-width)

#align-content


This aligns a flex container’s lines within when there is extra space in the cross-axis, similar to how justify-content aligns individual items within the main-axis.

Note: this property has no effect when there is only one line of flex items.

.container {
  align-content: flex-start | flex-end | center | space-between | space-around | stretch;
}
  • flex-start: lines packed to the start of the container
  • flex-end: lines packed to the end of the container
  • center: lines packed to the center of the container
  • space-between: lines evenly distributed; the first line is at the start of the container while the last one is at the end
  • space-around: lines evenly distributed with equal space around each line
  • stretch (default): lines stretch to take up the remaining space

Properties for the Children

order


By default, flex items are laid out in the source order. However, the order property controls the order in which they appear in the flex container.

.item {
  order: <integer>; /* default is 0 */
}

#flex-grow


This defines the ability for a flex item to grow if necessary. It accepts a unitless value that serves as a proportion. It dictates what amount of the available space inside the flex container the item should take up.

If all items have flex-grow set to 1, the remaining space in the container will be distributed equally to all children. If one of the children has a value of 2, the remaining space would take up twice as much space as the others (or it will try to, at least).

.item {
  flex-grow: <number>; /* default 0 */
}

Negative numbers are invalid.

#flex-shrink

This defines the ability for a flex item to shrink if necessary.

.item {
  flex-shrink: <number>; /* default 1 */
}

Negative numbers are invalid.

#flex-basis

This defines the default size of an element before the remaining space is distributed. It can be a length (e.g. 20%, 5rem, etc.) or a keyword. The auto keyword means “look at my width or height property” (which was temporarily done by the main-size keyword until deprecated). The content keyword means “size it based on the item’s content” – this keyword isn’t well supported yet, so it’s hard to test and harder to know what its brethren max-content, min-content, and fit-content do.

.item {
  flex-basis: <length> | auto; /* default auto */
}

If set to 0, the extra space around content isn’t factored in. If set to auto, the extra space is distributed based on its flex-grow value. See this graphic.

#flex

This is the shorthand for flex-grow,flex-shrink and flex-basis combined. The second and third parameters (flex-shrink and flex-basis) are optional. Default is 0 1 auto.

.item {
  flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
}

It is recommended that you use this shorthand property rather than set the individual properties. The short hand sets the other values intelligently.

#align-self


This allows the default alignment (or the one specified by align-items) to be overridden for individual flex items.

Please see the align-items explanation to understand the available values.

.item {
  align-self: auto | flex-start | flex-end | center | baseline | stretch;
}

Note that float, clear and vertical-align have no effect on a flex item.

Browser Support

Broken up by “version” of flexbox:

  • (new) means the recent syntax from the specification (e.g. display: flex;)
  • (tweener) means an odd unofficial syntax from 2011 (e.g. display: flexbox;)
  • (old) means the old syntax from 2009 (e.g. display: box;)
Chrome Safari Firefox Opera IE Android iOS
20- (old)
21+ (new)
3.1+ (old)
6.1+ (new)
2-21 (old)
22+ (new)
12.1+ (new) 10 (tweener)
11+ (new)
2.1+ (old)
4.4+ (new)
3.2+ (old)
7.1+ (new)

Blackberry browser 10+ supports the new syntax.

For more informations about how to mix syntaxes in order to get the best browser support, please refer to this article (CSS-Tricks) or this article (DevOpera).

阅读原文

操作系统级虚拟化概述

操作系统级虚拟化

KVM、XEN等虚拟化技术允许各个虚拟机拥有自己独立的操作系统。与KVM、XEN等虚拟化技术不同,所谓操作系统级虚拟化,也被称作容器化,是操作系统自身的一个特性,它允许多个相互隔离的用户空间实例的存在。这些用户空间实例也被称作为容器。普通的进程可以看到计算机的所有资源而容器中的进程只能看到分配给该容器的资源。通俗来讲,操作系统级虚拟化将操作系统所管理的计算机资源,包括进程、文件、设备、网络等分组,然后交给不同的容器使用。容器中运行的进程只能看到分配给该容器的资源。从而达到隔离与虚拟化的目的。

实现操作系统虚拟化需要用到Namespace及cgroups技术。

命名空间(Namespace)

在编程语言中,引入命名空间的概念是为了重用变量名或者服务例程名。在不同的命名空间中使用同一个变量名而不会产生冲突。Linux系统引入命名空间也有类似的作用。例如,在没有操作系统级虚拟化的Linux系统中,用户态进程从1开始编号(PID)。引入操作系统虚拟化之后,不同容器有着不同的PID命名空间,每个容器中的进程都可以从1开始编号而不产生冲突。

目前,Linux中的命名空间有6种类型,分别对应操作系统管理的6种资源:

  • 挂载点(mount point) CLONE_NEWNS
  • 进程(pid) CLONE_NEWPID
  • 网络(net) CLONE_NEWNET
  • 进程间通信(ipc) CLONE_NEWIPC
  • 主机名(uts) CLONE_NEWUTS
  • 用户(uid) CLONW_NEWUSER

将来还会引入时间、设备等对应的namespace.

Linux 2.4.19版本引入了第一个命名空间——挂载点,因为那时还没有其他类型的命名空间,所以clone系统调用中引入的flag就叫做CLONE_NEWNS

与命名空间相关的三个系统调用(system calls)

下面3个系统调用用来操作命名空间:

  • clone() —— 用来创建新的进程及新的命名空间,新的进程会被放到新的命名空间中
  • unshare() —— 创建新的命名空间但并不创建新的子进程,之后创建的子进程会被放到新创建的命名空间中去
  • setns() —— 将进程加入到已经存在的命名空间中

注意:这3个系统调用都不会改变调用进程(calling process)的pid命名空间,而是会影响其子进程的pid命名空间

命名空间本身并没用名字(囧),不同的命名空间用不同的inode号来标识,这也符合Linux用文件一统天下的惯例。可以在proc文件系统中查看一个进程所属的命名空间,例如,查看PID为4123的进程所属的命名空间:

kelvin@desktop:~$ ls -l /proc/4123/ns/
总用量 0
lrwxrwxrwx 1 kelvin kelvin 0 1226 16:28 cgroup -> cgroup:[4026531835]
lrwxrwxrwx 1 kelvin kelvin 0 1226 16:28 ipc -> ipc:[4026531839]
lrwxrwxrwx 1 kelvin kelvin 0 1226 16:28 mnt -> mnt:[4026531840]
lrwxrwxrwx 1 kelvin kelvin 0 1226 16:28 net -> net:[4026531963]
lrwxrwxrwx 1 kelvin kelvin 0 1226 16:28 pid -> pid:[4026531836]
lrwxrwxrwx 1 kelvin kelvin 0 1226 16:28 user -> user:[4026531837]
lrwxrwxrwx 1 kelvin kelvin 0 1226 16:28 uts -> uts:[4026531838]

下面的代码演示了如何利用上述3个系统调用来操作进程的命名空间:

#define _GNU_SOURCE
#include <sys/types.h>
#include <sys/wait.h>
#include <sched.h>
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#define STACK_SIZE (10 * 1024 * 1024)

char child_stack[STACK_SIZE];

int child_main(void* args) {
    pid_t child_pid = getpid();
    printf("I'm child process and my pid is %d \n", child_pid);
    // 子进程会被放到clone系统调用新创建的pid命名空间中, 所以其pid应该为1
    sleep(300);
    // 命名空间中的所有进程退出后该命名空间的inode将会被删除, 为后续操作保留它
    return 0;
}

int main() {
    /* Clone */
    pid_t child_pid = clone(child_main, child_stack + STACK_SIZE, \
        CLONE_NEWPID | SIGCHLD, NULL);
    if(child_pid < 0) {
        perror("clone failed");
    }

    /* Unshare */
    int ret = unshare(CLONE_NEWPID); // 父进程调用unshare, 创建了一个新的命名空间,
    //但不会创建子进程. 之后再创建的子进程将会被加入到新的命名空间中
    if (ret < 0) {
        perror("unshare failed");
    }
    int fpid = fork();
    if (fpid < 0) {
        perror("fork error");
    } else if (fpid == 0) {
        printf("I am child process. My pid is %d  \n", getpid());
        // Fork后的子进程会被加入到unshare创建的命名空间中, 所以pid应该为1
        exit(0);
    } else {
    }
    waitpid(fpid, NULL, 0);

    /* Setns */
    char path[80] = "";
    sprintf(path, "/proc/%d/ns/pid", child_pid);
    int fd = open(path, O_RDONLY);
    if (fd == -1)
        perror("open error");
    if (setns(fd, 0) == -1)
    // setns并不会改变当前进程的命名空间, 而是会设置之后创建的子进程的命名空间
        perror("setns error");
    close(fd);

    int npid = fork();
    if (npid < 0) {
        perror("fork error");
    } else if (npid == 0) {
        printf("I am child process. My pid is %d  \n", getpid());
        // 新的子进程会被加入到第一个子进程的pid命名空间中, 所以其pid应该为2
        exit(0);
    } else {
    }
    return 0;
}

运行结果:

$ sudo ./ns
I'm child process and my pid is 1 
I am child process. My pid is 1  
I am child process. My pid is 2 

控制组(Cgroups)

如果说命名空间是从命名和编号的角度进行隔离,而控制组则是将进程进行分组,并真正的将各组进程的计算资源进行限制、隔离。控制组是一种内核机制,它可以对进程进行分组、跟踪限制其使用的计算资源。对于每一类计算资源,控制组通过所谓的子系统(subsystem)来进行控制,现阶段已有的子系统包括:

  • cpusets: 用来分配一组CPU给指定的cgroup,该cgroup中的进程只等被调度到该组CPU上去执行
  • blkio : 限制cgroup的块IO
  • cpuacct : 用来统计cgroup中的CPU使用
  • devices : 用来黑白名单的方式控制cgroup可以创建和使用的设备节点
  • freezer : 用来挂起指定的cgroup,或者唤醒挂起的cgroup
  • hugetlb : 用来限制cgroup中hugetlb的使用
  • memory : 用来跟踪限制内存及交换分区的使用
  • net_cls : 用来根据发送端的cgroup来标记数据包,流量控制器(traffic controller)会根据这些标记来分配优先级
  • net_prio : 用来设置cgroup的网络通信优先级
  • cpu :用来设置cgroup中CPU的调度参数
  • perf_event : 用来监控cgroup的CPU性能

与命名空间不同,控制组并没有增加系统调用,而是实现了一个文件系统,通过文件及目录操作来管理控制组。下面通过一个例子来看一看cgroup是如何利用cpuset子系统来把进程绑定到指定的CPU上去执行的。

1. 创建一个一直执行的shell脚本

#!/bin/bash

x=0

while [ True ];do
    :
done;

2. 在后台执行这个脚本

# bash run.sh &
[1] 20553

3. 查看该脚本在哪个CPU上运行

# ps -eLo ruser,lwp,psr,args | grep 20553 | grep -v grep
root     20553   3 bash run.sh

可以看到PID为20553的进程运行在编号为3的CPU上,下面利用cgroups将其绑定到编号为2的CPU上去执行

4. 挂载cgroups类型的文件系统到一个新创建的目录cgroups中

# mkdir cgroups
# mount -t cgroup -o cpuset cgroups ./cgroups/
# ls cgroups/
cgroup.clone_children   cpuset.memory_pressure_enabled
cgroup.procs            cpuset.memory_spread_page
cgroup.sane_behavior    cpuset.memory_spread_slab
cpuset.cpu_exclusive    cpuset.mems
cpuset.cpus             cpuset.sched_load_balance
cpuset.effective_cpus   cpuset.sched_relax_domain_level
cpuset.effective_mems   docker
cpuset.mem_exclusive    tasks
cpuset.mem_hardwall     notify_on_release
cpuset.memory_migrate   release_agent
cpuset.memory_pressure

5. 创建一个新的组group0

# mkdir group0
# ls group0/
cgroup.clone_children  cpuset.mem_exclusive       cpuset.mems
cgroup.procs           cpuset.mem_hardwall        cpuset.sched_load_balance
cpuset.cpu_exclusive   cpuset.memory_migrate      cpuset.sched_relax_domain_level
cpuset.cpus            cpuset.memory_pressure     notify_on_release
cpuset.effective_cpus  cpuset.memory_spread_page  tasks
cpuset.effective_mems  cpuset.memory_spread_slab

6. 将上面的进程20553加入到新建的控制组中:

# echo 20553 >> group0/tasks 
# cat group0/tasks 
20553

7. 限制该组的进程只能运行在编号为2的CPU上

# echo 2 > group0/cpuset.cpus
# cat group0/cpuset.cpus
2

8. 查看PID为20553的进程所运行的CPU编号

# ps -eLo ruser,lwp,psr,args | grep 20553 | grep -v grep
root     20553   2 bash run.sh

上面的例子简单的展示了如何使用控制组。控制组通过文件和目录来操作,文件系统又是树形结构,因此如果不对cgroups的使用做一些限制的话,配置会变得异常复杂和混乱。因此,在新版的cgroups中做了一些限制。

小结

本文简要介绍了操作系统虚拟化的概念,以及实现操作系统虚拟化的技术——命名空间及控制组。并通过两个简单的例子演示了命名空间及控制组的使用方法。

让javascript中的异步请求同步起来

在页面加载的时候,javascript通常会从服务器去获取一些数据,拿到数据后再渲染页面。如果用同步请求一个一个去拿这些数据,加载会很慢。但如果使用异步请求,后面的渲染操作会在数据返回之前就把页面给渲染了。

google了一下好像木有合适的解决办法, 于是我尝试用一个死循环挡在渲染页面之前,拿到数据后再跳出死循环。类似于这样的:

overview.showLoading();
instances.get_cluster(true);
users.get_users(true);
databases.get_databases(true);

for(;;) {
    if(ctrl.cluster && ctrl.databases && ctrl.users) {
        break;
    }
    setTimeout('', 500);
}

instances.show();
databases.show();
users.show();
overview.show();
overview.hideLoading();

get_cluster, get_databases, get_users会发起异步请求,请求成功后会把数据写到ctrl中去。看起来不错,可是执行起来浏览器会建议用户杀掉script,因为发现了死循环。木有办法,稍微变通一下,只能让死循环活半个小时,如果加载页面需要半个小时的话,你的网站可以歇菜了。于是改成下面的代码:

overview.showLoading();
instances.get_cluster(true);
users.get_users(true);
databases.get_databases(true);

for(var i =0; i < 3600; i++) {
    if(ctrl.cluster && ctrl.databases && ctrl.users) {
        break;
    }
    setTimeout('', 500);
}

instances.show();
databases.show();
users.show();
overview.show();
overview.hideLoading();

世界安静了,同步时不停转的loading也很快就消失了。

Javascript中的数组

  • 数组的定义:
    • var colors = new Array(20);
    • var colors = new Array(‘red’);  // [‘red’]
    • var colors = [‘red’, ‘green’];
  • 判断变量是不是数组:
    • colors instanceof Array;  //true
    • Array.isArray(colors); //true
  • 将数组转化为字符串:
    • colors.toString(); // ‘red,green’
    • colors.join(‘ ‘); //’red green’
    • colors = [ “red”, undefined, “green”, null, “yellow” ];
      • colors.toString(); //"red,,green,,yellow"
        
        colors.join(' '); //"red  green  yellow"
        
        colors.join(';'); //"red;;green;;yellow"
  • 栈方法
    • colors.push(‘yellow’); //[‘red’, ‘green’, ‘yellow’]
    • colors.pop(); //[‘red’, ‘green’]
  • 队列方法
    • colors.push(‘yellow’); //[‘red’, ‘green’, ‘yellow’]
    • colors.shift(); //[‘green’, ‘yellow’]
    • colors.unshift(‘black’); //[‘black’, ‘red’, ‘green’]
  • 重新排序
    • colors.reverse(); //[‘green’, ‘red’]
    • colors.sort();
      • 字符串升序排列
        • var nums = [1, 5, 10]; //nums.sort();//[1, 10, 5]
      • colors.sort(function(a,b){return a – b;});升序排列
      • colors.sort(function(a,b){return b – a;});降序排列
  • 操作
    • var ret = colors.concat(‘black’); // ret = [‘red’, ‘green’, ‘black’]
    • var ret = colors.slice(0, 1); //[‘red’] 切片
    • colors.splice(pos, length, item, item…); 在pos处删除length项,然后插入item…
  • 位置
    • indexOf(‘red’); //0
    • lastIndexOf(‘red’); //0
  • 迭代
    • colors.every(function(item, index, array){}); 所有元素返回true则返回true
    • colors.filter(function(item, index, array){}); 返回为true的元素组成的数组
    • colors.forEach(function(item, index, array){}); 无返回值
    • colors.map(function(item, index, array){}); 返回函数调用结果组成的数组
    • colors.some(function(item, index, array){}); 如果有一项返回true则返回true
  • 归并方法
    • var sum = values.reduce(function(prev, cur, index, array){return prev + cur}, 0);
    • reduceRight(); 从后往前循环

Javascript中的基本数据类型

Undefined

  • 在var或者let中声明了变量但没有赋值时,这个变量的值就是undefined.
  • 使用typeof关键字检测未声明变量的类型为undefined.

Null

  • null表示一个空对象指针,所以用typeof检测null时,会返回object
  • undefine派生自null, null == undefined 为true, null === undefined为false

Boolean

  • true false 区分大小写
  • 空字符串、0和NaN、null、undefined转换为boolean的值为false

Number

  • Number表示整数和浮点数
  • 八进制数以0开头,十六进制数以0x开头
  • Number.MIN_VALUE 表示Javascript支持的正的最小数值,Number.MAX_VALUE表示Javascript支持的最大数值
  • 超出最大数值就会被转化为Infinity,如果为负值则会被转化为-Infinity
  • isFinite()函数可以判断一个数值是否在支持的范围之内
  • NaN表示本来该返回数值的操作数未返回数值的情况,如除以0就会返回NaN
  • NaN的数值运算会返回NaN
  • NaN == NaN 为false
  • isNaN()函数可以判断一个数值是不是NaN
  • Number()函数可以将其他类型的值转换为Number类型:
    • Number(true) = 1; Number(false) = 0;
    • Number(null) = 0;
    • Number(“”) = 0; Number(“0x1a”) = 26; Number(‘076’) = 76;
    • Number(‘100hello’) = NaN;
    • 如果是对象,则会调用对象的valueOf()方法,如果返回的是NaN则会先调用toString方法转化为字符串,然后根据字符串的转换规则来转换
  • parseInt()函数:
    • parseInt(‘100hello’) = 100;
    • parseInt(”) = NaN;
    • parseInt(‘0x1a’) = 26;
    • parseInt(‘076’) = 76; parseInt(‘076’, 8) = 62;
  • parseFloat()与parseInt()类似,但有如下区别:
    • parseFloat不能传入第二个参数(进制),不能解析十六进制字符串

String

  • 字符串一旦创建,其值不能改变,如:var lang = ‘Java’; lang += ‘Script’; 会重新创建一个字符串,填充上’JavaScript’, ‘Java’和’Script’都将被销毁
  • 除了null和undefined之外,其他的几个数据类型都有toString()方法,可以将其转换为字符串
  • 数值类型调用toString()方法可以传入进制作为参数,如:var a=20; a.toString(2);
  • String()方法可以将null转化为’null’,把undefined转化为’undefined’

React 概要

React 简介

React 是一个开源的javascript库,用来构建用户接口(UI)。下图是React的一些基本信息:

React 的特点

  1. 单向数据流
    • 数据自上而下
      • Props 不可变
      • States可变
      • 任何数据、函数都可以作为属性(props)传    递给子组件(Props, States, Handlers, Styles)
    • 事件冒泡
      • 子组件触发的事件会传递到父组件
  2. 虚拟DOM
    • Javascript内存中的DOM数据缓存
    • 组件发生变化时渲染虚拟DOM
    • React将虚拟DOM与DOM的差异转化为一系列的DOM操作
    • 将这些操作同步应用到真实的DOM中
  3. JSX
    • 可以使用HTML语法创建Javascript 对象
    • 代码更少
    • 会被转化为Javascript执行
      • Offline – react-tools
      • In-Browser – JSXTransformer
    • 不改变Javascript语义
  4. 其他特点
    • 元素嵌套: 每个组件只允许有一个顶层元素(div, table …)
    • 自定义属性: 除了HTML标签自带属性之外,React也支持自定义属性,自定义属性需要加上data- 前缀
    • JavaScript表达式: 可以通过{}在JSX中使用Javascript表达式
    • 三目运算符: JSX中不能使用if-else但可以使用三目运算符

React元素

const element = <h1>Hello, world</h1>;

  • React 元素 != DOM 元素
  • 将元素渲染到 DOM 中

    ReactDOM.render(element, document.getElementById(‘root’));
     

  • 更新元素 – 重新 Render
  • 更新元素只会更新变化的部分
function tick() {
  const element = (
    <div>
      <h1>Hello, world!</h1>
      <h2>It is {new Date().toLocaleTimeString()}.</h2>
    </div>
  );
  ReactDOM.render(
    element,
    document.getElementById('root')
  );
}
setInterval(tick, 1000);

React组件

组件可以将UI切分成一些的独立的、可复用的部件,这样你就只需专注于构建每一个单独的部件。

  • 如何定义一个组件
    • 函数
      function Welcome(props) {
        return <h1>Hello, {props.name}</h1>;
      }

       

    • class
      class Welcome extends React.Component {
        render() {
          return <h1>Hello, {this.props.name}</h1>;
        }
      }

       

  • 渲染组件
    • const element = <Welcome name=”Sara” />;
  • 组合组件
function App() {
  return (
    <div>
      <Welcome name="Sara" />
      <Welcome name="Cahal" />
      <Welcome name="Edite" />
    </div>
  );
}

状态与生命周期

因为react中props为只读,如果需要更新数据,可以使用react中的状态。在使用状态之前,需要把组件函数转变为类。

  • 创建一个名称扩展为 React.Component 的ES6 类
  • 创建一个叫做render()的空方法
  • 将函数体移动到 render() 方法中
  • 在 render() 方法中,使用 this.props 替换 props
  • 删除剩余的空函数声明

将组件函数转化为类之后就可以添加状态了:

  • 在 render() 方法中使用 this.state.date 替代 this.props.date
  • 添加一个类构造函数来初始化状态 this.state
  • 使用 this.setState() 来更新组件局部状
class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }
  componentDidMount() {
    this.timerID = setInterval(
      () => this.tick(),
      1000
    );
  }
  componentWillUnmount() {
    clearInterval(this.timerID);
  }
  tick() {
    this.setState({
      date: new Date()
    });
  }
  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}
ReactDOM.render(
  <Clock />,
  document.getElementById('root')
);

事件处理

  • React事件绑定属性的命名采用驼峰式写法,而不是小写。
  • 如果采用 JSX 的语法你需要传入一个函数作为事件处理函数,而不是一个字符串(DOM元素的写法)
  • React不能使用返回 false 的方式阻止默认行为

条件渲染

  • 使用 JavaScript 操作符 if 或条件运算符来创建表示当前状态的元素,然后让 React 根据它们来更新 UI
  • 使用变量来储存元素
    function Greeting(props) {
      const isLoggedIn = props.isLoggedIn;
      if (isLoggedIn) {
        return <UserGreeting />;
      }
      return <GuestGreeting />;
    }
    ReactDOM.render(
      // Try changing to isLoggedIn={true}:
      <Greeting isLoggedIn={false} />,
      document.getElementById('root')
    );

     

  • &&运算符
    function Mailbox(props) {
      const unreadMessages = props.unreadMessages;
      return (
        <div>
          <h1>Hello!</h1>
          {unreadMessages.length > 0 &&
            <h2>
              You have {unreadMessages.length} unread messages.
            </h2>
          }
        </div>
      );
    }

     

  • 三目运算符
    render() {
      const isLoggedIn = this.state.isLoggedIn;
      return (
        <div>
          The user is <b>{isLoggedIn ? 'currently' : 'not'}</b> logged in.
        </div>
      );
    }

     

列表渲染

  • React 可以直接渲染列表
  • Keys可以在DOM中的某些元素被增加或删除的时候帮助React识别哪些元素发生了变化。因此应当给数组中的每一个元素赋予一个确定的标识。
  • 元素的key只有在它和它的兄弟节点对比时才有意义
  • jsx中可以使用map
function ListItem(props) {
  return <li>{props.value}</li>;
}
function NumberList(props) {
  const numbers = props.numbers;
  const listItems = numbers.map((number) =>
    <ListItem key={number.toString()}
              value={number} />
  );
  return (
    <ul>
      {listItems}
    </ul>
  );
}

表单

  • HTML表单元素与React中的其他DOM元素有所不同,因为表单元素生来就保留一些内部状态
  • 在HTML当中,像<input>,<textarea>, 和 <select>这类表单元素会维持自身状态,并根据用户输入进行更新
  • 在React中,可变的状态通常保存在组件的状态属性中,并且只能用 setState(). 方法进行更新
class Reservation extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      isGoing: true,
      numberOfGuests: 2
    };
    this.handleInputChange = this.handleInputChange.bind(this);
  }
  handleInputChange(event) {
    const target = event.target;
    const value = target.type === 'checkbox' ? target.checked : target.value;
    const name = target.name;
    this.setState({
      [name]: value
    });
  }
  render() {
    return (
      <form>
        <label>
          Is going:
          <input
            name="isGoing"
            type="checkbox"
            checked={this.state.isGoing}
            onChange={this.handleInputChange} />
        </label>
        <br />
        <label>
          Number of guests:
          <input
            name="numberOfGuests"
            type="number"
            value={this.state.numberOfGuests}
            onChange={this.handleInputChange} />
        </label>
      </form>
    );
  }
}

 

[转]Linux Mint启用VNC

This tutorial was adapted from here.

1. Remove the default Vino server:

sudo apt-get -y remove vino

2. Install x11vnc:

sudo apt-get -y install x11vnc

3. Create the directory for the password file:

sudo mkdir /etc/x11vnc

4. Create the encrypted password file:

sudo x11vnc –storepasswd /etc/x11vnc/vncpwd

You will be asked to enter and verify the password.  Then press Y to save the password file.

5. Create the systemd service file for the x11vnc service:

sudo xed /lib/systemd/system/x11vnc.service

Copy/Paste this code into the empty file:

[Unit]
Description=Start x11vnc at startup.
After=multi-user.target

[Service]
Type=simple
ExecStart=/usr/bin/x11vnc -auth guess -forever -noxdamage -repeat -rfbauth /etc/x11vnc/vncpwd -rfbport 5900 -shared

[Install]
WantedBy=multi-user.target

6: Reload the services:

sudo systemctl daemon-reload

7. Enable the x11vnc service at boot time:

sudo systemctl enable x11vnc.service

8. Start the service:

Either reboot or

sudo systemctl start x11vnc.service

CSS概要

CSS 基础知识

语法

CSS全称为“层叠样式表 (Cascading Style Sheets)”,它主要是用于定义HTML内容在浏览器内的显示样式, 如文字大小、颜色、字体加粗等。使用CSS样式的一个好处是通过定义某个样式,可以让不同网页位置的 文字有着统一的字体、字号或者颜色等。

CSS语法
选择符 { 属性:值}

  • 选择符:又称选择器,指明网页中要应用样式规则的元素,如本例中是网页中所有的段(p)的文字将变 成蓝色,而其他的元素(如ol)不会受到影响。
  • 声明:在英文大括号“{}”中的的就是声明,属性和值之间用英文冒号“:”分隔。当有多条声明时,中间 可以英文分号“;”分隔
  1. 最后一条声明可以没有分号,但是为了以后修改方便,一般也加上分号
  2. CSS注释 – /*注释语句*/
  3. CSS的某些样式是具有继承性的。
  4. 为了使用样式更加容易阅读,可以将每条代码写在一个新行内

插入方式

CSS样式可以写在哪些地方呢?从CSS 样式代码插入的形式来看基本可以分为以下3种:内联式、嵌入式和

外部式三种。

  1. 内联式:把css代码用style属性直接写在现有的HTML标签中。如: <p style=”color:red”>这里文字是红色。</p>
  2. 嵌入式:把css样式代码写在<style type=“text/css”></style>标签之间。并且一般情况下嵌入式css样式 写在<head></head>之间。如:<style type=”text/css”> span{ color:red; } </style>
  3. 外部式:把css代码写一个单独的外部文件中,这个css样式文件以“.css”为扩展名,在<head>内(不是在<style>标签内)使用<link>标签将css样式文件链接到HTML文件内。如: <link href=”base.css” rel=”stylesheet” type=”text/css” />

优先级:内联式 > 嵌入式 > 外部式 ?

离被设置元素越近优先级别越高

权值、层叠、重要性

标签的权值为1,类选择符的权值为10,ID选择符的权值最高为100

  • p{color:red;} /*权值为1*/
  • p span{color:green;} /*权值为1+1=2*/
  • .warning{color:white;} /*权值为10*/
  • p span.warning{color:purple;} /*权值为1+1+10=12*/
  • #footer .note p{color:yellow;} /*权值为100+10+1=111*/

层叠就是在html文件中对于同一个元素可以有多个css样式存在,当有相同权重的样式存在时,会根据这些 css样式的前后顺序来决定,处于最后面的css样式会被应用。

p{color:red;}
p{color:green;}
<p class=”first”>hello world</p>

!important语句可以把样式改变为最高权值

p{color:red !important;} p{color:green;}
<p class=”first”>hello world</p>

单位和值

颜色值

  1. 英文命令颜色。 如: p{color:red;}
  2. RGB颜色 p{color:rgb(133,45,200);} 3.十六进制颜色 p{color:#00ffff;}

长度值

  1. 像素。 如: p{font-size: 20px}
  2. em。1 em = 父元素的font-size 如: p{font-size:14px} span{font-size:0.8em;} <p>以这个<span>例子</span>为例。</p>
  3. 百分比 p{font-size:12px;line-height:130%}

CSS 选择器

在{}之前的部分就是“选择器”,“选择器”指明了{}中的“样式”的作用对象,也就是“样式”作用于网页中的哪些元素。

  • 标签选择器 – 标签选择器其实就是html代码中的标签。

  • 类选择器

    .setGreen {
        color:green;
    }

    <span class=”setGreen”>胆小如鼠</span>

  • Id选择器

    #setGreen {
         color:green;
    }

  • 子选择器 – 即大于符号(>),用于选择指定标签元素的第一代子元素

    .food>li{border:1px solid red;}

  • 包含选择器 – 即加入空格,用于选择指定标签元素下的后辈元素

  • 通用选择器 – 它使用一个(*)号指定,它的作用是匹配html中所有标签元素

  • 伪类选择符 – 它允许给html不存在的标签(标签的某种状态)设置样式,如:a:hover{color:red;}

  • 分组选择符 – html中多个标签元素设置同一个样式时,可以使用分组选择符

    h1,span{color:red;}

CSS 排版 

  1. 设置字体: font-family:”宋体”

  2. 设置字号、颜色:font-size:12px;color:#666

  3. 设置文字的样式:粗体、斜体、下划线、删除线:

    • font-weight:bold;

    • font-style:italic

    • text-decoration:underline;

    • text-decoration:line-through;

  4. 设置文字缩进:text-indent:2em;

  5. 设置行高:line-height:2em;

  6. 设置字符间距、单词间距:

    • letter-spacing:50px;

    • word-spacing:50px;

  7. 设置对齐方式:

    • text-align:left;

    • text-align:center;

    • text-align:right;

CSS 布局模型

元素分类 在CSS中,html中的标签元素大体被分为三种不同的类型:块状元素、内联元素(又叫行内元素)和内联块状元素。

常用的块状元素(display: block)有: <div>、<p>、<h1>…<h6>、<ol>、<ul>、<dl>、<table>、<address>、<blockquote> 、<form>

  • 每个块级元素都从新的一行开始,并且其后的元素也另起一行。
  • 元素的高度、宽度、行高以及顶和底边距都可设置。
  • 元素宽度在不设置的情况下,是它本身父容器的100%(和父元素的宽度一致),除非设定一个宽度。

常用的内联元素(display: inline)有: <a>、<span>、<br>、<i>、<em>、<strong>、<label>、<q>、<var>、<cite>、<code>

  • 和其他元素都在一行上;
  • 元素的高度、宽度及顶部和底部边距不可设置;
  • 元素的宽度就是它包含的文字或图片的宽度,不可改变。

常用的内联块状元素(display: inline-block)有: <img>、<input>

  • 和其他元素都在一行上;
  • 元素的高度、宽度、行高以及顶和底边距都可设置。

盒子模型

流动模型 flow

流动模型,流动(Flow)是默认的网页布局模式。也就是说网页在默认状态下的 HTML 网页元素都是根据流

动模型来分布网页内容的。 流动布局模型具有2个比较典型的特征:

  • 块状元素都会在所处的包含元素内自上而下按顺序垂直延伸分布,因为在默认状态下,块状元素的 宽度都为100%。实际上,块状元素都会以行的形式占据位置。
  • 在流动模型下,内联元素都会在所处的包含元素内从左到右水平分布显示。

浮动模型 float

浮动模型,浮动(Float)如果想让两个块状元素并排显示,需要用到浮动模型。

Div {
    width:200px;
    height:200px;
    border:2px red solid;
    float:left;
}

<div id=”div1″> </div>
<div id=”div2″> </div>

层模型

什么是层布局模型?层布局模型就像是图像软件PhotoShop中非常流行的图层编辑功能一样,每个图层能够 精确定位操作,但在网页设计领域,由于网页大小的活动性,层布局没能受到热捧。但是在网页上局部使用 层布局还是有其方便之处的

层模型有三种形式:

  1. 绝对定位(position: absolute)
  2. 相对定位(position: relative)
  3. 固定定位(position: fixed)

如果想为元素设置层模型中的绝对定位,需要设置position:absolute(表示绝对定位),这条语句的作用将元 素从文档流中拖出来,然后使用left、right、top、bottom属性相对于其最接近的一个具有定位属性的父包含块 进行绝对定位。如果不存在这样的包含块,则相对于body元素,即相对于浏览器窗口。

如果想为元素设置层模型中的相对定位,需要设置position:relative(表示相对定位),它通过left、right、top、 bottom属性确定元素在正常文档流中的偏移位置。相对定位完成的过程是首先按static(float)方式生成一个元 素(并且元素像层一样浮动了起来),然后相对于以前的位置移动,移动的方向和幅度由left、right、top、 bottom属性确定,偏移前的位置保留不动。

fixed:表示固定定位,与absolute定位类型类似,但它的相对移动的坐标是视图(屏幕内的网页窗口)本身。 由于视图本身是固定的,它不会随浏览器窗口的滚动条滚动而变化,除非你在屏幕中移动浏览器窗口的屏幕 位置,或改变浏览器窗口的显示大小,因此固定定位的元素会始终位于浏览器窗口内视图的某个位置,不会 受文档流动影响

弹性盒布局

详细介绍请参考:https://www.ibm.com/developerworks/cn/web/1409_chengfu_css3flexbox/

.flex-container {
   list-style: none;
   display: flex;
   flex-direction: row;
   flex-wrap: wrap;
}
<ul class="flex-container">
<li class="flex-item"><imgsrc="//placehold.it/300&text=1"></li>
<li class="flex-item"><img src="//placehold.it/300&text=2"></li>
<li class="flex-item"><img src="//placehold.it/300&text=3"></li>
<li class="flex-item"><img src="//placehold.it/300&text=4"></li>
<li class="flex-item"><img src="//placehold.it/300&text=5"></li>
<li class="flex-item"><img src="//placehold.it/300&text=6"></li>
</ul>
.flex-item {   
    padding: 5px;
}

CSS 设计技巧

• 水平居中设置-行内元素

通过给父元素设置 text-align:center 来实现的

• 水平居中设置-定宽块状元素

通过设置“左右margin”值为“auto”来实现居中的

• 水平居中设置-不定宽块状元素方法

  1. 加入 table 标签

  2. 设置 display: inline 方法:与第一种类似,显示类型设为 行内元素,进行不定宽元素的属性设置

  3. 设置 position:relative 和 left:50%:利用 相对定位 的方式,将元素向左偏移 50% ,即达到居中的目的

• 垂直居中-父元素高度确定的单行文本

通过设置父元素的 height 和 line-height 高度一致来实现的

• 垂直居中-父元素高度确定的多行文本

  1. 使用插入 table (包括tbody、tr、td)标签,同时设置 vertical-align:middle

  2. 设置块级元素的 display 为 table-cell(设置为表格单元显示),激活 vertical-align 属性

Openstack Trove概要

Trove简介

Openstack Trove是openstack为用户提供的数据库即服务(DBaaS)。所谓DBaaS,即trove既具有数据库管理的功能,又具有云计算的优势。使用trove,用户可以:

  • “按需”获得数据库服务器
  • 配置所获得的数据库服务器或者数据库服务器集群
  • 对数据库服务器或者数据库服务器集群进行自动化管理
  • 根据数据库的负载让数据库服务器集群动态伸缩

与openstack的其他组件一样,trove也提供RESTful API,并通过RESTful API和其他组件进行交互。

Trove架构

上图为trove的架构图。Trove API和用户进行交互,当Trove API接收到用户请求时,trove API首先会调用Keystone的API来对用户进行认证,认证通过后才会去执行相应的操作。Trove API会同步处理操作简单的一些请求,复杂的请求则会通过Message Queue (RabbitMQ)交给Task Manager来处理。Task Manager会监听RabbitMQ的一个topic,收到请求后就会进行处理。这些请求通常是分配数据库实例、管理数据库实例的生命周期、操作数据库等。和openstack的其他组件一样,Trove也有一个Infrastructure Database来存储自己本身的数据,如数据库实例的信息等。Trove conductor的主要功能是接收来自guest agent的状态更新信息,这些信息会被存储在Infrastructure database里面或者作为调用结果返回给其他服务。通常这些状态更新信息包括:guest agent心跳包,数据库备份状态等。Guest Agent运营于数据库服务器中(虚拟机),给trove其他组件提供了一套内部使用的API,trove的其他组件通过Message Queue来调用这些API,guest agent收到API调用请求后,执行相应的数据库操作。

Trove的安装部署请参考Openstack官方文档(多坑慎入):

https://docs.openstack.org/project-install-guide/database/ocata/

Trove的基本概念

  • 数据库实例(Instance):包含数据库程序的openstack虚拟机,如果用户创建了一个数据库实例,那么他其实就创建了一台openstack虚拟机,并在该虚拟机上启动了数据库服务。
  • Datastore:用来表示和存储数据库的类型、版本、虚拟机镜像等信息。当用户创建一个数据库实例时需要指定Datastore.
  • 配置组(Configuration Group):数据库参数组成的集合。用户可以将配置组应用到一个或多个数据库实例上,因而避免了大量的重复操作。

Trove的用法

0.添加Datastore

在创建数据库实例时,需要指定Datastore来告诉trove需要用到的镜像、数据库类型及版本信息。所以在创建数据库实例之前需要在系统中创建Datastore.

由于版权问题,openstack官方并没有提供可供下载的镜像,需要用户自己去build。可参考文档:

https://docs.openstack.org/developer/trove/dev/building_guest_images.html

Build好镜像好需要将其上传到glance服务:

ad@ltczhp11:~$ glance image-create --name mysql-5.6 --disk-format=qcow2 --container-format=bare --file=./mysql-5.6.qcow2 --visibility public 
ad@ltczhp11:~$ glance image-list
+--------------------------------------+--------------------------+
| ID                                   | Name                     |
+--------------------------------------+--------------------------+
| 31d60001-c2bf-496e-9f21-069bb411bd3b | CouchDB                  |
| eaf27f1b-3a8a-4efb-827c-697fa065933b | DB2                      |
| 60ca8bfc-28a7-418a-9422-ec6548f23d54 | DIB-Mongodb              |
| 51103b44-2618-4c15-8ded-4371bea8973a | DIB-Postgres             |
| 8bc1a6a2-6ec3-4f37-bb54-91134b903996 | mongodb-lsl              |
| c4c9a58f-bbe6-4640-8488-0c05b52028df | mysql-5.6                |
| 5d800163-3660-467a-a433-e1827924a741 | PostgreSQL               |
| 38291f8f-5af6-4338-82b7-3f18dc355cae | ubuntu16.04-server-s390x |
+--------------------------------------+--------------------------+

使用trove-manage添加Datastore:

root@ltczhp11:~# trove-manage datastore_update mysql "" #创建一个datastore

root@ltczhp11:~# trove-manage datastore_version_update mysql 5.6 mysql c4c9a58f-bbe6-4640-8488-0c05b52028df "" 1 #创建一个dadastore的版本,一个dadastore可以有多个版本

root@ltczhp11:~# trove-manage datastore_update mysql 5.6 #指定默认的datastore版本

1.基本的数据库实例操作

  • 列出所有的数据库实例
    • $ trove list
  • 创建一个数据库实例
    • $ trove create vm1 2 –size 3 –datastore mysql
  • 重启一个数据库实例
    • $ trove restart vm1
  • 删除一个数据库实例
    • $ trove delete vm1
  • 强制删除一个数据库实例
    • $ trove force-delete vm1
  • 调整一个数据库实例的规格
    • $ trove resize-volume vm1 4
    • $ trove resize-instance vm1 3

2.管理数据库用户

  • 列出所有的数据库用户
    • $ trove user-list
  • 创建一个用户
    • $ trove user-create
  • 删除一个用户
    • $ trove user-delete
  • 给一个用户授权访问某个数据库
    • $ trove user-grant-access
  • 吊销用户对于某一个数据库的访问权限
    • $ trove user-revoke-access
  • 显示用户信息
    • $ trove user-show
  • 显示用户的权限
    • $ trove user-show-access

3. 数据库管理

  • 在一个数据库实例中创建一个数据库
    • $ trove database-create
  • 列出一个数据库实例中的所有数据库
    • $ trove database-list
  • 删除一个数据库实例中的某个数据库
    • $ trove database-delete

4. 副本管理

  • 创建一个副本
    • $ trove create  —replica_of
  • 将一个副本从源数据库分离
    • $ trove detach-replica
  • 让一个副本在副本集合中成为源数据库
    • $ trove promote-to-replica-source
  • 删除挂掉的源数据库
    • $ trove eject-replica-source
  • 设置副本亲和性
    • $ trove create  —replica_of  –locality affinity
    • $ trove create  —replica_of  –locality anti-affinity

 

 

ATOM快捷键操作

光标移动

·       Alt+Left or Alt+B – Move to the beginning of word

·       Alt+Right or Alt+F – Move to the end of word

·       Cmd+Left or Ctrl+A – Move to the first character of the current line

·       Cmd+Right or Ctrl+E – Move to the end of the line

·       Cmd+Up – Move to the top of the file

·       Cmd+Down – Move to the bottom of the file

·       Ctrl+P – Go up a single character

·       Ctrl+N – Go down a single character

·       Ctrl+B – Go left to a single character

·       Ctrl+F – Go right to a single character

·       Ctrl+G – Go to a certain line

·       Cmd+R – Jump to a symbol such as a method definition

·       Cmd+Shift+R – Search for symbols across the project

·       Alt+Cmd+Down to go to and Alt+Cmd+Up to return from the declaration of the symbol under the cursor

选择文本

·       Shift+移动快捷键

·       Cmd+A – Select the entire contents of the file

·       Cmd+L – Select the entire line

·       Ctrl+Shift+W – Select the current word

编辑文本

·       Cmd+J – Join the next line to the end of the current line

·       Cmd+Ctrl+Up/Down – Move the current line up or down

·       Cmd+Shift+D – Duplicate the current line

·       Cmd+K Cmd+U – Upper case the current word

·       Cmd+K Cmd+L – Lower case the current word

·       Ctrl+T – Transpose characters. This swaps the two characters on either side of the cursor.

·       Ctrl+Shift+K – Delete current line

·       Alt+Backspace or Alt+H – Delete to beginning of word

·       Alt+Delete or Alt+D – Delete to end of word

·       Cmd+Delete – Delete to end of line

·       Ctrl+K – Cut to end of line

·       Cmd+Backspace – Delete to beginning of line

多光标操作

·       Cmd+Click – Add a new cursor at the clicked location

·       Ctrl+Shift+Up/Down – Add another cursor above/below the current cursor

·       Cmd+D – Select the next word in the document that is the same as the currently selected word

·       Cmd+Ctrl+G – Select all words in the document that are the same as the currently selected word

·       Cmd+Shift+L – Convert a multi-line selection into multiple cursors

查找和替换文本

·       Cmd+F – Search within a buffer

·       Cmd+Shift+F – Search the entire project

 

HTML概要

HTML CSS Javascript 的关系

HTML是网页内容的载体。内容就是网页制作者放在页面上想要让用户浏览的信息,可以包含文字、图片、视频等。

CSS样式是表现。就像网页的外衣。比如,标题字体、颜色变化,或为标题加入背景图片、边框等。所有这些用来改变内容外观的东西称之为表现。

JavaScript是用来实现网页上的动态效果。如:鼠标滑过弹出下拉菜单。或鼠标滑过表格的背景颜色改变。还有焦点新闻(新闻图片)的轮换。

HTML 标签语法

1标签由英文尖括号<>括起来,如<html>就是一个标签

2. html中的标签一般都是成对出现的,分开始标签结束标签。结束标签比开始标签多了一个/

如:

1) <p></p>

2) <div></div>

3) <span></span>

3. 标签与标签之间是可以嵌套的,但先后顺序必须保持一致,如:<div>里嵌套<p>,那么</p>必须放在</div>的前面。如下图所示

4. HTML标签不区分大小写,<h1><H1>是一样的,但建议小写,因为大部分程序员都以小写为准。

HTML标签

<p> 标签

如果想在网页上显示文章,就需要<p>标签,把文章的段落放到<p>标签中

语法

<p>段落文本</p>

 

<hx> 标签

使用<hx>标签来制作文章的标题
标题标签一共有6个,h1h2h3h4h5h6分别为一级标题、二级标题、三级标题、四级标题、五级标题、六级标题。并且依据重要性递减。<h1>是最高的等级

语法

<h1>段落文本</h1>

<strong> <em>标签

在一段话中特别强调某几个文字,这时候就可以用到<em><strong>标签。

但两者在强调的语气上有区别:<em> 表示强调,<strong> 表示更强烈的强调。并且在浏览器中<em> 默认用斜体表示,<strong> 粗体表示

语法

<em>段落文本</em>

<strong>段落文本</strong>

<q> 标签

使用q标签可以在html中添加一段引用,如作家的话诗句等。

1注意要引用的文本不用加双引号,浏览器会对q标签自动添加双引号

语法

段落文本<q>引用文本</q>段落文本

<blockquote> 标签

 blockquote作用也是引用别人的文本。但它是对长文本的引用,如在文章中引入大段某知名作家的文字,这时需要这个标签。

1浏览器对<blockquote>标签的解析是缩进样式,而不是添加引号

语法

<blockquote>引用段落</blockquote>

<br /> 标签

 需要加回车换行的地方加入<br /><br />标签作用相当于word文档中的回车。

1浏览器会忽略HTML中的回车和空格,如果需要换行,就要用到<br />标签。

2. 如果需要加空格,则需要用&nbsp来替换空格。

语法

引用段落<br />

<hr /> 标签

在信息展示时,有时会需要加一些用于分隔的横线,这样会使文章看起来整齐.

1. <hr />标签和<br />标签一样也是一个空标签,所以只有一个开始标签,没有结束标签

2. <hr />标签的在浏览器中的默认样式线条比较粗,颜色为灰色。可以通过css来改变水平线的样式。

语法

<p>文本段落</p>

<hr />

<address> 标签

一般网页中会有一些网站的联系地址信息需要在网页中展示出来,这些联系地址信息如公司的地址就可以<address>标签。也可以定义一个地址(比如电子邮件地址)、签名或者文档的作者身份

1. <address>标签中的内容会在浏览器中显示为斜体。

语法

<address>地址信息或联系人信息</address>

<code><pre> 标签

在介绍语言技术的网站中,避免不了在网页中显示一些计算机专业的编程代码,当代码为一行代码时,你就可以使用<code>标签了,如下面例子:

<code>var i=i+300;</code>

1. 如果是多行代码,可以使用<pre>标签。

2. <pre> 标签的主要作用:预格式化的文本。被包围在 pre 元素中的文本通常会保留空格和换行符。

语法

<code>一行计算机代码</code>

<pre>多行计算机代码</pre>

<ul> <li>标签

利用<ul><li>可以生成没有顺序的列表。

语法

<ul>

  <li>精彩少年</li>

  <li>美丽突然出现</li>

  <li>触动心灵的旋律</li>

</ul>

<ol> <li>标签

利用<ol><li>可以生成有顺序的列表。

语法

<ol>

  <li>前端开发面试心法 </li>

  <li>零基础学习html</li>

  <li>JavaScript全攻略</li>

</ul>

<div> 标签

在网页制作过程过中,可以把一些独立的逻辑部分划分出来,放在一个<div>标签中,这个<div>标签的作用就相当于一个容器

1. divspan类似,都没有特殊的语义。

2. div可以用来排版。

3. div属于块级元素。

4. 可以用id来为div分组命名

语法

<div id=’xxx’>

  

</div>

<caption> 标签

可以使用caption标签来为表格添加标题:

语法:

<table>

  <caption>标题文本</caption>

  <tr>

    <td>…</td>

    <td>…</td>

     

   </tr>

   

</table>

<a> 标签

使用<a>标签可实现超链接,它在网页制作中可以说是无处不在,只要有链接的地方,就会有这个标签

语法:

<a href=”目标网址” title=”鼠标滑过显示的文本“>链接显示的文本</a>

1. title属性的作用鼠标滑过链接文字时会显示这个属性的文本内容。这个属性在实际网页开发中作用很大,主要方便搜索引擎了解链接地址的内容(语义化更友好)

2. <a>标签在默认情况下,链接的网页是在当前浏览器窗口中打开,如果需要在新的浏览器窗口中打开,则需要用到target选项。

<a href=”目标网址” target=”_blank”>click here!</a>
3. a标签还有一个作用是可以链接Email地址,使用mailto能让访问者便捷向网站管理者发送电子邮件

<img> 标签

使用<img>标签可以在网页中插入图片。

语法:

<img src=”图片地址” alt=”下载失败时的替换文本” title = “提示文本“>
1src标识图像的位置

2alt指定图像的描述性文本,当图像不可见时(下载不成功时),可看到该属性指定的文本

3title提供在图像可见时对图像的描述(鼠标滑过图片时显示的文本)

4图像可以是GIFPNGJPEG格式的图像文件。

HTML表单

表单可以把浏览者输入的数据传送到服务器端,这样服务器端程序就可以处理表单传过来的数据

语法:

<form method=”传送方式” action=”URL”>

</form>

1.<form> <form>标签是成对出现的,以<form>开始,以</form>结束

2.action 浏览者输入的数据被传送到的地方,比如一个PHP页面(save.php)

3.method  数据传送的方式(get/post

4. 所有表单控件(文本框、文本域、按钮、单选框、复选框等)都必须放在 <form></form> 标签之间
5. get请求会把表单提供的参数放到URL中,而post请求会把参数放到http请求体中

文本、密码输入框

当用户要在表单中键入字母、数字等内容时,就会用到文本输入框。文本框也可以转化为密码输入框

语法:

<form>

  <input type=”text/password” name=”名称” value=”文本” />

</form>

1type

   当type=”text”时,输入框为文本输入框;

   当type=”password”输入框为密码输入框

2name:为文本框命名,以备后台程序ASP PHP使用

3value:为文本输入框设置默认值。(一般起到提示作用)

文本域 多行文本输入

当用户需要在表单中输入大段文字时,需要用到文本输入域。

语法:

<textarea rows=”行数 cols=”列数>

文本

</textarea>

1<textarea>标签是成对出现的,以<textarea>开始,以</textarea>结束

2cols 多行输入域的列数

3rows 多行输入域的行数

4、在<textarea></textarea>标签之间可以输入默认值

单选框、复选框

在使用表单设计调查表时,为了减少用户的操作,使用选择框是一个好主意,html中有两种选择框,即单选框复选框,两者的区别是单选框中的选项用户只能选择一项,而复选框中用户可以任意选择多项,甚至全选

语法:

<input type=”radio/checkbox” value=”” name=”名称” checked=”checked”/>

1type:

   当 type=”radio” 时,控件为单选框

   当 type=”checkbox” 时,控件为复选

2value:提交数据到服务器的值(后台程序PHP使用

3name:为控件命名,以备后台程序 ASPPHP 使用

4checked:当设置 checked=”checked” 时,该选项被默认选中

下拉列表框

下拉列表在网页中也常会用到,它可以有效的节省网页空间。既可以单选、又可以多选

下拉列表也可以进行多选操作,在<select>标签中设置multiple=”multiple”属性,就可以实现多选功能

提交按钮

在表单中有两种按钮可以使用,分别为:提交按钮、重置。这一小节讲解提交按钮:当用户需要提交表单信息到服务器时,需要用到提交按钮

语法

<input type=”submit” value=”提交“>

1, type:只有当type值设置为submit时,按钮才有提交作用

2, value按钮上显示的文字

重置按钮

当用户需要重置表单信息到初始时的状态时,比如用户输入“用户名”后,发现书写有误,可以使用重置按钮使输入框恢复到初始状态。只需要把type设置为“reset”就可以

语法

<input type=”reset” value=”重置“>

1, type:只有当type值设置reset,按钮才有重置作用

2, value按钮上显示的文字

form表单中的label标签

label标签不会向用户呈现任何特殊效果,它的作用是为鼠标用户改进了可用性。如果你在 label 标签内点击文本,就会触发此控件

语法

<label for=”控件id名称“> </label>

HTML5

更简化的语法:

  • <!doctype html>
  • <html lang=“zh-CN”>
  • <meta charset=“utf-8”>
  • 不区分大小写  HTML = HtMl
  • checked=“checked” à checked
  • <html><head><body>可以省略

      。。。

废除的标签

  • 能用css替代的标签:basefont, font, center
  • Frame相关的标签,只支持iframeframeset, frame, noframes
  • 只有部分浏览器支持的标签:applet, bgsound
  • 其他废除的标签:rb, dir, listing, xmp

废除了一些和样式相关的属性

HTML5 新增标签

  • <section></section> 表示页面中的一个内容区块,不用作排版
  • <article></article> 表示与上下文不相干的独立内容,比如说文章
  • <aside></aside> 表示与文章相关的辅助信息,如文章后面的推荐阅读
  • <header></header> 页眉
  • <footer></footer> 页脚
  • <nav></nav> 导航栏
  • <figure></figure> 标签规定独立的流内容(图像、图表、照片、代码等等)。figure 元素的内容应该与主内容相关,但如果被删除,则不应对文档流产生影响
  • <figcaption></figcaption> 标签定义 figure 标题(caption)。figcaption元素应该被置于 “figure” 元素的第一个或最后一个子元素的位置
  • <video></video> 视频标签
  • <audio></audio> 音频标签
  • <embed /> 嵌入标签,可以是视频、音频、flash等多媒体内容
  • <mark></mark> 替换文本的背景色来标记文本
  • <progress max=“100” value=“85”></progress> 进度条
  • <canvas></canvas> 绘图,替代flash
  • <details><summary>always show</summary>something can be hidden</details>
  • <datalist></datalist>

HTML5 新增属性

  • <html manifest=“xxx.manifest”>
  • <meta charset=“utf-8”>
  • <link rel=‘icon’ href=“URL” type=image/gif sizes=“16×16”> //目前几乎没有主流浏览器支持 sizes 属性
  • <script defer src=“*.js”></script>
  • <script async src=“*.js”></script>
  • <a media=“tv href=“www.baidu.com hreflang=“zh ref=“external”>baidu</a>
  • <ol start=”50” reversed></ol>
  • <style scoped></style>
  • <iframe seamless srcdoc=“<h1>hello</h1>” sandbox src=www.baidu.com> </iframe>

HTML5 新增全局属性

  • data-*
  • Hidden
  • Tabindex
  • spellcheck=”true”
  • contenteditable=“true”

 

Python中list的遍历

在python中,若要遍历一个list而且需要在遍历时修改list,则需要十分注意,因为这样可能会导致死循环,例如:

In [10]: ls = ['hello', 'world', 'bugggggggg']

In [11]: for item in ls:
   ....:     if len(item) > 5:
   ....:         ls.insert(0, item)
   ....:         print ls
   ....:         
['bugggggggg', 'hello', 'world', 'bugggggggg']
['bugggggggg', 'bugggggggg', 'hello', 'world', 'bugggggggg']
['bugggggggg', 'bugggggggg', 'bugggggggg', 'hello', 'world', 'bugggggggg']
...

所以,为了安全起见,在遇到需要修改列表的时候,都不对列表本身进行遍历,而是创建一个列表的备份,然后对这个备份进行遍历,从而避免了上述情形。例如:

In [20]: In [10]: ls = ['hello', 'world', 'bugggggggg']

In [21]: for item in ls[:]:
   ....:     if len(item) > 5:
   ....:         ls.insert(0, item)
   ....:         

In [22]: print(ls)
['bugggggggg', 'hello', 'world', 'bugggggggg']

 

Python中的参数传递与解析

Python传递命令行参数

Python的命令行参数传递和C语言类似,都会把命令行参数保存到argv的变量中。对于python而言,argv是sys模块中定义的一个list。与C语言不同的是,python中并没有定义argc,要获得参数的个数,需要使用len(sys.argv)

当用户使用’python -c “command” ‘来运行一条python语句时,argv中保存的是[‘-c’]及”command”后面的参数,例如:

$ python -c 'import sys
print sys.argv' hello world
['-c', 'hello', 'world']

当用户使用’python -m “module” ‘来运行一个模块时,argv中保存的是模块名及”module”后面的参数,例如:

$ python -m 'show_args' hello world
['/home/kelvin/tmp/show_args.py', 'hello', 'world']

当运行python脚本时,argv中保存的是脚本名及其后面的参数:

$ python show_args.py hello world
['show_args.py', 'hello', 'world']
length of argv: 3

$ cat show_args.py 
#!/bin/env python

import sys

print sys.argv
print "length of argv: " + str(len(sys.argv))

使用标准库getopt解析选项和参数

getopt模块和C语言中的getopt函数有着一样的API,熟悉C语言的同学可快速上手。

# -*- coding: utf-8 -*-
#!/bin/env python

import getopt
import sys


def usage():
    print("Usage:")
    print(sys.argv[0] + ' -i input_file -o output_file')


def main():
    try:
        opts, args = getopt.getopt(sys.argv[1:], "ho:i:", ["help", "output=", "input="])
    except getopt.GetoptError as err:
        # print help information and exit:
        print("[" + err.opt + "]" + err.msg)
        usage()
        sys.exit(2)
    output = None
    input = None
    for o, a in opts:
        if o in ("-i", "--input"):
            input = a
        elif o in ("-h", "--help"):
            usage()
            sys.exit()
        elif o in ("-o", "--output"):
            output = a
        else:
            assert False, "unhandled option"
    print("Input file: %s" % (input))
    print("Output file: %s" % (output))

if __name__ == "__main__":
    main()

getopt需要传入3个参数:

1.  需要解析的字符串,即sys.argv[1:]

2. 短选项集合。其中跟冒号的短选项需要后接参数,如’o:’表示’-o’选项需要接参数。

3. 长选项列表。其中跟等号的长选项需要后接参数。

getopt返回一个元组,元组包括两个列表opts和args。opts的元素是一个元组,保存了解析好的选项和参数对。args保存了除去所有选项和选项的参数之外,剩下的所有参数。

如果解析出错则会抛出GetoptError异常,该异常有一个参数err。err.opt是出错时正在解析的选项,err.msg是错误消息。

出错的情况包括:

1. 选项没有在传入参数中的短选项或者长选项列表定义。

2. 需要带参数的选项没有跟参数。

3. 不需要带参数的长选项带了参数。

4. 其他。

kelvin@kvm:~/tmp$ python parse_args.py --help=out
[help]option --help must not have an argument
Usage:
parse_args.py -i input_file -o output_file
kelvin@kvm:~/tmp$ python parse_args.py -i input_file.txt 
Input file: input_file.txt
Output file: None
kelvin@kvm:~/tmp$ python parse_args.py -i input_file.txt --output="hello_world.txt"
Input file: input_file.txt
Output file: hello_world.txt
kelvin@kvm:~/tmp$ python parse_args.py -i input_file.txt -o "output.txt"
Input file: input_file.txt
Output file: output.txt

使用标准库argparse来解析选项和参数

argparse模块功能更加强大,例如可以自动生成help文档等,使用起来也更加简便,只需要三个步骤即可。第一步,创建一个ArgumentParser对象:

parser = argparse.ArgumentParser(description='Description of the program')

第二步,添加需要解析的选线和参数:

parser.add_argument('integers', metavar='N', type=int, nargs='+',
                    help='an integer for the accumulator')
parser.add_argument('--sum', dest='accumulate', action='store_const',
                    const=sum, default=max,
                    help='sum the integers (default: find the max)')

第三部,开始解析:

args = parser.parse_args()

ArgumentParser

 class argparse.ArgumentParser(prog=None, usage=None, 
description=None, epilog=None, parents=[], 
formatter_class=argparse.HelpFormatter, prefix_chars='-',
 fromfile_prefix_chars=None, argument_default=None, 
conflict_handler='error', add_help=True, allow_abbrev=True)

常用的参数解释如下:

prog: 指定程序的名字,默认为sys.argv[0].

usage: 描述程序该如何使用的字符串,默认会根据添加的参数和选项自动生成

description: 描述程序的功能,默认为空

epilog: epilog指定的字符串将会显示在帮助文档的最后

parents: 一个 ArgumentParser对象的列表,这些对象的选项和参数也会被继承

add_help: 添加-h/–help选项,默认为True

allow_abbrev: 允许长选项的缩写,默认为True

add_argument

 ArgumentParser.add_argument(name or flags...[, action]
[, nargs][, const][, default][, type][, choices][, required]
[, help][, metavar][, dest])

name将会作为解析后返回的对象args的属性,存储参数的值,flags定义指定的选项,flag的名字也会作为解析后返回的对象的属性,存储该选项的参数。例如:

parser.add_argument('-f', '--foo')
parser.add_argument('arg0')
args = parser.parse_args()
print(args.foo)
print(args.arg0)

执行结果如下:

$./arg_parse.py --foo hello world
hello
world

nargs指定选项参数或者参数本身的个数。例如:

parser.add_argument('-f', '--foo', nargs=2)
args = parser.parse_args()
print(args.foo)

执行结果如下:

$./arg_parse.py --foo hello world
['hello', 'world']

argparse会将–foo选项后面的两个参数都作为–foo的参数处理。

action指定argparse如何处理该选项的参数,共有8个值可选。

  1. ‘store’: 默认值,表示存储参数,如上面例子中的args.foo存储hello world.
  2. ‘store_const’: 存储常量,常量的值位于const参数中。如:
    $ cat arg_parse.py 
    #!/usr/bin/env python
    
    import argparse
    
    parser = argparse.ArgumentParser()
    parser.add_argument('-f', '--foo', action='store_const', const=1024)
    args = parser.parse_args()
    print(args.foo)
    
    $ ./arg_parse.py -f
    1024
    

     

  3. ‘store_true’或者’store_false’:和’store_const’类似,存储的值为True或者False

  4. ‘append’:连个同样的选项的参数会被放到同一个list里面,例如:
     

    $ cat arg_parse.py 
    #!/usr/bin/env python
    
    import argparse
    
    parser = argparse.ArgumentParser()
    parser.add_argument('-f', '--foo', action='append')
    args = parser.parse_args()
    print(args.foo)
    
    $ ./arg_parse.py --foo 1 --foo 2 -f 3
    ['1', '2', '3']

     

  5. ‘append_const’: 可将多个常量存放到一个list中,选项出现几次,list中的常量就出现几次,例如:
     

    $ cat arg_parse.py 
    #!/usr/bin/env python
    
    import argparse
    
    parser = argparse.ArgumentParser()
    parser.add_argument('-f', '--foo', action='append_const', const="1024")
    args = parser.parse_args()
    print(args.foo)
    
    $ ./arg_parse.py --foo --foo -f
    ['1024', '1024', '1024']

     

  6. ‘count’:  存储选项出现的次数。例如:
     

    $ cat arg_parse.py 
    #!/usr/bin/env python
    
    import argparse
    
    parser = argparse.ArgumentParser()
    parser.add_argument('-v', '--verbose', action='count')
    args = parser.parse_args()
    print(args.verbose)
    
    $ ./arg_parse.py -vvv
    3
    
    $ ./arg_parse.py -v --verbose -v
    3

     

  7. ‘help’: 当出现这个选项时,程序打印help文档然后退出。

  8. ‘version’: 当出现这个选项时,程序打印版本信息然后退出,版本信息可通过version定义,例如:
     

    $cat arg_parse.py
    #!/usr/bin/env python
    
    import argparse
    
    parser = argparse.ArgumentParser(prog="wchat")
    parser.add_argument('-v', '--version', action='version', version='%(prog)s 3.8.5')
    args = parser.parse_args()
    
    $ ./arg_parse.py --version
    wchat 3.8.5

     

required指定该参数或者选项是必须提供的,否则会报错退出。

type指定参数的类型,可以是任何python内建的数据类型如int等,也可以是自定义的类型转换函数的函数名。例如:

$ cat ./arg_parse.py 
#!/usr/bin/env python

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('-f', '--foo', type=int)
args = parser.parse_args()
print(args.foo)

$ ./arg_parse.py -f 12
12

$ ./arg_parse.py -f '12'
12

$ ./arg_parse.py -f hello
usage: arg_parse.py [-h] [-f FOO]
arg_parse.py: error: argument -f/--foo: invalid int value: 'hello'

choices指定一组参数,选项的参数必须从这组参数中来选取。例如:

$ cat arg_parse.py 
#!/usr/bin/env python

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('-f', '--foo', type=int, choices=range(1, 4))
args = parser.parse_args()
print(args.foo)

$ ./arg_parse.py -f3
3

$ ./arg_parse.py -f19
usage: arg_parse.py [-h] [-f {1,2,3}]
arg_parse.py: error: argument -f/--foo: invalid choice: 19 (choose from 1, 2, 3)

help指定参数或者选项的帮助信息,会出现在help文档里。

metavar可以改变帮助文档中选项的参数占位字符串,例如,–foo默认的占位字符串为FOO,可以通过metavar改为foo_arg:

$ cat arg_parse.py 
#!/usr/bin/env python

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('-f', '--foo')
args = parser.parse_args()
print(args.foo)

$ ./arg_parse.py -h
usage: arg_parse.py [-h] [-f FOO]

optional arguments:
  -h, --help         show this help message and exit
  -f FOO, --foo FOO

$ cat arg_parse.py 
#!/usr/bin/env python

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('-f', '--foo', metavar='foo_arg')
args = parser.parse_args()
print(args.foo)

$ ./arg_parse.py -h
usage: arg_parse.py [-h] [-f foo_arg]

optional arguments:
  -h, --help            show this help message and exit
  -f foo_arg, --foo foo_arg

dest可以修改存储参数的属性名,例如:

$ cat arg_parse.py 
#!/usr/bin/env python

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('-f', '--foo', dest='bar')
args = parser.parse_args()
print(args.bar)

$ ./arg_parse.py -f hello
hello

小结

getopt虽然提供了接近Unix C的用户接口,方便了熟悉Unix C的程序猿/媛们,但argparse模块功能更为强大,使用起来也更为简洁,所以大多数的python项目都采用argparse来解析参数。

"