scss基础知识整理
scss的环境搭建
这里使用koala,避免分部下载ruby什么的,到koala的官网下载软件即可。
Koala的使用——打开项目
打开软件的首界面如下图所示:
方法一:
点击左上角的加号选择项目所在的文件夹即可,koala会自动导入文件夹中的相关文件,在页面下方 可以选择文件类型的过滤,如styles,scripts等,当项目中文件有增加或者减少时,需要点击界面 上方的refresh按钮进行刷新。
方法二:
直接选中项目文件夹拖拽到首界面即可。
Koala的使用——scss的相关设置
有关scss的基本设置:
点击首界面左上角的齿轮符号可以打开设置界面,页面如上图所示。在基本设置中点击sass,在输出 中可以选择scss的输出方式,输出方式有四种,具体区别待会会说明。
设置scss编译后的输出路径:
在首页面中右边的栏目中选中需要编译的scss文件,点击鼠标右键,在弹出的菜单中选中设置输出路径, 如下图所示。在设置输出文件名时,需要加上.css后缀。
scss的四种输出模式
现在以下面的scss代码为例:
???nav { ???????ul { ???????????margin: 0; ???????????padding: 0; ???????????list-style: none; ???????} ???????????????li { display: inline-block; } ???????????????a { ???????????display: block; ???????????padding: 6px 12px; ???????????text-decoration: none; ???????} ???}
嵌套输出方式nested
输出的css格式如下:
???nav ul { ???????margin: 0; ???????padding: 0; ???????list-style: none; } ???nav li { ???????display: inline-block; } ???nav a { ???????display: block; ???????padding: 6px 12px; ???????text-decoration: none; }
展开输出方式expanded
输出的css格式如下:
???nav ul { ???????margin: 0; ???????padding: 0; ???????list-style: none; ???????} ???nav li { ???????display: inline-block; ???} ???nav a { ???????display: block; ???????padding: 6px 12px; ???????text-decoration: none; ???}
紧凑输出方式compact
输出的css格式如下:
???nav ul { margin: 0; padding: 0; list-style: none; } ???nav li { display: inline-block; } ???nav a { display: block; padding: 6px 12px; text-decoration: none; } ???
压缩输出方式compressed
输出的css格式如下:
???nav ul{margin:0;padding:0;list-style:none}nav li{display:inline-block}nav a{display:block;padding:6px 12px;text-decoration:none} ??
scss的基本语法
变量
变量使用“$”符号声明,! default表明这是默认变量,在花括号中定义的是局部变量,在花括号外 中定义的是全局变量,在默认变量前进行重复定义同名变量可以覆盖默认变量。
???????$width: 300px; ?/*变量的声明*/ ???????$height: 100px; /*全局变量*/ ???????$color: blue; ???????$baseFontSize: 20px !default; /*默认值*/ ???????$baseLineHeight: 24px; ?/*覆盖默认值*/ ???????$baseLineHeight: 12px !default; ????????.demo{ ???????????width: $width; ???????????height: $height; ??????????? ???????????line-height: $baseLineHeight; ???????????color: $color; ???????????????????$color: red; ???/*局部变量*/ ???????????a{ ???????????????color: $color; ???????????} ????????} ????
数据类型
???????/*数值类型(带单位也是数值型)*/ ???????$number1: 10; ???????$number2: 10px; ???????$number3: 1em; ???????????????/*字符串类型*/ ???????$string1: "string"; ???????$string2: string; ???????????????/*颜色类型*/ ???????$color1: blue; ???????$color2: #fff; ???????$color3: rgba(0,0,0,.5); ???????????????/*布尔类型*/ ???????$bool1: true; ???????$bool2: false; ???????????????/*空值类型*/ ???????$null1: null; ???????????????/*值列表类型*/ ???????$list: sans-serif; ???????$properties: (margin, padding); ???????/*map类型*/ ???????$map: ( ???????????primary: ( ???????????????bgcolor: red, ???????????????text-color: blue ???????????), ???????????defalut: ( ???????????????bgcolor: green, ???????????????text-color: yellow ???????????) ???????) ???
嵌套
嵌套包括选择器嵌套,属性嵌套,伪类嵌套。“&”符号用于获取父元素
???????nav{ ???????????/*简单的选择器嵌套*/ ???????????a{ ???????????????color: red; ???????????} ???????????/*引用父元素的选择器嵌套*/ ???????????header &{ ???????????????color: blue; ???????????} ???????????/*属性嵌套*/ ???????????border: { ???????????????top: 1px solid red; ???????????????bottom: 1px solid green; ???????????} ???????????/*伪类嵌套*/ ???????????&:before { ???????????????content: ""; ???????????} ????????????} ???
注释
scss中注释包括//和/**/两种,第一种在输出的css文件中不保留,第二种会保留,不过样式表中的注释可能位置为变乱。如下:
原来的scss中的注释
???????????//这里的注释不会被保留,下面的注释会保留不过位置会改变 ???????????$width: 300px; ?/*变量的声明*/ ???????????$height: 100px; /*全局变量*/ ???????????.size{ ???????????????width: $width; ???????????????height: $height; ???????????} ???????
编译后的css中的注释
???????????/*变量的声明*/ ???????????/*全局变量*/ ???????????.size { ???????????????width: 300px; ???????????????height: 100px; ???????????} ???????
基本运算
运算包括四则运算,颜色运算和字符串的加法运算。
一些规则说在前面
下面的可换算单位是指一些绝对单位,如px,in,cm,mm等;不可换算单位是一些相对单位,如em,rem等
带单位的运算之后的单位如果能被识别就能运算,不能被识别就不能运算。如1px+2in,因为换算成px,可以被识别,能够运算;又如2px*3px,单位变成px的平方不能被识别,不能运算。
加减法
操作数单位不同时,都是可换算单位可以进行加减计算,但是含有相对单位不能进行计算。
???????????$sidebar-width: 220px; ???????????$content-width: 720px; ???????????$gap-width: 20px; ???????????/** ???????????????加法 ???????????????不同的绝对单位可以进行计算,因为单位可以换算。不同的相对单位不能进行计算。 ???????????*/ ???????????.container{ ???????????????width: $sidebar-width+$content-width+$gap-width; ???????????????height: 20px + 8in + 1cm + 1pt + 1pc - 1mm; ???????????????margin-left: 1 + 1em; ???????????????margin: 0 auto; ???????????} ???????
乘法
???????????/** ???????????????乘法 ???????????????乘法只能带一个单位,因为两个单位相乘就变成了不能识别的单位,如px * px = (px)2 ???????????*/ ???????????.box{ ???????????????width: 10px * 2; ???????????} ???????
除法
除法的特别地方在于“/”符号在css中有特定的含义,所以在使用时要告诉编译器这是除法运算。
???????????/** ???????????????除法 ???????????????由于“/”符号在css中已作为一种符号使用,所以要让编译器知道是数学表达式才会运行除法。 ???????????????除法可以带单位(可换算单位) ???????????*/ ???????????$margin: 20px; ???????????.divide{ ???????????????width: (100px / 2); /*加上括号告诉编译器这是运算*/ ???????????????height: 100px / 2 + 3px; /*加上加或减法告诉编译器这是运算*/ ????????????????margin: $margin / 2; /*变量告诉编译器这是运算*/ ???????????????padding: (100px / 20cm); ????????????} ???????
颜色运算
颜色的运算规则:
颜色运算符号四则运算规则。
十六进制的运算是对应位进行运算,如#112233 + #112233 = #224466
rgba运算是rgba()函数的对应参数进行运算
运算极限:颜色最小只能是#000编译成black,最大只能是#fff编译成white;透明度最小只能是0,最大只能是1
???????????.color{ ???????????????color: #e89 + #e3f; ???????????????background: #ccc * 2; ???????????} ???????
字符串运算
加法就是进行字符串的拼接,如下面代码编译后content变为"Hello sass!"
???????????/*字符串运算*/ ???????????.string{ ???????????????content: "Hello" + " sass!"; ???????????} ???????
语句
语句包括判断语句和循环语句,语句一般用在混合宏中。
判断语句@if
???????????@mixin blockOrHidden($boolean:true) { ???????????????@if $boolean { ???????????????????display: block; ???????????????} ???????????????@else { ???????????????????display: none; ???????????????} ???????????} ???????
循环语句@for
循环语句@for有两种方式:
一:@for $i from (start) through (end)
二:@for $i from (start) to (end)
$i表示变量;(start)表示起始值;(end)表示结束值
through包括(end),to不包括(end)
???????????/*through方式*/ ???????????@for $i from 1 through 3 { ???????????????.item-#{$i} { width: 2em * $i; } ???????????} ???????????/*to方式*/ ???????????@for $i from 1 to 3 { ???????????????.item-#{$i} { width: 2em * $i; } ???????????} ???????
循环语句@while
下面使用的#{$type}为插值,作用是进行替换
???????????$types: 4; ???????????$type-width: 20px; ???????????/**/ ???????????@while $types > 0 { ???????????????.while-#{$types} { ???????????????????width: $type-width + $types; ???????????????} ???????????????$types: $types - 1; ???????????} ???????
变量语句@each
@each语句可以遍历列表和数组
scss文件:
???????????/**********混合宏声明*******/ ???????????@mixin list{ ???????????????$list: a b c; ???????????????/*遍历列表*/ ???????????????@each $item in $list{ ???????????????????.item-#{$item}{ ???????????????????????content: $item; ????????????????????} ???????????????} ???????????} ???????????@mixin arr{ ???????????????$arr: (d,e,f); ???????????????/*遍历数组*/ ???????????????@each $i in $arr{ ???????????????????.i-#{$i}{ ???????????????????????content: $i; ???????????????????} ???????????????} ???????????} ???????????/*****混合宏调用*****/ ???????????@include list; ???????????@include arr; ???????
编译后的css文件:
???????????????/*遍历列表*/ ???????????????.item-a { ?????????????????content: a; ???????????????} ???????????????????????????????.item-b { ?????????????????content: b; ???????????????} ???????????????????????????????.item-c { ?????????????????content: c; ???????????????} ???????????????????????????????/*遍历数组*/ ???????????????.i-d { ?????????????????content: d; ???????????????} ???????????????????????????????.i-e { ?????????????????content: e; ???????????????} ???????????????????????????????.i-f { ?????????????????content: f; ???????????????} ???????
插值和混合宏
插值——#{}
插值就是替换值得意思,如#{$i}就是这里用$i替换的意思。
混合宏调用时不能使用插值,不过继承可以。
???????????$properties: (margin, padding); /*属性集*/ ???????????$data: 1; ???????????/*************混合宏中的插值*****************/ ???????????/*属性使用插值替换*/ ???????????@mixin set-value($side, $value){ ???????????????/*遍历属性*/ ???????????????@each $prop in $properties{ ???????????????????#{$prop}-#{$side}: #{$data}; ???????????????} ?????????????????} ???????????/*类名使用插值替换*/ ???????????@mixin generate-sizes($class, $small, $medium, $big) { ???????????????.#{$class}-small { } ???????????????.#{$class}-medium { } ???????????????.#{$class}-big { } ???????????} ???????????/*继承使用插值替换*/ ???????????%updated-status { ??????????????? ???????????????background: #F00; ???????????} ???????????.selected-status { ???????????????font-weight: bold; ???????????} ???????????$flag: "status"; ???????????//不过混合宏的调用不能使用插值 ???????????/*************混合宏的调用*******************/ ???????????.login-box{ ???????????????@include set-value(top, 14px); ???????????} ???????????@include generate-sizes("header-text", 12px, 20px, 40px); ???????????.navigation { ???????????????@extend %updated-#{$flag}; ???????????????@extend .selected-#{$flag}; ???????????} ???????????.footer{ ???????????????@extend .#{selected}-status; //#{}里面可以是变量,字符串(不写引号也行) ???????????} ???????
混合宏
混合宏就像javascript中的自定义函数一样,它可以被调用,可以带参数,它用于代码的复用。
这里特别说一下variable...这种写法是指该变量含有多个值得意思,如果除了这个变量还有其它变量参数的话,必须把这个变量 写在最右边,且这种参数一个混合宏最多只能有一个。
???????????/*************混合宏的声明******************/ ???????????/*不带参的宏*/ ???????????@mixin border-radius{ ???????????????-webkit-border-radius: 5px; ???????????????-moz-border-radius: 5px; ???????????????-ms-border-radius: 5px; ???????????????-o-border-radius: 5px; ???????????????border-radius: 5px; ???????????} ???????????/*带参的宏*/ ???????????@mixin border-radius($radius: 5px){ ???????????????-webkit-border-radius: $radius; ???????????????-moz-border-radius: $radius; ???????????????-ms-border-radius: $radius; ???????????????-o-border-radius: $radius; ???????????????border-radius: $radius; ???????????} ???????????/*带多个参数的宏*/ ???????????@mixin box-shadow($color,$shadows...){ ???????????????color: $color; ???????????????@if length($shadows) >= 1 { ???????????????-webkit-box-shadow: $shadows; ???????????????box-shadow: $shadows; ???????????????} @else { ???????????????$shadows: 0 0 2px rgba(#000,.25); ???????????????-webkit-box-shadow: $shadow; ???????????????box-shadow: $shadow; ???????????????} ???????????} ???????????/**************混合宏的调用******************/ ???????????/*不带参的宏*/ ???????????.demo1{ ???????????????@include border-radius; ???????????} ???????????/*带参的宏*/ ???????????.demo2{ ???????????????@include border-radius(3px); ???????????} ???????????/*带多个参数的宏*/ ???????????.demo3{ ???????????????@include box-shadow(red,.0 0 1px rgba(#000,.5),0 0 2px rgba(#000,.2)) ???????????} ???????
占位符——%
占位符通过继承指令@extend调用
占位符不像普通的形式会被编译后的的css文件保留
编译前:
???????/*占位符不保留*/ ???????%bubaoliu { ???????????color: red; ???????} ???????/*普通的类形式会保留*/ ???????.baoliu{ ???????background: red; ???????} ???????.required{ ???????????@extend %bubaoliu; ???????????@extend .baoliu; ???????} ???
编译后:
???????/*占位符不保留*/ ???????.required { ???????????color: red; ???????} ???????????????/*普通的类形式会保留*/ ???????.baoliu, .required { ???????????background: red; ???????} ???
@规则指令
@import
@import是导入文件的指令,如果没有指明文件后缀,默认导入.scss或.sass文件
如果出现以下四种情况,则会编译成css的@import指令
扩展名是.css,文件名以http://开头,文件名是url(),指令中包含媒体查询如:
???????@import "foo.css"; ???????@import "foo" screen; ???????@import "http://foo.com/bar"; ???????@import url(foo); ???
@media
@media是媒体查询指令,编译时它始终冒泡到外面,且可嵌套
编译前:
???????@media screen { ???????????.sidebar { ???????????????@media (orientation: landscape) { ???????????????width: 500px; ???????????????} ???????????} ???????} ???
编译后:
???????@media screen and (orientation: landscape) { ???????????.sidebar { ???????????????width: 500px; ????????????} ????????} ???
@extend
@extend是继承指令,它用于扩展选择器或者占位符,而且它会把同时调用同一个选择器或者站位符的选择器样式合并
???????????/*继承会将选择器合并*/ ???????????.btn { ???????????????border: 1px solid #ccc; ???????????} ???????????.btn-danger { ???????????????background: red; ???????????????@extend .btn; ???????????} ???????????.btn-info { ???????????????background: blue; ???????????????@extend .btn; ???????????} ???
@at-root
@at-root是把自己变成根选择器的指令。
编译前:
???????.demo { ???????????animation: motion 3s infinite; ???????????@at-root { ????????????????@keyframes motion { ???????????????????0%{ ???????????????????????color: map-get($colors, red); ???????????????????} ???????????????????100%{ ???????????????????????color: map-get($colors, red); ???????????????????} ???????????????} ???????????} ???????} ???
编译后:
???????.demo { ???????????animation: motion 3s infinite; ???????} ???????@keyframes motion { ???????????0%{ ???????????????color: map-get($colors, red); ???????????} ???????????100%{ ???????????????color: map-get($colors, red); ???????????} ???????} ???
@deug
@debug指令用于调试,如果代码出错会在控制台输出提示
@error
@error指令用于输出自定义错误信息,是自定义异常
@warn
@warn指令用于输出警告信息
scss内置的功能函数
字符串函数
unqote($string)和quote($string)函数
这两个函数用于添加引号和删除引号,需要注意的是:
quote()只能增加双引号,如果字符串本身有引号,编译后都为双引号;如果字符串中间有引号或者空格,则会报错。
unqote()只能删除字符串两边的引号,而不能删除中间的引号;如果字符串本身没有引号,则返回字符串本身。
to-upper-case()和to-lower-case()函数
这两个函数用于字符串的大小写转换
数字函数
数字函数包括percentage(),round(),ceil(),floor(),abs(),min(),max(),random()
这些函数的功能和javascript中没有区别,不过需要跟前面说的运算一样,注意运算后单位的合法性。
列表函数
???????$list: 10px, 20px, 30px; ???????/*length($list)函数获取列表的长度*/ ???????@for $i from 1 through length($list){ ???????????.box-#{$i}{ ???????????????/*nth($list,$index)获取对应位置的列表的值,位置的标号从1开始*/ ???????????????width: nth($list,$i); ???????????} ???????} ????????????????$list1: blue, red; ???????$list2: yellow, white; ???????/*join函数可以组合两个列表,形成一个新的列表*/ ???????$list3: join($list1,$list2); ???????/* ???????????结果转换成: ???????????list3: blue, red, yellow, white ????????*/ ???????/*append函数用于在列表的后面插入列表项*/ ???????$list4: append($list1,green); ???????/* ???????????结果转换成: ???????????list4: blue, red, green ???????*/ ???????/* ???????????注意:join($list1,$list2,$separator)和append($list,$separator)函数的$separator ???????????当没有指定$separator时, ???????????join函数: ???????????先看$list1的格式,它是什么格式拼接后就是什么格式 ???????????如果$list1只有一项,就看$list2的格式,它是什么格式就以什么格式拼接 ???????????如果$list2也只有一项,就用空格拼接。 ???????????append函数: ???????????先看$list的格式,它是什么格式就用什么格式连接 ???????????如果$list只有一项,就用空格连接 ???????????????????$separator参数用来指定连接的格式: ???????????auto: 自动就是上面的规则 ???????????comma: 以逗号连接 ???????????space: 以空格连接 ???????*/ ???????????????$list5: 1px 2px 3px, solid dashed dotted, blue red green; ???????/*将列表分隔成多维列表*/ ???????$arr: zip($list); ???????/* ???????????结果转换成: ???????????nth($arr,1): 1px solid blue ???????????nth($arr,2): 2px dashed red ???????????nth($arr,3): 3px dotted green ???????*/ ???????????????/*index($list,$value)用于返回对应值在列表的索引,索引从1开始*/ ???????$index: index(1px solid red, 1px); ????????//结果:$index: 1 ???????//如果在列表没有找到对应值,就返回false ???
Introspection判断型函数
???????//type-of(value)返回对应值得类型 ???????$type-of1: type-of(100); //结果:"number" ???????$type-of2: type-of("abcd"); //结果:"string" ???????$type-of3: type-of(true); //结果:"bool" ???????$type-of4: type-of(blue); //结果:"color" ????????????????//unit(value)返回对应值的单位 ???????$unit1: unit(100px); //结果: $unit1: "px" ???????$unit2: unit(100); //结果:$unit2: "" ???????????????//unitless(value)判断对应值是否不含单位 ???????$unitless1: unitless(100); //结果: $unitless1: true ???????$unitless2: unitless(100px); //结果 $unitless2: false ???????????????//comparable(value1,value2)判断两个数是否可以进行“加,减或者合并” ???????$comparable1: comparable(2px,1%); //结果:false ???????$comparable2: comparable(2px,1cm ); //结果:true ???
Miscellaneous函数
???????//三元条件函数 if($condition,$if-true,$if-false)的使用 ???????$if1: if(true,1px,2px); //结果:$if1: 1px ???????$if2: if(false,1px,2px); //结果:$if2: 2px ????
Map的函数
???????????????/*定义Map*/ ???????$map:( ???????????dribble: #ea4c89, ???????????facebook: #3b5998, ???????????github: #171515, ???????????google: #db4437, ???????????twitter: #55acee ???????); ???????$map1:( ???????????color: red ???????); ???????$map2:( ???????????text-color: blue ???????); ???????//map-get($map,$key)函数获取对应$key的$value ???????$value: map-get($map,facebook); //结果:$value: #3b5998 ???????????????//map-has-key($map,$key)函数判断Map是否含有对应的$key ???????$hasKey: map-has-key($map, facebook); //结果:$hasKey: true ???????????????//map-keys($map)函数返回map所有的$key ???????$keyList: map-keys($map); //结果:$keyList: "dribble","facebook","github","google","twitter" ???????????????//map-values($map)函数返回map所有的$value ???????$valueList: map-values($map); //结果:$valueList: #ea4c89,#3b5998,#171515,#db4437,#55acee ???????????????//map-merge($map1,$map2)函数将两个map合并生成一个新的map ???????$mergeList: map-merge($map1,$map2); ????????/* ???????????结果:$mergeList: ( ???????????????????color: red, ???????????????????text-color: blue ???????????????) ???????*/ ???????????????????//map-remove($map,$key)函数删除一个$key,返回一个新的map ???????$removeMap: map-remove($map,facebook); ???????/* ???????????结果:$removeMap: ( ???????????????????dribble: #ea4c89, ???????????????????github: #171515, ???????????????????google: #db4437, ???????????????????twitter: #55acee ???????????????) ???????*/ ???????????????//keywords($args)函数用于动态创建map,与混合宏使用 ???????@mixin map($args...){ ???????????@debug keywords($args); ???????} ???????????????@include map( ???????????$dribble: #ea4c89, ???????????$facebook: #3b5998, ???????????$github: #171515, ???????????$google: #db4437, ???????????$twitter: #55acee ???????); ???????????????/* ???????????结果: ????????????DEBUG: (dribble: #ea4c89, facebook: #3b5998, github: #171515, google: #db4437, twitter: #55acee) ???????*/ ???
颜色函数
RGB函数
???????$red: 255; ???????$green: 255; ???????$blue: 255; ???????$alpha: 0.5; ???????$color: #f36; ???????$mixColor1: #f00; ???????$mixColor2: #00f; ???????//根据红、绿、蓝三个值创建一个颜色: rgb()函数参数类型为number ???????$color1: rgb($red,$green,$blue); ???????????????????????//根据红、绿、蓝、透明度四个值创建一个颜色, rgba()函数参数类型为number ???????$color2: rgba($red,$green,$blue,$alpha); ???????????????//获取一个颜色中的红、绿、蓝部分创建一个颜色 ???????$red1: red($color); ???????$green1: green($color); ???????$blue1: blue($color); ???????????????//mix($color1,$color2,$weight)函数用于混合函数,$weight指第一种颜色的比例 ???????//如果不定义$weight,默认为.5 ???????$mixColor: mix($mixColor1,$mixColor2,.75); ???
HSL函数
???????$baseColor: #ad141e; ???????//将颜色变亮或者变暗,第二个参数是变亮的程度,如10%就是增加10%的亮度 ???????.lighten{ ???????????background: lighten($baseColor,10%); ???????} ???????.darken{ ???????????background: darken($baseColor,10%); ???????} ???????//增加或减少颜色的饱和度 ???????.saturate{ ???????????background: saturate($baseColor,30%); ???????} ???????.desaturate{ ???????????background: desaturate($baseColor,30%); ???????} ???????//改变色相,第二个参数在-360deg和360deg之间,也可以是百分数 ???????.adjust-hue-deg{ ???????????background: adjust-hue($baseColor, 30deg); ???????} ???????.adjust-hue-per{ ???????????background: adjust-hue($baseColor, 30%); ???????} ???????//将饱和度直接设为0 ???????.grayscale{ ???????????background: grayscale($baseColor); ???????} ????
opacity函数
???????//获取颜色透明度,颜色透明度默认为1 ???????$alpha: alpha(red); ???????$opacity: opacity(red); ???????????????//上面说到的rgba()也可以设置透明度 ???????????????//将两种颜色的透明度进行加法运算,让其更不透明,返回一个新的颜色 ???????$opacify: opacify(rgba(22,34,235,.6),.2); ???????$fade-in: fade-in(rgba(22,34,235,.6),.2); ???????//结果:rgba(22,34,235,.8) ???????????????//将两种颜色的透明度进行减法运算,让其更加透明,返回一个新的颜色 ???????$transparentize: transparentize(red,.5); ???????$fade-out: fade-out(red,.5); ???????//结果:rgba(255,0,0,.5); ???
注意事项
混合宏、占位符、继承的比较
混合宏可以带参数,但是相同的调用选择器不会组合;
占位符不会在编译后的css文件中保留,相同的调用选择器会进行组合
不使用占位符的继承会在css文件中保留基类,相同的调用选择器会进行组合
scss的基础知识
原文地址:https://www.cnblogs.com/githubMYL/p/8971062.html