HTML5小技巧

🔥 Details Tag


<details>标签提供随需应变的细节内容给用户。如果需要按需向用户显示内容,请使用此标记。默认情况下,详细内容是关闭的。打开后,它将展开并显示其中的内容。


<summary>标签与<details>一起使用,来为它指定一个可见的标题。


Code


<details>
<summary>Click Here to get the user details</summary>
<table>
<tr>
<th>#</th>
<th>Name</th>
<th>Location</th>
<th>Job</th>
</tr>
<tr>
<td>1</td>
<td>Adam</td>
<td>Huston</td>
<td>UI/UX</td>
</tr>
</table>
</details>
复制代码

效果演示




您可以从这里开始查看演示:https : //html5-tips.netlify.app/details/index.html


小提示


在GitHub Readme中使用它来显示需要的详细信息。隐藏大量的文字并仅按需显示它。酷吧?


点击查看例子https://github.com/atapas/notifyme#properties


🔥 Content Editable


contenteditable是可以在元素上设置以使内容可编辑的属性


可以与DIV,P,UL等元素一起使用。您必须像这样指定它:<element contenteditable=”true|false”>


注意,如果contenteditable未在元素上设置属性,则会从其父级继承该属性。


Code


<h2> Shoppping List(Content Editable) </h2>
<ul class=“content-editable” contenteditable=“true”>
<li> 1. Milk </li>
<li> 2. Bread </li>
<li> 3. Honey </li>
</ul>

复制代码

效果演示




您可以从这里开始查看演示https://html5-tips.netlify.app/content-editable/index.html


小提示


可以使span或div元素可编辑,并且可以使用CSS样式向其添加任何丰富的内容。这将比使用input 输入框更好。试一试!


🔥 Map

1
2
3
4
5
6
7
8
9
10
11
<div>
<img src="circus.jpg" width="500" height="500" alt="Circus" usemap="#circusmap">

<map name="circusmap">
<area shape="rect" coords="67,114,207,254" href="elephant.htm">
<area shape="rect" coords="222,141,318, 256" href="lion.htm">
<area shape="rect" coords="343,111,455, 267" href="horse.htm">
<area shape="rect" coords="35,328,143,500" href="clown.htm">
<area shape="circle" coords="426,409,100" href="clown.htm">
</map>
</div>

效果演示

您可以从这里开始查看演示https://html5-tips.netlify.app/map/index.html

小提示

图像贴图有其自身的缺点,但是您可以将其用于视觉演示。我们可以用全家福照片尝试一下并深入研究个人照片

🔥 Mark Content

使用<mark>标记突出显示任何文本内容。

Code

 <p> Did you know, you can <mark>“Highlight something interesting”</mark> just with an HTML tag? </p>
复制代码

效果演示

您可以从这里开始查看演示https://html5-tips.netlify.app/mark/index.html

小提示

您始终可以使用CSS更改突出显示颜色,

mark {
background-color: green;
color: #FFFFFF;
}
复制代码

🔥 data-* attribute

data-*属性用于存储页面或应用程序专用的自定义数据。可以在JavaScript代码中使用存储的数据来创建更多的用户体验。

