jQuery中attr和prop方法的区别

thbcm阅读(164)

相比 attr,prop 是 1.6.1 才新出来的,二者从中文意思理解,都是获得/设置属性的方法(attributes 和 properties)。只是,window 或 document 中使用 .attr() 方法在 jQuery1.6 之前不能正常运行,由于 window 和 document 中不能有 attributes。prop 应运而生了。

之前看网上对照二者的文章,更是列出一个表来辨别什么标签下使用 prop,什么标签下使用 attr,谅解我是怠惰的人,最惧怕要背的东西,所以只有自己想一想办法了。

既然我们想知道他们两的区分,最好就看看他们的源代码,不要被代码长度所吓到,我们只看关键的几句:

attr 方法代码(jQuery 版本 1.8.3)

attr: function( elem, name, value, pass ) {   

var ret, hooks, notxml,

nType = elem.nodeType;

// don't get/set attributes on text, comment and attribute nodes

if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {

return;

}

if ( pass && jQuery.isFunction( jQuery.fn[ name ] ) ) {

return jQuery( elem )[ name ]( value );

}

// Fallback to prop when attributes are not supported

if ( typeof elem.getAttribute === "undefined" ) {

return jQuery.prop( elem, name, value );

}

notxml = nType !== 1 || !jQuery.isXMLDoc( elem );

// All attributes are lowercase

// Grab necessary hook if one is defined

if ( notxml ) {

name = name.toLowerCase();

hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );

}

if ( value !== undefined ) {

if ( value === null ) {

jQuery.removeAttr( elem, name );

return;

} else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {

return ret;

} else {

elem.setAttribute( name, value + "" );

return value;

}

} else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {

return ret;

} else {

ret = elem.getAttribute( name );

// Non-existent attributes return null, we normalize to undefined

return ret === null ?

undefined :

ret;

}

}

prop 方法代码(jQuery 版本1.8.3)

prop: function( elem, name, value ) { 

var ret, hooks, notxml,

nType = elem.nodeType;

// don't get/set properties on text, comment and attribute nodes

if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {

return;

}

notxml = nType !== 1 || !jQuery.isXMLDoc( elem );

if ( notxml ) {

// Fix name and attach hooks

name = jQuery.propFix[ name ] || name;

hooks = jQuery.propHooks[ name ];

}

if ( value !== undefined ) {

if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {

return ret;

} else {

return ( elem[ name ] = value );

}

} else {

if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {

return ret;

} else {

return elem[ name ];

}

}

}

attr 方法里面,最关键的两行代码,elem.setAttribute( name, value + “” )和 ret = elem.getAttribute( name ),很明显的看出来,使用的 DOM 的 API setAttribute 和 getAttribute 方法操作的属性元素节点。

而 prop 方法里面,最关键的两行代码,return ( elem[ name ] = value )和 return elem[ name ],你可以理解成这样document.getElementById(el)[name] = value,这是转化成 JS 对象的一个属性。

pandas 常规操作,你学 ’废‘ 了么?

thbcm阅读(180)

一 聚合函数

1. numpy、pandas使用的统计方式
在数组中经常使用的聚合方式
data[['counts', 'ches_name']].agg([np.mean, np.std])
agg({'xx':np.mean, 'xx2':[np.sum, np.std]})
2. 在pandas或者numpy中没有现成的函数可以使用,可以使用transform自定义函数

如: 将指定列的全部数据 * 2

方式一
data['counts'].transform(lambda x: x*2)
方式二:按照函数内既定的规则,进行指定数据的操作
def transform_func(values):
	"""自定义函数,定义数据操作规则"""
	return values*2
data['counts'].transform(transform_func)   # 一维
data1 = data.groupby(by='品牌')['销售额'].transform(tran_func)  # 分组之后自定义聚合

推荐好课:Python 自动化办公

二 透视表 – pivot_table

