h5实现slider滑块功能及样式自定义
公司最近人手不足,于是,又开始折腾起Html来了
本文主要讲slider滑块的实现、样式自定义、刻度绘制、与输入框的联动我们先来看看效果图
h5 slider.gif上图中,我们需要实现的难点就是那个绿色的滑块,其它都是输入框及文本框,容易实现。
滑块的实现
其实,只要设置input的type,即可实现滑块功能
12 <input <span class="hljs-keyword">id</span>=<span class="hljs-string">"slider"</span> type=<span class="hljs-string">"range"</span> min=<span class="hljs-string">"0"</span> max=<span class="hljs-string">"550"</span> step=<span class="hljs-string">"1"</span> /> <span class="hljs-comment">// step表示滑动的最小步长</span>效果如下:
range.jpg样式自定义
虽然实现了滑块的效果,但是感觉有点太丑了,主要是和设计相差太远,于是,我们来美化下,先看看css
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697 <span class="hljs-comment">/*** @range.css**/</span><span class="hljs-selector-class">.ne-range_thumb</span>,<span class="hljs-selector-tag">input</span><span class="hljs-selector-class">.ne-range</span><span class="hljs-selector-attr">[type=range]</span><span class="hljs-selector-pseudo">::-webkit-slider-thumb</span> {<span class="hljs-attribute">width</span>: <span class="hljs-number">2em</span>;<span class="hljs-attribute">height</span>: <span class="hljs-number">2em</span>;<span class="hljs-attribute">border-radius</span>: <span class="hljs-number">50%</span>;<span class="hljs-attribute">border</span>: <span class="hljs-number">0</span><span class="hljs-comment">/**1px solid #45bd5c*/</span>;<span class="hljs-attribute">background-color</span>: <span class="hljs-number">#5cdf84</span>;<span class="hljs-attribute">box-shadow</span>: <span class="hljs-number">0</span> <span class="hljs-number">1px</span> <span class="hljs-number">4px</span> <span class="hljs-built_in">rgba</span>(0, 0, 0, 0.21);<span class="hljs-attribute">-webkit-transition</span>: border-color <span class="hljs-number">0.15s</span>, background-color <span class="hljs-number">0.15s</span>;<span class="hljs-attribute">transition</span>: border-color <span class="hljs-number">0.15s</span>, background-color <span class="hljs-number">0.15s</span>;<span class="hljs-attribute">cursor</span>: pointer;<span class="hljs-attribute">background-clip</span>: padding-box;<span class="hljs-attribute">box-sizing</span>: border-box;}<span class="hljs-selector-class">.ne-range_thumb</span><span class="hljs-selector-pseudo">:active</span>,<span class="hljs-selector-tag">input</span><span class="hljs-selector-class">.ne-range</span><span class="hljs-selector-attr">[type=range]</span><span class="hljs-selector-pseudo">::-webkit-slider-thumb</span><span class="hljs-selector-pseudo">:active</span> {<span class="hljs-attribute">border</span>: <span class="hljs-number">0</span><span class="hljs-comment">/**1px solid #45bd5c*/</span>;<span class="hljs-attribute">background-color</span>: <span class="hljs-number">#5cdf84</span>;}<span class="hljs-selector-class">.ne-range_track</span>,<span class="hljs-selector-tag">input</span><span class="hljs-selector-class">.ne-range</span><span class="hljs-selector-attr">[type=range]</span> {<span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>;<span class="hljs-attribute">height</span>: <span class="hljs-number">8px</span>;<span class="hljs-attribute">border-radius</span>: <span class="hljs-number">8px</span>;<span class="hljs-attribute">margin</span>: .<span class="hljs-number">8em</span> <span class="hljs-number">0</span>;<span class="hljs-attribute">padding</span>: <span class="hljs-number">0</span>;<span class="hljs-attribute">cursor</span>: pointer;<span class="hljs-attribute">border</span>: <span class="hljs-number">0</span>;<span class="hljs-comment">/**background-color: #45bd5c;*/</span><span class="hljs-attribute">background</span>: <span class="hljs-built_in">-webkit-linear-gradient</span>(#40c35f, #40c35f) no-repeat <span class="hljs-number">#cccccc</span>;<span class="hljs-attribute">background-size</span>: <span class="hljs-number">0%</span> <span class="hljs-number">100%</span>;}<span class="hljs-selector-class">.ne-range_track</span> > <span class="hljs-selector-tag">span</span> {<span class="hljs-attribute">display</span>: block;<span class="hljs-attribute">width</span>: <span class="hljs-number">0%</span>;<span class="hljs-attribute">height</span>: <span class="hljs-number">100%</span>;<span class="hljs-attribute">background-color</span>: <span class="hljs-number">#40c35f</span>;}<span class="hljs-selector-class">.ne-range_tips</span> {<span class="hljs-attribute">position</span>: absolute;<span class="hljs-attribute">margin-top</span>: -<span class="hljs-number">2em</span>;<span class="hljs-attribute">width</span>: <span class="hljs-number">6em</span>;<span class="hljs-attribute">text-align</span>: center;<span class="hljs-attribute">margin-left</span>: -<span class="hljs-number">3em</span>;}<span class="hljs-selector-class">.ne-range_thumb</span> > <span class="hljs-selector-class">.ne-range_tips</span> {<span class="hljs-attribute">margin-left</span>: -<span class="hljs-number">2.15em</span>;}<span class="hljs-selector-class">.ne-range_tips</span> > <span class="hljs-selector-tag">span</span> {<span class="hljs-attribute">position</span>: relative;<span class="hljs-attribute">display</span>: inline-block;<span class="hljs-attribute">padding</span>: <span class="hljs-number">0</span> <span class="hljs-number">3px</span>;<span class="hljs-attribute">min-width</span>: <span class="hljs-number">1.2em</span>;<span class="hljs-attribute">color</span>: white;<span class="hljs-attribute">background</span>: <span class="hljs-built_in">rgba</span>(0, 0, 0, 0.5);<span class="hljs-attribute">border-radius</span>: <span class="hljs-number">3px</span>;<span class="hljs-attribute">text-align</span>: center;}<span class="hljs-selector-class">.ne-range_tips</span> > <span class="hljs-selector-tag">span</span><span class="hljs-selector-pseudo">::after</span> {<span class="hljs-attribute">content</span>: <span class="hljs-string">''</span>;<span class="hljs-attribute">position</span>: absolute;<span class="hljs-attribute">left</span>: <span class="hljs-number">50%</span>;<span class="hljs-attribute">bottom</span>: -<span class="hljs-number">0.25em</span>;<span class="hljs-attribute">margin-left</span>: -<span class="hljs-number">0.3em</span>;<span class="hljs-attribute">border</span>: <span class="hljs-number">0.3em</span> solid <span class="hljs-built_in">rgba</span>(0, 0, 0, 0.5);<span class="hljs-attribute">border-right-color</span>: transparent;<span class="hljs-attribute">border-left-color</span>: transparent;<span class="hljs-attribute">border-bottom</span>: <span class="hljs-number">0</span>;}<span class="hljs-comment">/*Real Range*/</span><span class="hljs-selector-tag">input</span><span class="hljs-selector-class">.ne-range</span><span class="hljs-selector-attr">[type=range]</span> {<span class="hljs-attribute">position</span>: relative;<span class="hljs-attribute">outline</span>: <span class="hljs-number">0</span>;<span class="hljs-attribute">-webkit-appearance</span>: none <span class="hljs-meta">!important</span>;}<span class="hljs-selector-tag">input</span><span class="hljs-selector-class">.ne-range</span><span class="hljs-selector-attr">[type=range]</span><span class="hljs-selector-pseudo">::-webkit-slider-thumb</span> {<span class="hljs-attribute">-webkit-appearance</span>: none <span class="hljs-meta">!important</span>;}<span class="hljs-comment">/*Virtual Range*/</span><span class="hljs-selector-class">.ne-range</span> {<span class="hljs-attribute">display</span>: inline-block;<span class="hljs-attribute">position</span>: relative;<span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>;<span class="hljs-attribute">font-size</span>: <span class="hljs-number">1em</span>;}<span class="hljs-selector-class">.ne-range_thumb</span> {<span class="hljs-attribute">position</span>: absolute;<span class="hljs-attribute">top</span>: <span class="hljs-number">0</span>;<span class="hljs-attribute">margin-left</span>: -<span class="hljs-number">0.85em</span>;}<span class="hljs-selector-class">.ne-range_thumb</span><span class="hljs-selector-class">.ondrag</span> > <span class="hljs-selector-class">.ne-range_tips</span> {<span class="hljs-attribute">visibility</span>: visible;}有点多,说下关键点,thumb相关的是设置滑块按钮(即那个圆点)相关属性,track即那一条滑动条。
需要注意的是下面两行代码
123 <span class="hljs-selector-tag">background</span>: <span class="hljs-selector-tag">-webkit-linear-gradient</span>(<span class="hljs-selector-id">#40c35f</span>, <span class="hljs-selector-id">#40c35f</span>) <span class="hljs-selector-tag">no-repeat</span> <span class="hljs-selector-id">#cccccc</span>;<span class="hljs-selector-tag">background-size</span>: 0% 100%;background设置了-webkit,因为我这边是针对手机端;-linear-gradient表示线性渐变,括号中两个颜色值都是#40c35f,此时就是纯色的绿色;no-repeat表示背景图像仅出现一次,不会重复出现;最后的#cccccc则定义了右边没有滑到的区域为灰色。
而background-size设置了两个宽度百分比,分别是#40c35f占的百分比和#cccccc占的百分比,这里都是相对于整个滑块区域来讲的。
关于线性渐变,下面一张linear-gradient(#cccccc, #000000)供参考linear-gradient(#cccccc, #000000).png说完css,我们在来看看html
12 <input type=<span class="hljs-string">"range"</span> id=<span class="hljs-string">"slider"</span> name=<span class="hljs-string">"slider"</span> <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"ne-range"</span> value=<span class="hljs-string">"0"</span> style=<span class="hljs-string">"margin-top: 4vw;"</span>/>和之前的基本一致,这里没有设置min,max,step等,留在后面js中设置,没什么大的区别
1234567891011121314151617181920212223242526272829303132333435 $.fn.RangeSlider = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">cfg</span>) </span>{<span class="hljs-keyword">this</span>.sliderCfg = {<span class="hljs-attr">min</span>: cfg && !<span class="hljs-built_in">isNaN</span>(<span class="hljs-built_in">parseFloat</span>(cfg.min)) ? <span class="hljs-built_in">Number</span>(cfg.min) : <span class="hljs-literal">null</span>,<span class="hljs-attr">max</span>: cfg && !<span class="hljs-built_in">isNaN</span>(<span class="hljs-built_in">parseFloat</span>(cfg.max)) ? <span class="hljs-built_in">Number</span>(cfg.max) : <span class="hljs-literal">null</span>,<span class="hljs-attr">step</span>: cfg && <span class="hljs-built_in">Number</span>(cfg.step) ? cfg.step : <span class="hljs-number">1</span>,<span class="hljs-attr">callback</span>: cfg && cfg.callback ? cfg.callback : <span class="hljs-literal">null</span>};<span class="hljs-keyword">var</span> $input = $(<span class="hljs-keyword">this</span>);<span class="hljs-keyword">var</span> min = <span class="hljs-keyword">this</span>.sliderCfg.min;<span class="hljs-keyword">var</span> max = <span class="hljs-keyword">this</span>.sliderCfg.max;<span class="hljs-keyword">var</span> step = <span class="hljs-keyword">this</span>.sliderCfg.step;<span class="hljs-keyword">var</span> callback = <span class="hljs-keyword">this</span>.sliderCfg.callback;$input.attr(<span class="hljs-string">'min'</span>, min).attr(<span class="hljs-string">'max'</span>, max).attr(<span class="hljs-string">'step'</span>, step);$input.bind(<span class="hljs-string">"input"</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">e</span>) </span>{$input.attr(<span class="hljs-string">'value'</span>, <span class="hljs-keyword">this</span>.value);$input.css(<span class="hljs-string">'background-size'</span>, <span class="hljs-keyword">this</span>.value * <span class="hljs-number">100.0</span> / max + <span class="hljs-string">'% 100%'</span>);<span class="hljs-keyword">if</span> ($.isFunction(callback)) {callback(<span class="hljs-keyword">this</span>);}});};<span class="hljs-keyword">var</span> change = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">$input</span>) </span>{<span class="hljs-comment">/*拖动滑块的事件,内容可自行定义*/</span>}$(<span class="hljs-string">'#slider'</span>).RangeSlider({ <span class="hljs-attr">min</span>: <span class="hljs-number">0</span>, <span class="hljs-attr">max</span>: <span class="hljs-number">550</span>, <span class="hljs-attr">step</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">callback</span>: change });这里注意,绑定的是公式输入有误input.css,这里我们改变background-size第一个百分比就可以达到左侧绿色覆盖的目的。
这里就完成了滑块的基本功能。刻度绘制
但是,离上面效果图还有蛮大差距的。比如上面的刻度,这里我取巧使用了宽度百分比来直接绘制了数字:
123456789101112131415 <div <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"ne-cell-center"</span> style=<span class="hljs-string">"width: 9%"</span>><span class="xml"><span class="hljs-tag"><<span class="hljs-name">label</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"ne-label"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"color: #333333; font-size: 3.2vw"</span>></span>0<span class="hljs-tag"></<span class="hljs-name">label</span>></span></span><span class="xml"><span class="hljs-tag"></<span class="hljs-name">div</span>></span></span><div <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"ne-cell-center"</span> style=<span class="hljs-string">"width: 9%"</span>><span class="xml"><span class="hljs-tag"><<span class="hljs-name">label</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"ne-label"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"color: #333333; font-size: 3.2vw"</span>></span>50<span class="hljs-tag"></<span class="hljs-name">label</span>></span></span><span class="xml"><span class="hljs-tag"></<span class="hljs-name">div</span>></span></span><div <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"ne-cell-center"</span> style=<span class="hljs-string">"width: 9%"</span>><span class="xml"><span class="hljs-tag"><<span class="hljs-name">label</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"ne-label"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"color: #333333; font-size: 3.2vw"</span>></span>100<span class="hljs-tag"></<span class="hljs-name">label</span>></span></span><span class="xml"><span class="hljs-tag"></<span class="hljs-name">div</span>></span></span><div <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"ne-cell-center"</span> style=<span class="hljs-string">"width: 9%"</span>><span class="xml"><span class="hljs-tag"><<span class="hljs-name">label</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"ne-label"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"color: #333333; font-size: 3.2vw"</span>></span>150<span class="hljs-tag"></<span class="hljs-name">label</span>></span></span><span class="xml"><span class="hljs-tag"></<span class="hljs-name">div</span>></span></span><div <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"ne-cell-center"</span> style=<span class="hljs-string">"width: 9%"</span>><span class="xml"><span class="hljs-tag"><<span class="hljs-name">label</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"ne-label"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"color: #333333; font-size: 3.2vw"</span>></span>200<span class="hljs-tag"></<span class="hljs-name">label</span>></span></span><span class="xml"><span class="hljs-tag"></<span class="hljs-name">div</span>></span></span><div <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"ne-cell-center"</span> style=<span class="hljs-string">"width: 9%"</span>><span class="xml"><span class="hljs-tag"><<span class="hljs-name">label</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"ne-label"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"color: #333333; font-size: 3.2vw"</span>></span>250<span class="hljs-tag"></<span class="hljs-name">label</span>></span></span><span class="xml"><span class="hljs-tag"></<span class="hljs-name">div</span>></span></span><div <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"ne-cell-center"</span> style=<span class="hljs-string">"width: 9%"</span>><span class="xml"><span class="hljs-tag"><<span class="hljs-name">label</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"ne-label"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"color: #333333; font-size: 3.2vw"</span>></span>300<span class="hljs-tag"></<span class="hljs-name">label</span>></span></span><span class="xml"><span class="hljs-tag"></<span class="hljs-name">div</span>></span></span><div <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"ne-cell-center"</span> style=<span class="hljs-string">"width: 9%"</span>><span class="xml"><span class="hljs-tag"><<span class="hljs-name">label</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"ne-label"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"color: #333333; font-size: 3.2vw"</span>></span>350<span class="hljs-tag"></<span class="hljs-name">label</span>></span></span><span class="xml"><span class="hljs-tag"></<span class="hljs-name">div</span>></span></span><div <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"ne-cell-center"</span> style=<span class="hljs-string">"width: 9%"</span>><span class="xml"><span class="hljs-tag"><<span class="hljs-name">label</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"ne-label"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"color: #333333; font-size: 3.2vw"</span>></span>400<span class="hljs-tag"></<span class="hljs-name">label</span>></span></span><span class="xml"><span class="hljs-tag"></<span class="hljs-name">div</span>></span></span><div <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"ne-cell-center"</span> style=<span class="hljs-string">"width: 9%"</span>><span class="xml"><span class="hljs-tag"><<span class="hljs-name">label</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"ne-label"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"color: #333333; font-size: 3.2vw"</span>></span>450<span class="hljs-tag"></<span class="hljs-name">label</span>></span></span><span class="xml"><span class="hljs-tag"></<span class="hljs-name">div</span>></span></span><div <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"ne-cell-center"</span> style=<span class="hljs-string">"width: 9%"</span>><span class="xml"><span class="hljs-tag"><<span class="hljs-name">label</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"ne-label"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"color: #333333; font-size: 3.2vw"</span>></span>500<span class="hljs-tag"></<span class="hljs-name">label</span>></span></span><span class="xml"><span class="hljs-tag"></<span class="hljs-name">div</span>></span></span><div <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"ne-cell-center"</span> style=<span class="hljs-string">"width: 9%"</span>><span class="xml"><span class="hljs-tag"><<span class="hljs-name">label</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"ne-label"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"color: #333333; font-size: 3.2vw"</span>></span>550<span class="hljs-tag"></<span class="hljs-name">label</span>></span></span><span class="xml"><span class="hljs-tag"></<span class="hljs-name">div</span>></span></span><div <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"align-right"</span>><span class="xml"><span class="hljs-tag"><<span class="hljs-name">label</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"ne-label"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"font-size: 2.5vw"</span>></span>单位:毫升(ml)<span class="hljs-tag"></<span class="hljs-name">label</span>></span></span><span class="xml"><span class="hljs-tag"></<span class="hljs-name">div</span>></span></span>当然有很多更好的办法,至少可以写个js循环,但是第一次写h5,还是先实现功能再考虑优化吧。
到这里,我们就实现了一个滑块,效果图如下:slider.jpg与输入框联动
但是,最初的效果图中,滑块是可以和上方的输入框联动的。于是,我们再定义一个数字输入框:
12 <input id=<span class="hljs-string">"amount"</span> name=<span class="hljs-string">"amount"</span> <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"ne-input"</span> placeholder=<span class="hljs-string">"只允许输入数字"</span> pattern=<span class="hljs-string">"\d*"</span> type=<span class="hljs-string">"number"</span>>要达到输入框内容跟着滑块变化,我们需要改下上面js中的change方法,让滑块滑动时,改变amount输入框的值
12345 <span class="hljs-keyword">var</span> change = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-params">($input)</span> </span>{<span class="hljs-comment">/*拖动滑块的事件,内容可自行定义*/</span>$(<span class="hljs-string">"#amount"</span>).val($input.value);}然后,当输入框输入数字时,我们的滑块也需要跟着一起移动:
123456789101112131415 $(<span class="hljs-string">'#amount'</span>).bind(<span class="hljs-string">"input"</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">e</span>) </span>{<span class="hljs-keyword">var</span> value = <span class="hljs-number">0</span>;<span class="hljs-comment">// 过滤下输入内容,因为个别特殊机型手机在input设置了只能输入数字后还是能输入符号</span><span class="hljs-keyword">if</span> (<span class="hljs-regexp">/^[1-9][0-9]*/</span>.test(<span class="hljs-keyword">this</span>.value)) {value = <span class="hljs-keyword">this</span>.value;}<span class="hljs-comment">// 这里保证输入最大值为550,与滑块一致</span><span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>.value > <span class="hljs-number">550</span>) {value = <span class="hljs-number">550</span>;$(<span class="hljs-string">"#amount"</span>).val(<span class="hljs-number">550</span>);}<span class="hljs-comment">// 这里设置滑块的值和css</span>$(<span class="hljs-string">"#slider"</span>).val(value).css(<span class="hljs-string">'background-size'</span>, value * <span class="hljs-number">100.0</span> / <span class="hljs-number">550</span> + <span class="hljs-string">'% 100%'</span>);});至此,我们就完成了滑块及相关功能:
h5 slider.jpgps:中间虽然还有一些css没有给出,但是都是无关紧要的,比如div的class中ne-cell对应的css,就是一些常规的布局,相信会h5的肯定比我这个刚接触几天时间的人熟悉。另外,刚接触h5,写得有问题的地方多谢指出及纠正。
完成滑块功能时,也是网上找资料,其中主要借鉴了以下博文:
https://blog.csdn.net/u013347241/article/details/51560290作者:ThinkinLiu
链接:https://www.jianshu.com/p/54fd0f8f8481
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。