data- *属性由两部分组成:

  • 属性名称不得包含任何大写字母,并且前缀“ data-”后必须至少长一个字符
  • 属性值可以是任何字符串

  • Code

    <h2> Know data attribute </h2>
    <div
    class=“data-attribute”
    id=“data-attr”
    data-custom-attr=“You are just Awesome!”>

    I have a hidden secret!
    </div>

    function reveal() {
    let dataDiv = document.getElementById(‘data-attr’);
    let value = dataDiv.dataset[‘customAttr’];
    document.getElementById(‘msg’).innerHTML = &lt;mark&gt;<span class="hljs-subst">${value}</span>&lt;/mark&gt;;
    }
    复制代码

    注意:要在JavaScript中读取这些属性的值,可以使用getAttribute(),但是规范定义了一种更简单的方法:使用dataset属性。

    效果演示

    您可以从这里开始查看演示https://html5-tips.netlify.app/data-attribute/index.html

    小提示

    您可以使用它在页面中存储一些数据,然后使用REST调用将其传递给服务器。

    🔥 Output Tag

    <output>标签表示运算的结果。通常,此元素定义一个区域,该区域将用于显示某些计算得出的文本。

    Code

    <form oninput=“x.value=parseInt(a.value) * parseInt(b.value)”>
    <input type=“number” id=“a” value=“0”>

    * <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"number"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"b"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"0"</span>&gt;</span>
          = <span class="hljs-tag">&lt;<span class="hljs-name">output</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"x"</span> <span class="hljs-attr">for</span>=<span class="hljs-string">"a b"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">output</span>&gt;</span>
    

    </form>
    复制代码

    效果演示

    您可以从这里开始查看演示https://html5-tips.netlify.app/output/index.html

    小提示

    如果要在客户端JavaScript中执行任何计算,并且希望结果反映在页面上,请使用<output>标记。您不必走动使用可获取元素的额外步骤:getElementById()。

    🔥 Datalist

    <datalist>标签指定了预先定义的选项列表,并允许用户添加更多。它提供了一项autocomplete功能,使您可以提前输入所需的选项。

    Code

    <form action=“” method=“get”>
    <label for=“fruit”>Choose your fruit from the list:</label>
    <input list=“fruits” name=“fruit” id=“fruit”>
    <datalist id=“fruits”>
    <option value=“Apple”>
    <option value=“Orange”>
    <option value=“Banana”>
    <option value=“Mango”>
    <option value=“Avacado”>
    </datalist>
    <input type=“submit”>
    </form>
    复制代码

    效果演示

    您可以从这里开始查看演示https://html5-tips.netlify.app/datalist/index.html

    小提示

    与传统<select>-<option>标签有何不同?Select标记用于从选项中选择一个或多个项目,您需要浏览列表以进行选择。Datalist是具有自动完成支持的高级功能。也就是说Datalist标签不仅可以选择,还可以输入

    🔥 Range(Slider)

    range具有滑块,范围选择的输入类型

    Code

    <form method=“post”>
    <input
    type=“range”
    name=“range”
    min=“0”
    max=“100”
    step=“1”
    value=“”
    onchange=“changeValue(event)”/>

    </form>
    <div class=“range”>
    <output id=“output” name=“result”> </output>
    </div>
    复制代码

    效果演示

    您可以从这里开始查看演示https://html5-tips.netlify.app/range/index.html

    小提示

    在html5中,没有叫slider的东西

    🔥 Meter

    使用<meter>标签测量给定范围内的数据。

    Code

    `<label for=“home”>/home/atapas</label>
    <meter id=“home” value=“4” min=“0” max=“10”>2 out of 10</meter><br>

    css3瀑布流的实现

    这篇介绍一下关于css3实现的瀑布流

    css部分

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    <style>
    *{
    margin:0;
    padding:0;
    }
    #main{
    -webkit-column-width:42%;
    column-width: 42%;
    -webkit-column-count:2;
    column-count:2;
    column-gap:5%;
    padding:4.5%;
    }
    .pic{
    border:1px solid #ddd;
    padding:10px;
    border-radius: 5%;
    margin-bottom: 20px;
    -webkit-column-break-inside:avoid; //避免在元素内部断行并产生新列
    break-inside:avoid;
    }
    .pic img{
    width: 100%;
    }
    </style>

    html部分

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    <div id="main">
    <div class="pic">
    <img src="https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=1494624936,3877802643&fm=26&gp=0.jpg" alt="">
    </div>
    <div class="pic">
    <img src="https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=3511243883,1584271914&fm=26&gp=0.jpg">
    </div>
    <div class="pic">
    <img src="https://dss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=427521938,3722192058&fm=111&gp=0.jpg" alt="">
    </div>
    <div class="pic">
    <img src="https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=3777291312,1522321691&fm=26&gp=0.jpg" alt="">
    </div>
    <div class="pic">
    <img src="https://dss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=1537769626,3511701130&fm=111&gp=0.jpg" alt="">
    </div>
    </div>

    那么效果就出来了呀,对没有js没有js,没有js

    效果如下:

    瀑布流

    提示:

    由于兼容性问题,建议在移动端使用~

    Iframe跨域通信

    很多情况下需要用到iframe嵌入子页面以达到也无需求,通常使用场景都是跨页面的情况下,这时候如果需要传递数据怎么处理呢?

    父页面

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    //  iframe页面
    <iframe id="siri_child" src="<%=url%>" onload="postMsg()" width="100%"></iframe>
    <script type="text/javascript">
    var url="<%=url%>";
    function postMsg(){
    var msg = {sendMsg:'sendMsg',action:'registerChildFunc',setParentHeigh:'setParentHeigh'}
    document.getElementById('siri_child').contentWindow.postMessage(msg, url)
    }
    window.addEventListener("message",function(obj){
    var data = obj.data;
    var action = data.action;
    console.log(obj);
    });
    </script>

    子页面

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    //子页面
    window.sendMsg = '';
    window.setParentHeigh=0;
    window.origin='';
    window.addEventListener('message',function(event){
    if(window.parent !== event.source){return}
    if(event.data.action=='registerChildFunc'){
    window.sendMsg=event.data.sendMsg;
    window.setParentHeigh=event.data.setParentHeigh;
    window.origin=event.origin;
    }
    }, false);

    function send(userId){
    if(window.sendMsg){
    var msg = {userId,action:'sendMsg'}
    parent.postMessage(msg, window.origin)
    }
    }

    好吧,看起来很清晰,就不细说了

    Mobx示例

    React必备技能之一> 作为优秀的状态管理工作,Redux之外,Mobx也是一个很好的选择哦,用起来非常的简单,花了点时间研究了一下,瞧下面↓

    入口文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    import React from 'react'
    import {render} from 'react-dom'
    import Routers from './routers/router'
    import { configure } from 'mobx';
    import { Provider } from 'mobx-react';
    import * as stores from './stores'
    configure({ enforceActions: "observed" })

    render((
    <Provider {...stores}>
    <Routers />
    </Provider>
    ), document.getElementById('root'))


    // 开启局部热更新
    if (module.hot) {
    module.hot.accept('./routers/router', () => {
    render((
    <Provider {...stores}>
    <Routers />
    </Provider>
    ), document.getElementById('root'))
    })
    }

    store

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    //index.js
    import shop from './shop'

    export {
    shop,
    }


    //shop.js
    import { observable, action, computed, autorun } from 'mobx';
    import { create, persist } from 'mobx-persist'

    class Shop {
    @persist('list') @observable data = [];
    @observable action = null;
    //持久化测试
    @persist('object') @observable persistTestObj = null //对象这里不能写{} 要么就也写成初始值
    @persist('list') @observable persistTestArr = []
    @persist @observable persistTestNum = 0
    @persist @observable persistTestStr = ""

    //设置初始化数据
    @action
    changeInitialData = (data)=>{
    this.data = data
    }
    @computed get totalCount(){
    return this.data.reduce(function(prev,next){
    return prev + next.count
    },0)
    }
    @computed get totalPrice(){
    return this.data.reduce(function(prev,next){
    return prev + next.count * next.price
    },0)
    }
    @action
    increase = (i)=>{
    this.action = 'increase'
    this.data.find(function(item,index){
    return index == i
    }).count += 1
    }
    @action
    setAction = (data)=>{
    this.action = data
    }
    @action
    decrease = (i)=>{
    this.action = 'decerase'
    this.data.find(function(item,index){
    return index == i
    }).count -= 1
    }
    }

    let _Shop = new Shop()

    autorun(()=>{
    _Shop.action && console.log(_Shop.action == 'increase' ? '您点击了增加':"您点击了减少")
    _Shop.setAction(null)
    },{
    delay:500 //加上delay 多次快速点击只会出现一次 console
    })

    const hydrate = create({
    storage: localStorage, // or AsyncStorage in react-native.
    // default: localStorage
    jsonify: true // if you use AsyncStorage, here shoud be true
    // default: true
    })

    hydrate('shop', _Shop,{
    persistTestObj:{
    "a":10,"b":2
    },
    persistTestArr:[1,3,20],
    persistTestNum:1,
    persistTestStr:'2'
    }).then(() => console.log('_Shop has been hydrated'))

    export default _Shop

    container

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    import React, {Component} from 'react'
    import { inject, observer } from 'mobx-react';
    import './index.scss'
    import tu1 from 'static/1.jpg'

    @inject('shop')
    @observer
    export default class Home extends Component {
    componentDidMount(){
    let data = [
    {
    img:"https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=2781512380,2039838908&fm=200&gp=0.jpg",
    title:"狗狗",
    price:'9.9',
    count:1,
    },
    {
    img:"https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=2781512380,2039838908&fm=200&gp=0.jpg",
    title:"狗狗2",
    price:'19.9',
    count:0,
    },
    {
    img:"https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=2781512380,2039838908&fm=200&gp=0.jpg",
    title:"狗狗3",
    price:'29.9',
    count:10,
    }
    ]
    this.props.shop.changeInitialData(data)
    }
    render () {
    const {
    data, totalCount, totalPrice,
    increase,decrease
    } = this.props.shop

    return(
    <div className="Home">
    <img src={tu1} style={{width:100}} alt=""/>
    <div className="tu2"></div>
    <ul>
    {
    data.length>0 && data.map((item, i)=>{
    return(
    <li key={i}>
    <img src={item.img} alt=""/>
    <span>{item.title}</span>
    <em>${item.price}</em>
    <div>
    <button onClick={()=>decrease(i)}>-</button>
    <span>{item.count}</span>
    <button onClick={()=>increase(i)}>+</button>
    </div>
    </li>
    )
    })
    }
    </ul>
    <p>
    <span className="left">数量:{totalCount}个</span>
    <span className="right">价格:${totalPrice}</span>
    </p>

    </div>
    )
    }
    }

    温馨提示:

    • autorun这里需要监听的是 new Shop()的对象属性
    • mobx-persist初始值最好在上面定义的地方和下面hydrate的地方都写一下(尤其是对象),否则hydrate不写的话只会在执行其中一个有持久化数据的时候才会保存在本地
    • 善用computedmobx状态改变后不会在组件中通过componentWillReceiveProps拦截到,而是直接进入的render,可以在手机进入的时候通过computed监听需要改变的元素,或者autorun来实现吧
    • 真的可以用autorundelay来实现防抖动哦

    node抓取百度头像

    没有头像当然首先想到的是百度咯,如何批量抓取呢,那么这里用node来做一个栗子

    首先安装依赖文件

    "dependencies": {
        "colors": "^1.1.2",
        "node-fetch": "^1.7.3"
    }
    

    分析百度头像接口,大概酱紫

    https://image.baidu.com/search/acjson?tn=resultjson_com&ipn=rj&ct=201326592&fp=result&queryWord=${encodeURIComponent('网络头像')}&cl=2&lm=-1&ie=utf-8&oe=utf-8&word=${encodeURIComponent('非主流')}&pn=${pn.page}&width=180&height=180`
    

    代码撸起

    var https = require("https");
    var fs = require("fs");
    var fetch = require('node-fetch');
    var colors = require('colors'); 
    var pn={page:1,count:1,max:900} //控制分页+显示名称+长度
    

    将文件地址写入到.txt

    function asyncAppendFile(url){
        return new Promise(function (resolve, reject){
            fs.appendFile('./img.txt', url+'\r\n',function(err){
                  if(err){
                      console.log(err)
                      reject(err);
                  }
                      resolve()
                });
        });
    }
    

    将图片获取并保存到文件夹

    function asyncWriteFile(imgUrl){
        return new Promise(function (resolve, reject){
            fs.writeFile(`./downImg/head${pn.count}.jpg`, imgUrl, "binary",                 function(err){
                    if(err){
                        console.log("down fail");
                        reject(err);
                      }else{
                          console.log(`文件:head${pn.count}.jpg 下载成功!`.green)
                        resolve()
                      }
                });
            });
    }
    

    循环图片数组并执行存储操作

    function syncArrMap(imgArr, selfObj){
        if(imgArr[selfObj.now].thumbURL){
            https.get(imgArr[selfObj.now].thumbURL, function(res){
                var imgUrl = "";
                res.setEncoding("binary");
                res.on("data", function(url){
                    imgUrl += url;
                });
                res.on("end", function(){
                    if(pn.count>pn.max) return;
                    asyncAppendFile(imgArr[selfObj.now].thumbURL)
                        .then((data) => asyncWriteFile(imgUrl))
                        .then((data) => {
                            pn.count ++
                            selfObj.now += 1
                            if(selfObj.now>=selfObj.length-1){
                                pn.page++
                                getImageData()
                            }else{
                                syncArrMap(imgArr, selfObj)
                            }
                    })
    
                });
            });
        }else{
            selfObj.length -= 1
        }
    }
    

    最后获取图片

    getImageData()
    function getImageData(){
        fetch(`https://image.baidu.com/search/acjson?tn=resultjson_com&ipn=rj&ct=201326592&fp=result&queryWord=${encodeURIComponent('网络头像')}&cl=2&lm=-1&ie=utf-8&oe=utf-8&word=${encodeURIComponent('非主流')}&pn=${pn.page}&width=180&height=180`)
            .then(res=>res.json())
            .then(data=>{
                var imgArr = data.data
                var selfObj = {length:imgArr.length,now:0}
                  syncArrMap(imgArr,selfObj)
            })
    }
    

    客户端系统判断

    判断客户端是PC还是手机

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    function IsPC() {
    var userAgentInfo = navigator.userAgent;
    var Agents = ["Android", "iPhone",
    "SymbianOS", "Windows Phone",
    "iPad", "iPod"];
    var flag = true;
    for (var v = 0; v < Agents.length; v++) {
    if (userAgentInfo.indexOf(Agents[v]) > 0) {
    flag = false;
    break;
    }
    }
    return flag;
    }

    var flag = IsPC();
    console.log(flag)//true为PC端,false为手机端和ipad

    Iscroll使用导致键盘不弹出

    Iscroll使用禁用了浏览器默认事件,导致键盘不弹出也不能手动上划出来

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    this.timerId = null;
    let cnt = 0;
    setInterval( () => {
    if (cnt < 4) {
    cnt++;
    } else {
    clearInterval(this.timerId);
    this.timerId = null;
    return;
    }
    if(this.state.OS < 11){
    this.refs.ipt.scrollIntoView(true)
    this.refs.ipt.scrollIntoViewIfNeeded();
    document.body.scrollTop=document.body.scrollHeight;
    }
    }, 300);

    相关问题

    更新IScroll不能滚动的问题

    1
    onRefresh={()=>this.state.n<5 ? this.setState({n:this.state.n+1}) : false}

    初始化仓库失败,因新仓库有文件

    1
    2
    git pull –rebase origin master
    git push -u origin master

    微信分享失败

    1
    2
    需要再componentDidMounted中才会生效
    或者分享失败时做刷新操作

    后端做限制不能访问资源还是 http/https访问问题

    1
    <meta name="referrer" content="never">   //no-referrer  可以访问

    mac显示影藏文件

    1
    2
    defaults write com.apple.finder AppleShowAllFiles Yes && killall Finder //显示隐藏文件
    defaults write com.apple.finder AppleShowAllFiles No && killall Finder //不显示隐藏文件

    css超出…

    1
    2
    3
    4
    5
    6
    7
    8
    9
    //超出省略号
    overflow:hidden;
    text-overflow:ellipsis;
    white-space:nowrap;

    display:-webkit-box;
    -webkit-box-orient:vertical;
    -webkit-line-clamp:3;
    overflow:hidden;

    向网页中动态插入可执行js脚本

    1
    2
    3
    4
    5
    var head = document.getElementsByTagName('head')[0];
    var script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = 'https://unpkg.com/axios/dist/axios.min.js';
    head.appendChild(script);

    React深入一丢丢

    1.给setState传入回调函数

    setState其实是异步的. 因为出于性能优化考虑, React会将多次setState做一次批处理. 于是setState并不会在被调用之后立即改变我们的state. 这就意味着你并不能依赖于在调用setState方法之后立即使用state, 因为此时你并不能确认该state更新与否. 当然针对这个问题我们也有解决办法–用前一个state(previous state)作为需要传入函数的参数,将一个函数作为参数传递给setState. 这样做能保证你传入的函数需要取到的state一定会是被传入的setState执行之后的state.

    举个例子就是:

    // 不使用callback
    state={a:0}
    this.setState({a:1})
    this.setState({a:2})
    console.log(this.state.a) //0
    // 使用callback
    state={a:0}
    this.setState({a:1},()=>console.log(this.state.a)) //1
    this.setState({a:2})
    console.log(this.state.a) //0
    // 传入函数
    state={a:0}
    this.setState({a:1})
    this.setState((nextState, nextProps)=>{
        console.log(nextState.a) //1
    })
    console.log(this.state.a) //0
    

    2.使用无状态组件

    export function UIComponent(props){
        return <div>{props.name}</div>
    }
    

    3. 使用高阶组件

    export function HOC(WrappedComponent) {
        return class Test extends Component {
          render() {
              const newProps = {
                  title: 'New Header',
                  footer: false,
                  showFeatureX: false,
                  showFeatureY: true
              };
    
              return <WrappedComponent {...this.props} {...newProps} />
          }
        }
    }        
    

    4.使用简单索引作为key

    通常循环列表的时候都会用数组顺序作为索引的key值,而更好的性能优化是把key和我们想要表达的数据紧紧关联在一起

    //bad->会阻碍React对于我们组件的优化,可能传了一个假key
    {todos.map((todo, index) =>
        <Todo
            {...todo}
            key={index}
        />
    )}
    //good -> 保持了对数据的索引
    {todos.map((todo) =>
        <Todo {...todo}
        key={todo.id} />
    )}
    

    5.shouldComponentUpdate检查

    合理的实现shouldComponentUpdate能够避免不必要的重新渲染.
    当React想要重新渲染组件时, React会检查shouldComponentUpdate这个函数是返回true还是false(这将决定组件是否更新.)React默认这个函数是返回true的,意味着无论state还是props发生变化, 组件都将被更新). 所以对于那些不需要变化的组件, 我们可以直接返回false来阻止组件更新,以此提升性能. 但更多的时候, 我们需要在这个函数内写自己的逻辑来判断组件是否需要更新.

    shouldComponentUpdate(nextProps, nextState) {
       if (nextProps.a !== this.props.a) {
             return true;
       }
       return false;
    }
    

    6.使用PureComponent

    Pure Component默认会在shouldComponentUpdate方法中做浅比较. 只有PureComponent检测到state或者props发生变化时,PureComponent才会调用render方法,这种实现可以避免发生在state或者props没有真正改变的重新渲染.
    Recompose提供了一个叫pure的高阶组件来实现这个功能, React在v15.3.0中正式加入了React.PureComponent.

    浅比较只会"浅"检查组件的props和state,这就意味着嵌套对象 和 数组 是不会被比较的。
    handleClick() {
        let {items} = this.state
        items.push('new-item')
        this.setState({ items })
    }
    render() {
        return (
            <div>
                  <button onClick={this.handleClick} />
                  <ItemList items={this.state.items} />
            </div>
        )
    }        
    

    如果ItemList是纯组件(PureComponent),那么这时它是不会被重新渲染的,因为尽管this.state.items的值发生了改变,但是它仍然指向同一个对象的引用(浅比较)

    git常用命令

    git操作首先推荐使用sourcetree一款很好的可视化工具,但是某些时候还是需要自己操作命令的,毕竟没有工具的是也是需要熟练操作的😁

    --soft 将本地撤回点之后的所有修改文件回退到git暂存区
    --mixed 将本地撤回点之后的所有修改文件修改回退到工作区(回退的默认方式)
    --hard 将本地撤回点之后的所有修改文件做删除操作
    同样为撤销操作的git reset 和 git revert:
        git reset,它不会改变现在的提交历史
        Revert撤销一个提交的同时会创建一个新的提交。
    因此,git revert可以用在公共分支上,git reset应该用在私有分支上。
    

    查看、添加、提交、删除、找回,重置修改文件

    Git常用命令 命令释义
    git help 显示command的help
    git show $id 显示某次提交的内容(不加id显示最近一次)
    git checkout – file 抛弃文件工作区修改
    git checkout . 抛弃所有工作区修改(add .到git暂存区的不能取消)
    git add file 将工作文件修改添加到git暂存区
    git add . 将所有修改过的添加到git暂存区
    git reset file 从git暂存区恢复到工作区
    git reset – . 从git暂存区(add . 到达的区域)恢复全部到工作区
    git reset –hard 删除所有git暂存区的文件修改,也不会在工作区保留,慎用啊!!
    git reset HEAD^ 回退版本,一个^表示一个版本,可以多个,另外也可以使用 git reset HEAD~n这种形式 或者 git reset commit-id,将上个版本所有的修改回退到工作区
    git reset commit-id 删除所有git暂存区的文件修改,也不会在工作区保留,慎用啊!!
    git commit -m ‘xxx’ 将git暂存区提交到history,然后才能从history push到线上
    git commit -am ‘xxx’ 等于git add . + git commit -m ‘xx’
    git revert HEAD 放弃当前commit所有修改,撤销到前一次 commit内容 到 git暂存区(撤销也会作为一次提交进行保存。)
    git revert HEAD~1 撤销前前一次 commit
    git revert commit_id 比如:(git revert fa042ce57ebbe5bb9c8db709f719cec2c58ee7ff)撤销指定的版本,
    git rm file 从版本库中删除文件

    查看文件diff

    命令 释义
    git diff 比较当前文件和暂存区文件差异 git diff
    git diff commit_id 显示某次提交的的diff
    git diff branch1..branch2 在两个分支之间比较
    git diff –stat 仅仅比较统计信息

    查看提交记录

    命令 释义
    git log file 查看该文件每次提交记录
    git log -p 查看每次详细修改内容的diff
    git log -p -2 查看最近两次详细修改内容的diff
    git log –stat 查看提交统计信息

    Git本地分支管理

    查看、切换、创建和删除分支
    命令 释义
    git branch -r 查看远程分支 /a 全部分支
    git branch -v 查看各个分支最后提交信息
    git checkout -b xx_branch 创建新的分支,并且切换过去
    git branch new_branch 创建新的分支
    git checkout xx_branch 切换到某个分支,没有该分支则以本分支创建一个(本地修改也会一起切换到对应分支)
    git checkout -b new_branch branch 基于branch创建新的new_branch
    git checkout $id 把某次历史提交记录checkout出来,但无分支信息,切换到其他分支会自动删(主要还是用来查看旧版本信息为主)
    git checkout $id -b new_branch 把某次历史提交记录checkout出来,创建成一个分支
    git branch -d xx_branch 删除某个分支
    git branch -D 强制删除某个分支 (未被合并的分支被删除的时候需要强制)
    git push origin :remote_branch 删除远程分支
    分支合并和rebase
    命令 释义
    git merge xxx_branch 将xxx_branch分支合并到当前分支
    git merge origin/master –no-ff 不要Fast-Foward合并,这样可以生成merge提交
    git cherry-pick commitid 把指定commitid的变动合并到当前分支

    Git暂存管理

    命令 释义
    git stash(git stash create ‘名字’) 本地暂存区暂存,当一个分支未开发完成又不想commit的时候,是不能切换到其他分支的,除非把改动的文件进行暂存,切换回来的时候再恢复就行了
    git stash list 列所有stash本地暂存区
    git stash apply 恢复本地暂存区的内容(恢复到工作副本)
    git stash drop 删除本地暂存区

    Git远程分支管理

    命令 释义
    git pull 抓取远程仓库所有分支更新并合并到本地
    git pull –no-ff 不要快进合并(Create a merge commit)
    git merge origin/master 将远程主分支合并到本地当前分支
    git checkout –track origin/master 检出远程分支到本地
    git checkout -b local_branch origin/remote_branch 基于远程分支创建本地分支,并切换到新建分支
    git push push所有分支
    git push origin master 将本地主分支推到(已跟踪的)远程主分支
    git push origin HEAD:master 不同分支之间提交(未跟踪)比如 test->develop
    git push origin local_branch 创建远程分支并推送到该分支, local_branch是远程仓库名

    Git远程仓库管理

    命令释义
    git remote -v查看远程服务器地址和仓库名称
    git remote show origin查看远程服务器仓库状态
    git remote add origin git@github:robbin/robbin_site.git添加远程仓库地址
    git remote set-url origin git@github.com:robbin/robbin_site.git设置远程仓库地址(用于修改远程仓库地址)
    git remote rm删除远程仓库
    git push -u origin master首次将本地分支提交到远程master分支,”-u”是首次提交需要增加追踪(track),-u后以后提交到该分支的远程只需要git push,否则需要git push origin xxx
    git remote set-head origin master设置远程仓库的HEAD指向master分支(可以用checkout直接切换)

    OVER