源码参数分析
def pivot_table(
    data,             # Dataframe,对哪张表进行操作
    values=None,      # 显示的字段
    index=None,       # 行分组键,可以是数组,列表,如果是数组,必须有一样的长度
    columns=None,      # 列分组键
    aggfunc="mean",    # 聚合函数, 默认是mean
    fill_value=None,   # 填充空值, 将为Nan的值填充为对应的值
    margins=False,     # 汇总开关,默认是False
    dropna=True, 
    margins_name="All", # 汇总的列或者行的bolumns,可以指定修改名称
    observed=False,
1、index: 行分组键,分完组后,分组键的取值在行索引的位置上
pd.pivot_table(data, index=['order_id', 'dishes_name'], aggfunc=[np.mean, np.sum], values=['add_inprice', 'counts'])
                                mean                sum       
                         add_inprice counts add_inprice counts
order_id dishes_name                                          
137      农夫山泉NFC果汁100%           0      1           0      1
         凉拌菠菜                      0      1           0      1
         番茄炖牛腩\r\n                 0      1           0      1
         白饭/小碗                     0      4           0      4
         西瓜胡萝卜沙拉                   0      1           0      1
...                              ...    ...         ...    ...
1323     番茄炖秋葵                     0      1           0      1
         芝士烩波士顿龙虾                  0      1           0      1
         芹黄鳝丝                      0      1           0      1
         蒜蓉生蚝                      0      1           0      1
         谷稻小庄                      0      1           0      1
[2778 rows x 4 columns]

2、columns: 列分组键,分完组后,分组键的取值在列索引上

pd.pivot_table(data, columns= ['order_id', 'amounts'], aggfunc=[np.mean, np.sum], values=['add_inprice', 'counts'])
# 列分组键,可以说是行分组键的转置
            mean                                ...  sum                        
order_id    137                           165   ... 1323                        
amounts      1    6    26   27   35   99   9    ...  39  49  58  65  78  80  175
add_inprice  0.0  0.0  0.0  0.0  0.0  0.0  0.0  ...    0   0   0   0   0   0   0
counts       4.0  1.0  1.0  1.0  1.0  1.0  1.5  ...    1   1   1   1   1   1   1
[2 rows x 4956 columns]
3、结合使用
# aggfunc 聚合函数
# fill_value 为空的,怎么显示,默认为Nan
# margins 汇总,默认是不汇总
# margins_name 汇总列或者行字段名称,默认为all
pd.pivot_table(data, index=['dishes_name'], columns='order_id', values='counts', aggfunc=np.sum, fill_value=0, margins=True, margins_name='总')
dishes_name   42度海之蓝   北冰洋汽水   38度剑南春   50度古井贡酒  ...  黄油曲奇饼干  黄花菜炒木耳  黑米恋上葡萄     总
order_id                                         ...                              
137                0        0        0        0  ...       0       0       0     9
165                0        0        1        0  ...       0       1       0    21
166                0        0        0        0  ...       0       0       0     7
171                0        0        0        0  ...       0       0       0    10
177                0        0        0        0  ...       0       0       0     4
...              ...      ...      ...      ...  ...     ...     ...     ...   ...
1314               0        0        1        0  ...       0       0       0    12
1317               0        0        0        0  ...       0       0       0    18
1319               0        0        0        0  ...       0       0       0     9
1323               0        0        1        0  ...       0       0       0    15
总                  5       45        6        5  ...       5      15      18  3088

推荐好课:Python 自动化管理

三 交叉表-crosstab

def crosstab(
    index,   # 行分组键
    columns,  # 列分组键
    values=None,   # 显示的字段
    rownames=None,    # 行name
    colnames=None,     # 列name
    aggfunc=None,      # 聚合函数
    margins=False,      # 汇总
    margins_name: str = "All",   # 汇总列或者行的名称
    dropna: bool = True,
    normalize=False,
基本语法
pd.crosstab(index = data['dishes_name'], columns=data['order_id'], values=data['counts'], aggfunc = np.sum)
dishes_name   42度海之蓝   北冰洋汽水   38度剑南春   ...  黄油曲奇饼干  黄花菜炒木耳  黑米恋上葡萄
order_id                                ...                        
137              NaN      NaN      NaN  ...     NaN     NaN     NaN
165              NaN      NaN      1.0  ...     NaN     1.0     NaN
166              NaN      NaN      NaN  ...     NaN     NaN     NaN
171              NaN      NaN      NaN  ...     NaN     NaN     NaN
177              NaN      NaN      NaN  ...     NaN     NaN     NaN
...              ...      ...      ...  ...     ...     ...     ...
1309             NaN      NaN      NaN  ...     NaN     NaN     NaN
1314             NaN      NaN      1.0  ...     NaN     NaN     NaN
1317             NaN      NaN      NaN  ...     NaN     NaN     NaN
1319             NaN      NaN      NaN  ...     NaN     NaN     NaN
1323             NaN      NaN      1.0  ...     NaN     NaN     NaN
[278 rows x 156 columns]

四 表格合并

1、每个表的列都相同,pd.concat((df1, df2, df3 … ))

axis = 0 : 纵向合并axis = 1:横向合并,索引对应合并

函数源码
def concat(
    objs: Union[Iterable["NDFrame"], Mapping[Label, "NDFrame"]], # 传入的是Df格式
    axis=0,          # 进行合并的方向
    join="outer",    # 默认使用的外连接
    ignore_index: bool = False,  # 重置排序索引
    keys=None,
    levels=None,
    names=None,
    verify_integrity: bool = False,
    sort: bool = False,
    copy: bool = True,
left = pd.DataFrame({'key1': ['K0', 'K0', 'K1', 'K3'],
                     'key2': ['K0', 'K1', 'K0', 'K1'],
                         'A': ['A0', 'A1', 'A2', 'A3'],
                         'B': ['B0', 'B1', 'B2', 'B3']})right = pd.DataFrame({'key1': ['K0', 'K1', 'K1', 'K2'],                       'key2': ['K0', 'K0', 'K0', 'K0'],                          'C': ['C0', 'C1', 'C2', 'C3'],                          'D': ['D0', 'D1', 'D2', 'D3']}) pd.concat((left, right), axis = 0, join = 'inner') # 指定使用内连接,进行合并,默认使用的是outer pd.concat((left, right), axis = 1, join = 'inner')

2、 表合并,解决行索引没有意义情况下,数据行不匹配问题(解决concat横向拼接问题)

def merge(
    left,                # 左表
    right,               # 右表
    how: str = "inner",    # 默认是内连接,
    on=None,               # 必须是两张表中有公共的主键,才能作为主键
    left_on=None,          # 左表主键
    right_on=None,         # 右表主键
    left_index: bool = False,
    right_index: bool = False,
    sort: bool = False,
    suffixes=("_x", "_y"),
    copy: bool = True,
    indicator: bool = False,
    validate=None,

(1) 两表中有相同的主键

on 连接的主键,两表中共有的主键
how 连接的方式,默认使用的是内连接
outer外连接,返回全部     inner内连接返回等值连接     left以左表为主     right以右表为主
pd.merge(left, right, on='key1', how='outer')
  key1 key2_x    A    B key2_y    C    D
0   K0     K0   A0   B0     K0   C0   D0
1   K0     K1   A1   B1     K0   C0   D0
2   K1     K0   A2   B2     K0   C1   D1
3   K1     K0   A2   B2     K0   C2   D2
4   K3     K1   A3   B3    NaN  NaN  NaN
5   K2    NaN  NaN  NaN     K0   C3   D3
多个相同主键连接
pd.merge(left, right, on=['key1', 'key2'], how='outer')
  key1 key2    A    B    C    D
0   K0   K0   A0   B0   C0   D0
1   K0   K1   A1   B1  NaN  NaN
2   K1   K0   A2   B2   C1   D1
3   K1   K0   A2   B2   C2   D2
4   K3   K1   A3   B3  NaN  NaN
5   K2   K0  NaN  NaN   C3   D3

(2) 两表中没有相同的主键

left_on   : 指定左表中的主键
right_on  : 指定右表中的主键
pd.merge(left, right, left_on = 'key1', right_on = 'key2', how='outer')
  key1_x key2_x   A   B key1_y key2_y    C    D
0     K0     K0  A0  B0     K0     K0   C0   D0
1     K0     K0  A0  B0     K1     K0   C1   D1
2     K0     K0  A0  B0     K1     K0   C2   D2
3     K0     K0  A0  B0     K2     K0   C3   D3
4     K0     K1  A1  B1     K0     K0   C0   D0
5     K0     K1  A1  B1     K1     K0   C1   D1
6     K0     K1  A1  B1     K1     K0   C2   D2
7     K0     K1  A1  B1     K2     K0   C3   D3
8     K1     K0  A2  B2    NaN    NaN  NaN  NaN
9     K3     K1  A3  B3    NaN    NaN  NaN  NaN

(3) 更改表格名称的方法

left.rename(columns={'key1': 'key11111'}, inplace=True)
print(left)
  key11111 key2   A   B

(4) 重叠合并,目的是将残缺的表,合并为完整的表df1.combine_first(df2)

主表.combine_first(附表)
dict1 = {'ID':[1,2,3,4,5,6,7,8,9],
    'System':['W10','w10',np.nan,'w10',np.nan,np.nan,'w7','w7','w8']}dict2 = {'ID':[1,2,3,4,5,6,7,8,9],     'System':[np.nan,np.nan,'w7','w7','w7','w7','w8',np.nan,np.nan]} df1 = pd.DataFrame(dict1) df2 = pd.DataFrame(dict2) print(df1,df2) # 谁在前,为主表,主表中没有的补全,有的值,不动 print(df1.combine_first(df2))     ID System 0 1 W10 1 2 w10 2 3 w7 3 4 w10 4 5 w7 5 6 w7 6 7 w7 7 8 w7 8 9 w8

​推荐好课:Python3进阶:数据分析及可视化

Python中sys.argv(参数、解包、变量)

thbcm阅读(165)

小编今天给大家介绍将变量传递给脚本的方法。

在 python 中如果要运行一个my.py脚本,只需要在命令行中运行 python my.py,这句命令中的 my.py 部分就是所谓的‘参数(argument)’,现在要做的是如何写一个可以接受参数的脚本。

from sys import argv
script , first , second , third = argvprint('the script is called ',script) print('your first variable is ',first) print('your second variable is ',second) print('your thrid variable is ',thrid) 
  • 第一行中 import 导入库,argv 就是所谓的‘参数变量(arguement variable),这个变量包含了传递给 python 的参数;
  • 第二行 argv 解包(unpack),意思为把 argv 东西解包,将所有参数依次赋予左边的变量名。

在命令行中实现 my.py 的调用必须传递三个参数

python my.py first 2nd 3nd

在终端执行时将看到以下效果:

$  python my.py first 2nd 3nd
the script is called my
your first variable is first
your second variable is 2nd
your thrid variable is 3nd

推荐好课:Python3零基础入门到爬虫实战Python自动化办公+数据可视化视频课程

中国程序员容易发音错误的单词(点击收听正确读音)

thbcm阅读(194)

单词 正确发音(英音) 正确发音(美音) 错误发音
access √点击试听  /'ækses/ √点击试听  /ˈækses/ × /ək'ses/
Adobe √点击试听  /ə'dəʊbi/ √点击试听  /ə'dəʊbi/ × /əˈdub/
admin √点击试听  /'ædmɪn/ √点击试听  /ˈædmɪn/ × /ɜ:d'mɪn/
adversarial √点击试听  /ˌædvəˈseəriəl/ √点击试听   /ˌædvərˈseriəl/ × /ədˈvɜːrsəriəl/
agile √点击试听 /'ædʒaɪl/ √点击试听  /ˈædʒl/ × /ə'dʒaɪl/
amazon √点击试听  /'æməzən/ √点击试听  /ˈæməzɑːn/ × /'əmeizən/  /ə'meizən/
analogy √点击试听  /əˈnælədʒi/ √点击试听  /əˈnælədʒi/ × /ænə'lɒdʒi/
Angular √点击试听  /'æŋgjʊlə/ √点击试听  /ˈæŋɡjələr/ × /'æŋɡələ/  /'æŋdʒʌlə/
AJAX √点击试听  /'eidʒæks/ √点击试听  /'eidʒæks/ × /ə'dʒʌks/
alias √点击试听  /ˈeɪliəs/ √点击试听  /ˈeɪliəs/ × /ə'lais/
Apache √点击试听  /ə'pætʃɪ/ √点击试听  /əˈpætʃi/ × /ʌpʌtʃ/
app √点击试听  /æp/ √点击试听  /æp/ × /eipi'pi/
archive √点击试听  /'ɑːkaɪv/ √点击试听  /'ɑːkaɪv/ × /'ətʃɪv/
array √点击试听  /ə'rei/ √点击试听  /əˈreɪ/ × /æ'rei/
ASCII √点击试听  /'æski/ √点击试听  /ˈæski/ × /ɑːsk/
aspect √点击试听  /'æspekt/ √点击试听  /ˈæspekt/ × /ə'spekt/
avatar √点击试听  /'ævətɑː/ √点击试听  /ˈævətɑːr/ × /ə'vʌtɑ/
Azure √点击试听  /'æʒə/ √点击试听  /ˈæʒər/ × /ˈæzʊʒə/
bind √点击试听  /baɪnd/ √点击试听  /baɪnd/ × /bɪnd/
cache √点击试听  /kæʃ/ √点击试听  /kæʃ/ × /kætʃ/
clang √点击试听  /klæŋ/ √点击试听  /klæŋ/ × /sɪlæŋ/
daemon √点击试听  /'diːmən/ √点击试听  /ˈdiːmən/ × /dæmən/
debt √点击试听  /det/ √点击试听  /det/ × /de'bit/
deny √点击试听  /dɪ'naɪ/ √点击试听  /dɪˈnaɪ/ × /'dæni/
deprecate √点击试听 /ˈdeprəkeɪt/ √点击试听 /ˈdeprəkeɪt/
deque √点击试听  /'dek/ √点击试听  /dɛk/ × /di'kju/
digest √点击试听  n. /'dɑɪdʒɛst/ v. /dɑɪ'dʒɛst/ √点击试听  /daɪˈdʒest,dɪˈdʒest/ × /'dɪgɛst/
Dijkstra √点击试听  Dutch:/ˈdɛikstra/  English:/ˈdaɪkstrə/ √点击试听
Django √点击试听  /ˈdʒæŋɡoʊ/ √点击试听  /ˈdʒæŋɡoʊ/ × /diˈdʒæŋɡoʊ/
doc √点击试听  /dɒk/ √点击试听  /dɒk/ × /daʊk/
epoch √点击试听  /ˈiːpɒk/ √点击试听  /ˈepək/ × /'ɛpətʃ/
execute √点击试听 /ˈeksɪkjuːt/ √点击试听 /ˈeksɪkjuːt/
executor √点击试听 /ɪɡˈzekjətə(r)/ √点击试听 /ɪɡˈzekjətər/
event √点击试听  /ɪ'vent/ √点击试听  /ɪˈvent/ × /'ɪvənt/
facade √点击试听  /fə'sɑːd/ √点击试听  /fəˈsɑːd/ × /'feikeid/
fedora √点击试听  /fɪ'dɔːrə/ √点击试听  /fɪˈdɔːrə/ × /'fedərə/
format √点击试听  /'fɔːmæt/ √点击试听  /ˈfɔːrmæt/ × /fɔ'mæt/
gauge √点击试听 /ɡeɪdʒ/ √点击试听 /ɡeɪdʒ/ × /ɡɑudʒ/
Git √点击试听  /ɡɪt/ √点击试听  /ɡɪt/ × /dʒɪt/
GNU √点击试听  /gnu:/ √点击试听  /nuː,njuː/
Grafana √点击试听   /grəˈfɑːnˌɑː/ √点击试听   /grəˈfɑːnˌɑː/
GraphQL √点击试听  /græf kju ɛl/ √点击试听  /græf kju ɛl/ × /dʒɪgræf kju ɛl/
GUI √点击试听  /ˈɡu:i/ √点击试听  /ˈɡu:i/
Haskell √点击试听  /ˈhæskəl/ √点击试听  /ˈhæskəl/ × /hæˈskəl/
height √点击试听  /haɪt/ √点击试听  /haɪt/ × /heɪt/
hidden √点击试听  /'hɪdn/ √点击试听  /ˈhɪdn/ × /'haɪdn/
image √点击试听  /'ɪmɪdʒ/ √点击试听  /ˈɪmɪdʒ/ × /ɪ'meɪdʒ/
implement √点击试听  /'ɪmplɪm(ə)nt/ √点击试听  /ˈɪmplɪmənt/ /ˈɪmpləˌment/ × /ɪm'plem(ə)nt/
integer √点击试听  /'ɪntɪdʒə/ √点击试听  /ˈɪntɪdʒər/ × /ˈɪntaɪgə/
issue √点击试听  /'ɪʃuː/ √点击试听  /ˈɪʃuː/ × /ˈaɪʃuː/
Java √点击试听  /'dʒɑːvə/ √点击试听  /ˈdʒɑːvə/ × /'dʒɑːvɑː/
jpg √点击试听  /'dʒeɪpeɡ/ √点击试听  /'dʒeɪpeɡ/ × /ˈdʒeɪˈpi:ˈdʒiː/
key √点击试听  /kiː/ √点击试听  /kiː/ × /kei/
Kubernetes* √点击试听  /kubз'netɪs/ √点击试听  /kuːbə˞'netiz/
lambda √点击试听  /ˈlæmdə/ √点击试听  /ˈlæmdə/ × /ˈlɒŋmdɑ/
linear √点击试听  /'lɪnɪə/ √点击试听  /ˈlɪniər/ × /'laɪə/
Linux √点击试听  /'lɪnəks/ √点击试听  /ˈlaɪnəks/ /ˈlɪnəks/ × /ˈlɪnʌks/ /ˈlɪnjuːks/
locale √点击试听  /ləʊ'kɑːl/ √点击试听  /loʊˈkæl/ × /ˈloʊk(ə)l/
Lucene √点击试听  /lu'siːn/ √点击试听  /lu'siːn/ × /'lu:sən/
main √点击试听  /meɪn/ √点击试听  /meɪn/ × /mɪn/
margin √点击试听  /'mɑːdʒɪn/ √点击试听  /ˈmɑːrdʒɪn/ × /'mʌgɪn/
matrix √点击试听  /ˈmeɪtrɪks/ √点击试听  /ˈmeɪtrɪks/ × /ˈmɑ:trɪks/
maven √点击试听  /'meɪvn/ √点击试听  /ˈmeɪvn/ × /'maːvn/
Microsoft √点击试听  /'maikrəusɔft/ √点击试听  /ˈmaɪkrəsɔːft/ × /'mikrəusɔft/
miscellaneous √点击试听 /ˌmɪsəˈleɪniəs/ √点击试听 /ˌmɪsəˈleɪniəs/
module √点击试听  /'mɒdjuːl/ √点击试听  /ˈmɑːdʒuːl/ × /'məʊdl/
nginx Engine X Engine X
null √点击试听  /nʌl/ √点击试听  /nʌl/ × /naʊ/
obsolete √点击试听 /ˈɒbsəliːt/ √点击试听 /ˌɑːbsəˈliːt/
OS X OS ten OS ten × /ɔs eks/
phantom √点击试听  /'fæntəm/ √点击试听  /ˈfæntəm/ × /'pæntəm/
parameter √点击试听  /pə'ræmɪtə/ √点击试听  /pəˈræmɪtər/ × /'pærəmɪtə/
privilege √点击试听 /'prɪvəlɪdʒ/ √点击试听  /ˈprɪvəlɪdʒ/ × /'prɪvɪlɪdʒ/
Prometheus √点击试听  /prə-ˈmē-thē-əs/ √点击试听  /pro'miθɪəs/
putty √点击试听  /ˈpʌti/ √点击试听  /ˈpʌti/ × /ˈpuːti/
Qt √点击试听  /kjuːt/ √点击试听  /kjuːt/
query √点击试听  /'kwɪəri/ √点击试听  /ˈkwɪri/ × /'kwaɪri/
Realm √点击试听  /relm/ √点击试听  /relm/ × /riəlm/
reconcile √点击试听 /ˈrekənsaɪl/ √点击试听 /ˈrekənsaɪl/
Redux √点击试听  /ri'dʌks/ √点击试听  /ri'dʌks/ × /'ridju:ks/
resume √点击试听   /rɪ'zju:m/ √点击试听  /rɪˈzuːm/ ×  /rɪ'sju:m/
resolved √点击试听  /rɪ'zɒlvd/ √点击试听  /rɪˈzɑːlvd/ × /rɪ'səʊvd/
resort √点击试听  /rɪˈzɔ:t/ √点击试听  /rɪˈzɔːrt/ × /rɪˈsɔ:t/
retina √点击试听  /'retɪnə/ √点击试听  /ˈretɪnə/ × /ri'tina/
route √点击试听  /ruːt/ √点击试听  /ruːt,raʊt/ × /rəʊt/
San Jose √点击试听  /sænhəu'zei/ √点击试听  /sænhəu'zei/ × /sæn'ju:s/
safari √点击试听  /sə'fɑːrɪ/ √点击试听  /səˈfɑːri/ × /sæfərɪ/
scheme √点击试听  /skiːm/ √点击试听  /skiːm/ × /s'kæmə/
scala √点击试听  /ˈskɑːlɑ/ √点击试听  /ˈskɑːlɑ/ × /ˈskæːlɑ/
segue √点击试听  /'sɛɡwe/ √点击试听  /ˈseɡweɪ/ × /se'dʒ/
SQL /ˈsiːkwəl/ /ˈesˈkjuːˈel/ /ˈsiːkwəl/  /ˈesˈkjuːˈel/
sudo /'suːduː/ /'suːduː/
suite √点击试听  /swiːt/ √点击试听  /swiːt/ × /sjuːt/
thymeleaf √点击试听  /ˈtaɪmˌlɪːf/ √点击试听  /ˈtaɪmˌlɪːf/ × /θiːmɪlɪːf/
tuple √点击试听 /tjʊpəl/ √点击试听 /tuːpəl/
typical √点击试听  /'tɪpɪkl/ √点击试听  /ˈtɪpɪkl/ × /'taɪpɪkəl/
Ubuntu √点击试听  /ʊ'bʊntʊ/ √点击试听  /ʊ'bʊntʊ/ × /juː'bʊntʊ/
Vagrant √点击试听 /ˈveɪɡrənt/ √点击试听 /ˈveɪɡrənt/ /ˈvagɹent/
variable √点击试听  /'veəriəbl/ √点击试听  /ˈveriəbl,ˈværiəbl/ × /və'raiəbl/
verbose √点击试听  /vɜːˈbəʊs/ √点击试听  /vɜːrˈboʊs/ × /'vɜːrboʊs/
vue √点击试听  /v'ju:/ √点击试听  /v'ju:/ × /v'ju:i/
width √点击试听  /wɪdθ/ √点击试听  /wɪdθ,wɪtθ/ × /waɪdθ/
YouTube √点击试听  /'juː'tjuːb/ √点击试听  /'juː'tjuːb/ × /'juː'tʊbɪ/

附注

  • 当使用简名 ‘Kube’ 称呼 ‘Kubernetes’ 时, 发音则与 ‘cube’(/kjuːb/) 一致

其他相关链接

  1. 真人发音 (by @hailintao)
  2. 简洁的单词列表,正确读音不用再打开新网页 (by @antfu7)
  3. 国际音标严式记音(纽约音) (by @b1f6c1c4)

说明

  1. 本着简单的原则, 又为了避免程序猿们出现选择困难症, ‘正确音标’采用了最接近有道词典音频的英式 DJ 音标, 不代表其唯一性
  2. 专业在线英语词典请参考知乎链接:在线英语词典哪个比较好?

参考资料

  1. IT 圈里有哪些经常被读错的词?
  2. 关于那些开发语言中的常用名词,大家读的都正确吗?
  3. 今天才发现我不会读 main 和 null 的读音
  4. 同事老把 cache 读成 catch,要不要当面纠正呢?
  5. 你们怎么发 git 的音?有多少人能正确发音吗?
  6. sudo 这个词该怎么读?

推荐阅读

作者:Horcrux 原文地址:Words Commonly Mispronounced by Chinese Programmers

[Java设计模式] 单例模式入门

thbcm阅读(186)

什么是单例模式

  • 单例模式(Singleton Pattern)是一个比较简单的模式,实际应用很广泛,比如 Spring 中的Bean实例就是一个单例对象。
  • 定义:确保某一个类 只有一个实例,而且自行实例化并向整个系统提供这个实例。

单例模式的优缺点

优点

  • 只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例。
  • 单例模式可以避免对资源的多重占用,例如一个写文件动作,由于只有一个实例存在内存中,避免对同一个资源文件的同时写操作。
  • 单例模式可以在系统设置全局的访问点,优化和共享资源访问,例如可以设计一个单例类,负责所有数据表的映射处理。

缺点

  • 单例模式一般没有接口,很难扩展(根据环境而定)。
  • 单例模式与单一职责原则有冲突。一个类应该只实现一个逻辑,而不关心是否是单例的。

单例模式的实现

  • 单例模式有很多的实现方式,但是各种实现的方式都有其优缺点,下面来看看各种的实现方式。
  • 单例模式的实现满足以下几点:构造方法私有。有一个静态方法获取该类的实例。该类保证只有一个实例。

懒汉式

  • 懒汉式是当用到这个对象的时候才会创建。
  • 懒汉式,在需要单例模式类实例时它才创建出来给你(因为很懒)。
  • 优点:只有用到的时候才会创建这个对象,因此节省资源。
  • 简单的实现如下:
/**
  *Singleton类,单例模式类,在类加载时便会创建一个私有静态变量instance,也就是该类的实
  *例,再通过公共接口getInstance()来发布该实例
  */
public class Singleton {  
    private static Singleton instance;
    //私有化构造方法防止外界new对象
    private Singleton (){

    }

    //公有化静态函数,对外暴露单例对象的接口

    public static Singleton getInstance() {

        if (instance == null) {

            instance = new Singleton();

        }

        return instance;

    }

但是这种方式并不能保证这是唯一的单例,在高并发访问下,多个线程同时访问到这个单例时,还是有可能不能保证这个类就是单例的

为了保证线程安全,我们可以加锁,给这个getInstance()方法加上线程同步锁synchronize具体实现如下:

public class Singleton {  

    private static Singleton instance;  

    private Singleton (){

        

    }  

    public static synchronized Singleton getInstance() {  

    if (instance == null) {  

        instance = new Singleton();  

    }  

    return instance;  

    }  

}

但是这种方式一旦加锁,虽然可以保证其实单例且线程安全的,但是在高并发访问下性能必然是受到影响,多个线程都需要用到该单例时,就无法保证速度,需要同步地等待这个单例使用完回到JVM中的堆区(Heap)才可以继续使用这个单例,效率十分的低。

还有一种是双重检查式,两次判断

Double Check Lock(DCL)方式实现单例模式

public class Singleton{

    private volatile static Singleton instance;

    private Singleton(){

        

    }

    public static Singleton getInstance(){

        if(instance == null){

            synchronized (Singleton.class){

                if(instance == null){

                    instance = new Singleton();

                }

            }

        }

        return instance;

    }

}

我们可以看到getInstance中对instance进行了两次判断是否为空,第一次判断主要是为了避免不必要的同步问题,第二次判断则是为了在null的情况下创建实例,因为在某些情况下会出现失效问题即DCL失效问题,可以使用volatile关键字处理这个问题,但是同样的,使用了volatile关键字也会对性能有一定的影响。但是优点在于资源利用率高,第一次执行getInstance时对象才被实例化,但是DCL也因为第一次加载时反应慢,所以在高并发情况下也会有一定的缺陷。

饿汉式

  • 饿汉式和懒汉式恰巧相反,在类加载的时候就创建实例。
  • 单例模式类迫不及待的想要创建实例了(因为饿了)
  • 优点:还没用到就创建,浪费资源。
  • 缺点:在类加载的时候就创建,线程安全。
  • 实现如下:

/**

  *这种方式在类加载时就完成了初始化,所以类加载较慢,但是获取对象的速度快。这种方式

  *基于类加载机制,避免了多线程的同步问题。如果从来没有使用过这个实例,则会造成内存

  *的浪费。

  */

public class Singleton {  

    private static Singleton instance = new Singleton();  

    private Singleton (){

        

    }  

    public static Singleton getInstance() {  

     return instance;  

    }  

}

匿名内部类/静态内部类

  • 利用静态变量、静态代码块、静态方法都是在类加载的时候只加载一次的原理。
  • 实现如下

public class Singleton {

    private static Singleton instance;

    //静态块在类加载时会被执行,也就创建了Singleton类实例

    static{

        instance = new Singleton();

    }

    private Singleton (){

    

    }  

    public static final Singleton getInstance() {  

     return SingletonHolder.INSTANCE;  

    }  

}

/**

  *Java静态内部类的特性是,加载的时候不会加载内部静态类,使用的时候才会进行加载。

  *第一次加载Singleton类时并不会初始化sInstance,只有第一次调用getInstance方法时虚

  *拟机加载SingletonHolder并初始化sInstance。这样不仅能确保线程安全,也能保证

  *Singleton类的唯一性。所以,推荐使用静态内部类单例模式

  */

public class Singleton {  

    private static class SingletonHolder {  

     private static final Singleton INSTANCE = new Singleton();  

    }

    private Singleton (){

    

    }  

    public static final Singleton getInstance() {  

     return SingletonHolder.INSTANCE;  

    }  

}

枚举单例模式

/**
  *默认枚举实例的创建是线程安全的,并且在任何情况下都是单例。
  *枚举单例的有点就是简单,缺点是可读性不高。
  */
public enum Singleton {
    //外部调用由原来的Singleton.getInstance变成了Singleton.INSTANCE了。
    INSTANCE;
}

总结

单例模式是运用频率很高的模式,在我们客户端通常是没有高并发的情况,所以选择哪种方式并不会有太大的影响。出于效率考虑,推荐使用静态内部类的单例模式和DCL的单例模式。

优点:

  • 由于单例模式在内存中只有一个实例,减少内存开支,特别是一个对象需要频繁创建、销毁时,而且创建或销毁时性能又无法优化,单例模式的优势就十分明显。
  • 由于单例模式只生成一个实例,所以减少了系统的性能开销,当一个对象的产生需要比较多的资源时,如读取配置、产生其他依赖对象时,则可通过在应用启动时直接产生一个单例对象,然后用永久驻留的方式解决。
  • 单例模式可以避免对资源的多重占用,如一个文件的操作,由于只有一个实例存在内存中,避免对同一个资源文件的同时操作。
  • 单例模式可以在系统设置全局的访问点,优化和共享资源访问。例如,可以设计一个单例类,负责所有数据表的映射处理。

缺点:

  • 单例模式一般没有接口,扩展很困难,除非修改代码。
  • 单例对象如果持有Context,那么很容易引发内存泄露,此时需要注意传递给单例对象的Context最好是Application Context。
  • 不适合用于变化频繁的对象;如果实例化的对象长时间不被利用,系统会认为该对象是垃圾而被回收,这可能会导致对象状态的丢失;

使用场景

  • 网站访问量计数器。
  • 项目中用于读取配置文件的类。
  • Spring中,每个Bean默认都是单例的,这样便于Spring容器进行管理。

推荐好课:Java:23天零基础完全入门Java面试 基础题应知应会

jsp实现登陆验证码

thbcm阅读(157)

填写输入信息 index.jsp

<html><body>     

<form method=post action="result.jsp">     

<input type=text name=input maxlength=4>     

<img border=0 src="image.jsp">     

<input type="submit"value="submit">     

</form></body></html> 

生成图片 image.jps

<%@ page contentType="image/JPEG" 

    import="java.awt.*,java.awt.image.*,java.util.*,javax.imageio.*" 

    pageEncoding="GBK"%> 

给定范围取得随机色彩

<%!Color getRandColor(int fc, int bc) { 

        Random random = new Random();  

        if (fc > 255)  

            fc = 255;  

        if (bc > 255)  

            bc = 255;  

        int r = fc + random.nextInt(bc - fc);  

        int g = fc + random.nextInt(bc - fc);  

        int b = fc + random.nextInt(bc - fc);  

        return new Color(r, g, b);  

    }%> 

<%  

设置页面不缓存

 response.setHeader("Pragma", "No-cache");  

response.setHeader("Cache-Control", "no-cache");  

response.setDateHeader("Expires", 0);  

在内存中创建图像

 int width = 60, height = 20;  

    BufferedImage image = new BufferedImage(width,height,  

            BufferedImage.TYPE_INT_RGB);  

获得图形上下文

 Graphics g = image.getGraphics();  

生成随机类

Random random = new Random();  

设定背景

 g.setColor(getRandColor(200, 250));  

    g.fillRect(0, 0, width, height);  

设定字体

g.setFont(new Font("Times New Roman", Font.PLAIN,18));  

画边框

//g.setColor(newColor());  

    //g.drawRect(0,0,width⑴,height⑴);  

 随机产生155条干扰线,使图像中的认证码不容易被其它程序探测到  

g.setColor(getRandColor(160, 200));  

    for (int i = 0; i < 100; i++) {  

        int x = random.nextInt(width);  

        int y = random.nextInt(height);  

        int xl = random.nextInt(12);  

        int yl = random.nextInt(12);  

        g.drawLine(x, y, x + xl, y + yl);  

    }  

取随机产生的认证码(4位数字)

 String sRand = "";  

    for (int i = 0; i < 4; i++) {  

        String rand =String.valueOf(random.nextInt(10));  

        sRand += rand;  

将认证码显示到图像中

 g.setColor(new Color(20 + random.nextInt(110), 20 +random  

        .nextInt(110), 20 +random.nextInt(110)));

调用函数出来的色彩相同,多是由于种子太接近,所以只能直接生成

g.drawString(rand, 13 * i + 6,16);  

    }  

将认证码存入SESSION

 session.setAttribute("code",sRand);  

图像生效

 g.dispose();  

输出图像到页面

 ImageIO.write(image, "JPEG",response.getOutputStream());  

%>

验证是不是输入正确result.jsp

<%@ page language="java"import="java.util.*" pageEncoding="GBK"%> 

<html><body> 

<%  

    String input=request.getParameter("input");  

    String code=(String)session.getAttribute("code");      

    if(input.equals(code)){  

        out.println("验证成功!");  

    }else{  

        out.println("验证失败!");  

    }  

%> 

</body></html>

可能遇到的问题:

你的 eclipse 会提示你:graphic.drawString() 方法毛病

是你的 jdk 版本太高了,但是不要紧。把这个项目的兼容版本放低就好了。

具体操作步骤:

右键进程,选中 propriety,再选中“Java compiler”

把 jdk 的兼容版本下降到1.4便可

用VUE写的页面不利于SEO怎么办?实现VUE单页面应用SEO的另一种思路

thbcm阅读(172)

(设置 vue 单页面 meta info 信息,如果需要单页面 SEO,可以和 prerender-spa-plugin 形成更优的配合) 单页面应用在前端正大放光彩。三大框架 Angular Vue React ,可谓妇孺皆知。随着单页面应用的普及,人们在感受其带来的完美的用户体验,极强的开发效率的同时,也似乎不可避免的要去处理 SEO 的需求。 本文主要针对 vue 2.0 单页面 Meta SEO 优化展开介绍: 其实解决 SEO 问题不一定非得用服务端渲染来处理,服务端渲染对于刚接触 vue 的新手来说,并不是那么友好,虽然已有官方 SSR 中文文档 。但是对于一个已经开发完毕的 vue 项目去接 SSR 无论是从工作量还是技术角度来说,都是一种挑战。不过这些怎么能难得到伟大的前端程序员!

如果您调研服务器端渲染(SSR)只是用来改善少数营销页面(例如 /, /about, /contact 等)的 SEO,那么您可能需要预渲染。无需使用 web 服务器实时动态编译 HTML,而是使用预渲染方式,在构建时 (build time) 简单地生成针对特定路由的静态 HTML 文件。优点是设置预渲染更简单,并可以将您的前端作为一个完全静态的站点。 如果您使用 webpack,您可以使用 prerender-spa-plugin 轻松地添加预渲染。它已经被 Vue 应用程序广泛测试。 预渲染为 SEO 提供了另一种可能,简单的来说,预渲染就是当 vue-cli 构建的项目进行 npm run build 的时候,会按照路由的层级进行动态渲染出对应的 html 文件。

// webpack.conf.js
var path = require('path')
var PrerenderSpaPlugin = require('prerender-spa-plugin')


module.exports = {
  // ...
  plugins: [
    new PrerenderSpaPlugin(
      // 编译后的html需要存放的路径
      path.join(__dirname, '../dist'),
      // 列出哪些路由需要预渲染
      [ '/', '/about', '/contact' ]
    )
  ]
}

最终会生成类似于这样的目录结构

而里面的内容都会被渲染成了静态的 html 文件

相对于之前的可能只有

<html>
  <head>
    <meta charset="utf-8">
    <title>tangeche-pc</title>
  </head>
  <body>
    <div id="app"></div>
    <!-- built files will be auto injected -->
  <script type="text/javascript" src="/app.js"></script></body>
</html>

可以直观的发现,预渲染的作用。 有了预渲染,我们可以解决很多方面的 SEO 的问题,但是有时候我们也会需要 Meta 信息的变化,比如title 比如 Meta keyWords 或者是link… 这里安利一下 vue-meta-info 一个可以动态设置 meta 信息的 vue 插件如果需要单页面 SEO,可以和 prerender-spa-plugin形成更优的配合。 vue-meta-info 是一个基于 vue 2.0 的插件,它会让你更好的管理你的 app 里面的 meta 信息。你可以直接 在组件内设置 metaInfo 便可以自动挂载到你的页面中。如果你需要随着数据的变化,自动更新你的 titlemeta 等信息,那么用此 插件也是再合适不过了。 当然,有时候我们也可能会遇到让人头疼的 SEO 问题,那么使用此插件配合 prerender-spa-plugin 也是再合适不过了

1.安装

yarn:

    yarn add vue-meta-info

npm:

    npm install vue-meta-info --save

2.全局引入 vue-meta-info

    import Vue from 'vue'
    import MetaInfo from 'vue-meta-info'


    Vue.use(MetaInfo)

3.组件内静态使用 metaInfo

    <template>
      ...
    </template>


    <script>
      export default {
        metaInfo: {
          title: 'My Example App', // set a title
          meta: [{                 // set meta
            name: 'keyWords',
            content: 'My Example App'
          }]
          link: [{                 // set link
            rel: 'asstes',
            href: 'https://assets-cdn.github.com/'
          }]
        }
      }
    </script>

4.如果你的 title 或者 meta 是异步加载的,那么你可能需要这样使用

    <template>
      ...
    </template>


    <script>
      export default {
        name: 'async',
        metaInfo () {
          return {
            title: this.pageName
          }
        },
        data () {
          return {
            pageName: 'loading'
          }
        },
        mounted () {
          setTimeout(() => {
            this.pageName = 'async'
          }, 2000)
        }
      }
    </script>

写到这里,大家应该都明白了我所说的 SEO 的另一种思路是什么了,preRender + metaInfo 可以才一定层次上去解决 SEO 问题,这种方式优点就是代码侵入性最低,开发成本最少。但是也是有弊端的:

  • 不能很好地处理用户独特性路由: 比如有个路由是/my-profile, 预渲染可能不会很好用, 因为这个内容页是根据用户信息变化的,所以页面内容也不是唯一确定的. 你可能会使用类似于这样的路由路径 /users/:username/profile,但是这样也是不合适的.
  • 经常变动的文件
  • 需要预渲染成千上万的路由文件: 这个可能会导致你编译时间…..额,可能你会编译很长时间

作者:王伟

原文:https://muwoo.github.io/pager5/

ssh连接docker服务器详操

thbcm阅读(184)

小编刚接触 docker 时,是真的懵,看了半天教程也不会使,但现在至少了解了 docker 是一个容器,里面可以放各种软件,放了 ubuntu 的话,这个容器就可以看做 ubuntu 在其他环境使用,今天就给小伙伴们介绍下如何使用 ssh 连接 docket 服务器。

主要说一下怎么创建一个docker服务,让别人可以通过ssh来连接使用(以ubuntu为例)

创建容器

需要镜像,使用过 ubuntu 等镜像安装的小伙伴应该都明白,如果没有的话通过 docker pull 镜像名就可以下载一个

在 ubuntu 镜像中创建容器,并将 docker 服务器的 50003 端口映射到容器的 22 端口上

docker run -it -d -p 50003:22 ubuntu

这时我们使用 docker ps 可以看到我们的容器已经启动了

通过 ID 进入容器

docker exec -it a9cbce70127f /bin/bash

这时我们就进入了容器,也就是在 ubuntu 的环境里了

安装 ssh server

apt-get update
apt-get install passwd
apt-get install openssh-server

这里安装 ssh 服务时会让你选择时区,用数字选择就行了,我用的 6 31

tips: 如果你使用命令,报这个命令找不到,可以直接使用 apt-get install 命令名来安装这个命令

通过 passwd 命令来设置 root 的密码

启动 ssh 服务

service ssh start

可以通过 ps -e |grep ssh 查看服务是否启动

修改配置文件

通过 vim 编辑器打开配置文件

vim /etc/ssh/sshd_config

在配置文件中写入以下内容(#号后是注释)

PubkeyAuthentication yes                #启用公钥私钥配对认证方式
AuthorizedKeysFile .ssh/authorized_keys #公钥文件路径
PermitRootLogin yes                     #root能使用ssh登录

这里要是提示没有 vim 命令就按我上面说的下一个,另外这个编辑器用起来和普通的不一样,有插入模式、命令模式等需要去查一下具体怎么操作,这里简单说一下进入编辑器后按i键进入插入模式,然后就正常的编辑文件,完成后按 esc 退出插入模式,直接输入:wq命令就是保存并退出

重启服务

service ssh restart

这时就可以远程连接了,再打开一个 cmd 窗口通过 ssh –p 端口号 用户名 @IP 地址或者其他的工具都可以连接成功后进入 ubuntu 的环境,这时就可以使用 linux 的命令了。

​推荐好课:Docker基础入门Docker 从入门到实践

CSS应用:让页脚紧贴页面底部

thbcm阅读(177)

怎么使用 Sticky Footer 代码

介绍

Google 一下可以找到很多让页脚紧贴页面底部的方法,我试过其中的很多,但他们总会在某些方面存在一些问题。之所以有这些问题,可能是因为出现了更新版本的浏览器。一些方法因为太过久远,原本在老版本浏览器可以正常工作,却不再适用更新之后的版本。也因为这些页面太过久远,过去曾被大量链接过,所以在Google 的结果中排名很高。这样,一些网站管理员在搜索 sticky footer 方案的时候,对搜索出的结果都很挠头,因为排在搜索结果前列的方法都有这样那样的问题。 众所周知的是 Ryan Fait 的方案,它的确工作的很好。但是,它必须要单独写一个没有内容的 div,来提供额外的”push”。对 HTML 语义要求严格的人可以说代码这么写是不符合规范的,我们的方案不用附加的div。 将要介绍的 Sticky Footer 方案是建立在 Exploring Footers article from A List Apart 成果的基础上,并受到 Cameron Adams 和 this piece at lwis.net 工作的启发。在 Google Chrome 和其他浏览器中,当你缩放窗口的时候,页脚会浮上来。该方案会应用一种 Clear fix hack 方法,把页脚固定在适当的位置上,这种方法同时也解决了页面布局是两列或三列悬浮可能会带来的问题。在超过 50 种以上的浏览器测试中,它都能很好的工作。

HTML 代码

下面是 HTML 代码的基本结构,footer 标签在 wrap 标签的外面。

<!--Example Source Code-->

<div id="wrap">

<div id="main" class="clearfix">

</div>

</div>

<div id="footer">

</div>

​​

页面内容可以放在 main 标签的内部。例如,下面是两列悬浮页面布局的 HTML 代码;

<!--Example Source Code-->

<div id="wrap">

<div id="main" class="clearfix">

<div id="content">

</div>

<div id="side">

</div>

</div>

</div>

<div id="footer">

</div>

​​

Header放在wrap的里面,main的上面,如下所示;

<!--Example Source Code-->

<div id="wrap">

<div id="header">

</div>

<div id="main" class="clearfix">

</div>

</div>

<div id="footer">

</div>

​如果你需要在 wrap 或者 footer 的外面放一些元素,他们必须使用绝对位置;否则,页面上计算好的 100% 的高度会被弄乱掉。

CSS 代码

下面的 CSS 代码使页脚紧贴在页面的底部。

/Example Source Code/ html, body, #wrap {height: 100%;} body > #wrap {height: auto; min-height: 100%;} #main {padding-bottom: 150px;} /* must be same height as the footer / #footer {position: relative; margin-top: -150px; / negative value of footer height */ height: 150px;

clear:both;}

你会发现,页脚的高度在这里被重复使用了三次,这是至关重要的,而且三个高度必须使用同样的值。wrap 的 height 属性把自己拉伸至窗口全部高度的尺寸,负的 margin 会把 footer 提高到 main 的 padding 的位置上去,因为 main 已经在 wrap 的里面,所以 main 的 padding 已经是 wrap 100% 高度的一部分。 这样,footer 就留在页面的底部了。 现在还不算完成,我们还需要去 clearfix main。

Clearfix Hack to the Rescue

多数 SS designers 对 Clearfix Hack 很熟悉,它解决了很多元素悬浮的问题,在这里,我们用它使得 Google Chrome 里面的页脚紧贴页面底部。它同时也解决了两列悬浮布局所带来的问题。这样你就可以把内容放在一列,sidebar 放在另一列,不会出现个别浏览器下面 main 里面的悬浮的内容导致页脚浮上来的情况。 下面的代码也加入到我们的 stylesheet 里面去;

/Example Source Code/ .clearfix:after {content: "."; display: block; height: 0; clear: both; visibility: hidden;} .clearfix {display: inline-block;} /* Hides from IE-mac */ *html .clearfix { height: 1%;} .clearfix {display: block;} /* End hide from IE-mac */

如果你比较喜欢 Ryan Fait 的方法,添加额外的 push,在多列悬浮的页面中,同样需要用到 clearfix。

需要了解的内容

高度和边距

Header,wrap 或者 main 标签内部,如果对一些元素使用 top 或者 bottom margin,可能会出现 footer 被向下移动的现象,移动距离一般是所用的 margin 的高度。这种情况下,可以使用 padding 替代 margin 来填充元素间隙。在页面内容少的情况下,footer 本来应该在页面的底部,窗口的滚动条告诉你 footer 在页面底部偏下的位置。找到那个捣乱的 margin,并用 padding 替换掉。 为 main 声明padding 的时候要多加小心,如果你添加了这样的代码:padding:0 10px 0 10px,你就覆盖了那个至关重要的本来应该和 footer一样的 padding。Google Chrome 中,在页面内容很多的情况下,footer就会和你的页面内容重叠在一起。

字体的大小

设置字体大小的时候,如果你使用相对尺寸,要注意有些访问者可能会在显示器配置中使用较大字体。如果 footer 下面没有剩余足够的空间来容纳大字体,页面高度的设置就会被破坏,从而导致 footer 下面有多余的空隙。所以,请使用 绝对大小(px),不要使用pt或者 em。

HTML+CSS布局img图片元素出现空白的问题

thbcm阅读(185)

在进行页面的 HTML+CSS 排版时,遇到IE6(当然有时Firefox下也会偶遇)浏览器中的图片元素 img 下出现多余空白的问题绝对是常见的,对于该问题的解决方法也是“见机行事”,根据原因的不同要用不同的解决方法,这里把解决直接把解决 image 图片布局下边的多余空隙的 BUG 的常用方法归纳,供大家参考。

1、将图片转换为块级对象

即,设置img为:

display:block;

在本例中添加一组CSS代码:

#nav img {vertical-align:top;}

2、设置图片的垂直对齐方式

即设置图片的 vertical-align 属性为“top,text-top,bottom,text-bottom”也可以解决。如本例中增加一组CSS代码:

#nav img {vertical-align:top;}

3、设置父对象的文字大小为0px

即,在#nav 中添加一行:

font-size:0;

可以解决问题。但这也引发了新的问题,在父对象中的文字都无法显示。就算文字部分被子对象括起来,设置子对象文字大小依然可以显示,但在 CSS 效验的时候会提示文字过小的错误。
4、改变父对象的属性

如果父对象的宽、高固定,图片大小随父对象而定,那么可以设置:

overflow:hidden;

来解决。如本例中可以向 #sub 中添加以下代码:

width:88px;height:31px;overflow:hidden;

5、设置图片的浮动属性

即在本例中增加一行 CSS 代码:

#nav img {float:left;}

如果要实现图文混排,这种方法是很好的选择。

6、取消图片标签和其父对象的最后一个结束标签之间的空格。

比如:

<img src="https://www.w3cschool.cn/" />

<div style="width:195px; height:24px;clear:both; background:#B51D9F; ">网页设计</div>

修正为:

<img src="https://www.w3cschool.cn/" /> <div style="width:195px; height:24px;clear:both; background:#B51D9F; ">网页设计</div>

联系我们