Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
項(xiàng)目開發(fā)中,你一定遇到過精度丟失的問題!比如某個無良的后端返回了一個超16位的數(shù)字訂單號,比如0.1+0.2 !=0.3等等:
let a=0.1235678912345623456
console.log(a)
let b=256.1235678912345623456
console.log(b)
let c=0.1
let d=0.2
console.log(c + d)
let e=2.55
let f=1.55
console.log(e.toFixed(1))
console.log(f.toFixed(1))
01
精度丟失的原因
是什么原因造成的捏?
嗯?
大道理咱也不會說,問就是一句話回復(fù):
在十進(jìn)制轉(zhuǎn)二進(jìn)制的過程中,因js存儲位數(shù)有限制,末位就會0舍1入取近似值,從而導(dǎo)致再轉(zhuǎn)回十進(jìn)制時產(chǎn)生誤差。
02
如何解決
使用toPrecision
這個方法主要用于純展示。先用toPrecision保留一定位數(shù)的經(jīng)度,再通過parseFloat展示。
例如:
console.log(parseFloat(0.30000000000000004.toPrecision(12)))
這個12是精度默認(rèn)值或者說是一個經(jīng)驗(yàn)值,12位一般都能解決0000...1和0000...9的問題。一般不適合浮點(diǎn)數(shù)的運(yùn)算。
先轉(zhuǎn)整數(shù)進(jìn)行運(yùn)算,再轉(zhuǎn)成小數(shù)
這種方式是我之前浮點(diǎn)運(yùn)算時經(jīng)常用到的方法。我們拿0.1+0.2的運(yùn)算來舉例:
let a=(0.1*10 + 0.2*10) / 10
console.log(a) //0.3
但這種方法也不是萬能的,有時候也會失精:
console.log(33.41*100) //3340.9999999999995
console.log(2.55*100) //254.99999999999997
真是防不勝防啊!這時候我們也可以使用Math.round()方法來達(dá)到我們的目的,如下:
console.log(Math.round(33.41*100)) //3341
console.log(Math.round(2.55*100)) //255
console.log((Math.round(0.1*10) + Math.round(0.2*10)) / 10) //0.3
先加上1e-14或Number.EPSILON再取值
給浮點(diǎn)數(shù)加上一個極小的數(shù)就可以達(dá)到目的。獲取極小的數(shù)有兩種方式:
先來看看Number.EPSILON是什么?
console.log(Number.EPSILON) //2.220446049250313e-16
console.log(Number.EPSILON.toFixed(20)) //0.00000000000000022204
這兩種方式都可以,看自己的喜好啦!
let a=0.1235678912345623456
console.log((a+1e-14).toFixed(1)) //0.1
console.log((0.1 + Number.EPSILON + 0.2 + Number.EPSILON).toFixed(1))
//0.3
第三方庫
第三方庫主要介紹以下四種:
安裝:
npm install --save bignumber.js
引入:
import BigNumber from 'bignumber.js';
使用:
const a=new BigNumber(0.2);
const b=new BigNumber(0.1)
let c=a.plus(b)
console.log(c) //BigNumber {s: 1, e: -1, c: Array(1)}
console.log(c.toString()) //0.3
console.log(c.toNumber()) //0.3
官網(wǎng):https://mikemcl.github.io/bignumber.js/
安裝:
npm install number-precision --save
引入:
import NP from 'number-precision';
使用:
console.log(NP.strip(0.09999999999999998)); // 四舍五入:=0.1
console.log(NP.round(0.105, 2)) //取2位小數(shù),四舍五入:=0.11
console.log(NP.plus(2.3, 2.6)); // 加:=4.9
console.log(NP.minus(1.0, 0.9)); // 減:=0.1
console.log(NP.times(3, 0.3)); // 乘:=0.9
console.log(NP.divide(0.9, 0.3)); // 除:=3
console.log(NP.plus(0.1, 0.2))
安裝:
npm install --save decimal.js
引入:
import Decimal from "decimal.js"
使用:
console.log(Decimal(0.1).add(Decimal(0.2))); // 加: {s: 1, e: -1, d: Array(1), constructor: ?}
console.log(Decimal(0.1).sub(Decimal(0.2))); // 減:{s: -1, e: -1, d: Array(1), constructor: ?}
console.log(Decimal(0.1).mul(Decimal(0.2))); // 乘:{s: 1, e: -2, d: Array(1), constructor: ?}
console.log(Decimal(0.1).div(Decimal(0.2))); // 除:{s: 1, e: -1, d: Array(1), constructor: ?}
上面的結(jié)果是Decimal 對象,取值需要Number 或 String轉(zhuǎn)換
官網(wǎng):http://mikemcl.github.io/decimal.js/
安裝:
npm install json-bigint
引入:
import JSONBigInt from 'json-bigint';
const JSONBigIntNative=JSONBigInt();
使用:
let json="{\"order\":258431607934229718,\"price\":1.258431607934229718,\"no\":123456}"
const obj1=JSON.parse(json)
const obj2=JSONBigIntNative.parse(json)
console.log(obj1) //{order: 258431607934229730, price: 1.2584316079342297, no: 123456}
console.log(obj2.order.toString()) //258431607934229718
console.log(obj2.price.toString()) //1.258431607934229718
console.log(obj2.order.toNumber()) //258431607934229730
console.log(obj2.price.toNumber()) //1.2584316079342297
主要是把大數(shù)據(jù)轉(zhuǎn)成字符串。其實(shí)關(guān)于這一點(diǎn),如果后端經(jīng)驗(yàn)豐富的話,自然會給前端返回字符串,也無需前端轉(zhuǎn)換。不過呢,可能前端的技能的提升也就是從無經(jīng)驗(yàn)的后端開始的噢!
oundation 可以很簡單的創(chuàng)建一個提醒框:
提醒框可以使用 .alert-box
類創(chuàng)建, 可以添加可選的類: .secondary
, .success
, .info
, .warning
或 .alert
:
實(shí)例
<div data-alert class="alert-box">
This is a default alert box.
</div>
<div data-alert class="alert-box secondary">
This is a secondary alert box.
</div>
<div data-alert class="alert-box success">
<strong>Success!</strong> This alert box indicates a successful or positive action.
</div>
<div data-alert class="alert-box info">
<strong>Info!</strong> This alert box indicates a neutral informative change or action.
</div>
<div data-alert class="alert-box warning">
<strong>Warning!</strong> This alert box indicates a warning that might need attention.
</div>
<div data-alert class="alert-box alert">
<strong>Alert!</strong> This alert box indicates a dangerous or potentially negative action.
</div>
圓角提醒框
.radius
和 .round
類用于為提醒框添加圓角:
實(shí)例
<div data-alert class="alert-box success radius">
<strong>Success!</strong> Alert box with a radius.
</div>
<div data-alert class="alert-box info round">
<strong>Info!</strong> Alert box that is rounded.
</div>
關(guān)閉提醒框
要關(guān)閉提醒框,可以在連接或按鈕元素上添加 class="close"
類,并初始化 Foundation JS:
實(shí)例
<div data-alert class="alert-box">
This is a default alert box with closing functionality.
<a href="#" class="close">×</a>
</div>
<script>
// Initialize Foundation JS For Functionality
$(document).ready(function() {
$(document).foundation();
})
</script>
提醒框的寬度為容器的 100%。
× (×) 是一個 HTML 字符實(shí)體表示一個關(guān)閉按鈕的圖標(biāo),而不是字母 "x"。
/面包理想
一轉(zhuǎn)眼已經(jīng)2018年,前端行業(yè)也風(fēng)風(fēng)雨雨地走過了10多年,網(wǎng)頁布局也從最原始的文檔變成了精彩紛呈的交互。當(dāng)我看到第四代CSS布局技術(shù)的時候,在驚嘆互聯(lián)網(wǎng)發(fā)展如此突飛猛進(jìn)的同時,不禁會有一個疑問:CSS經(jīng)歷1.0到3.0的版本變遷,最終又將走向哪里?
今天我們就回顧一下CSS簡史和四次布局技術(shù)的躍遷。
1.CSS簡史
為什么我們需要回顧一下CSS簡史呢?
1.了解過去能夠更好地預(yù)測未來,畢竟太陽底下沒有什么新鮮事。
2.相比預(yù)測未來,通過了解CSS發(fā)展演變趨勢,能夠科學(xué)合理地評判CSS的發(fā)展,指導(dǎo)我們學(xué)習(xí)CSS的核心技術(shù),讓我們在有限的精力和時間內(nèi)學(xué)對知識,學(xué)好知識。
那是1989年的第一場雪,比1988年來的更早一些,伯納斯·李(Tim Berners-Lee)以超人的智慧和消耗了前額無數(shù)濃密的頭發(fā)為代價發(fā)明了World Wide Web,沒有他就沒有我們今天互聯(lián)網(wǎng)相關(guān)的工作,也就沒有了這個專欄教程,請?jiān)试S我代表廣大前端致以崇高的敬意。我們先一睹大神的風(fēng)采。
對互聯(lián)網(wǎng)之父,我只想對他說一句話,有一款洗發(fā)水增發(fā)效果挺好的,我一直用,你要不要試試?
互聯(lián)網(wǎng)誕生了以后,最初的網(wǎng)頁僅僅是純文本,但是隨著互聯(lián)網(wǎng)的發(fā)展,大家意識到web的原始版本根本就沒有提供一種裝飾網(wǎng)頁的方法。這就好比一個嬰兒不會穿著衣服出生一樣,孩子大了,總不能裸奔吧?這個時候兩個大神提供了解決方案Pei Yaun Wei和Andreesen。
Pei Yaun Wei說,這個好辦,我們可以給孩子穿上紙尿褲。
Pei-Yuan Wei在1991年創(chuàng)建圖形瀏覽器 ViolaWWW ,他整合了自己提出的樣式語言到自己開發(fā)的瀏覽器中,還期望自己的樣式語法最終能成為web關(guān)于樣式的官方標(biāo)準(zhǔn)。雖然這個目標(biāo)并未達(dá)到,但是他提出的樣式語法確實(shí)為其它的一些樣式語法提供了一些靈感。
Andreesen說,那玩意得換多麻煩,我給孩子畫一身衣服吧,當(dāng)然你懂的,最后Pei Yaun Wei的方案被采用了,但是我們還是看看Andreessen畫出來的情況有多亂。
與此同時,Andreessen 在他開發(fā)的網(wǎng)景瀏覽器中進(jìn)行了不同的嘗試。他并沒有創(chuàng)建一種分離式的標(biāo)記語言,而是采取拓展HTML標(biāo)簽的方法來包含非標(biāo)準(zhǔn)化的HTML標(biāo)簽已達(dá)到裝飾網(wǎng)頁的目的。不幸的是,沒過多久,網(wǎng)頁就失去了所有的語義化并看起來像下面這樣混亂:
<MULTICOL COLS="3" GUTTER="25"> <P><FONT SIZE="4" COLOR="RED">This would be some font broken up into columns</FONT></P></MULTICOL>
最終被大家采納的語言是由Hakon Wium 在 1994年 10月提出的樣式語法。它被稱為樣式層疊表,簡稱CSS,但是直到1996年的時候,CSS才演變成我們熟悉的樣子。
html { margin-left: 2cm; font-family: "Times", serif; }h1 { font-size: 24px; }
然后在1998年5月W3C發(fā)表了CSS2,緊接著一個讓我們深惡痛覺的瀏覽器誕生了!對沒錯,就是你深惡痛絕的那個萬能的IE6,2001年微軟發(fā)布了IE6,不過搞笑的是,IE6最初的出現(xiàn)確實(shí)很大程度推動了CSS發(fā)展。那時候的網(wǎng)頁已經(jīng)變成跟現(xiàn)在很接近了。
按照常理你肯定會想,后面我就知道了,你不用說了,然后就是CSS3.0了。好吧,如果是我,我也這樣想,但是國際友人的腦回路可能跟我們不一樣,事實(shí)上,CSS3早于1999年已經(jīng)開始制訂,直到2011年6月7日,CSS 3 Color Module終于發(fā)布為W3C Recommendation。這個故事告訴我們兩件事:
1.w3c這個組織活的真夠長,甚至比很多讀者年齡都大。
2.不是CSS正式版發(fā)布了你才放心使用,如果等到那個時候使用,你的項(xiàng)目可能未曾綻放就枯萎了。
細(xì)心的讀者可能會問了,CSS3正式版什么時候發(fā)布啊?另外CSS4.0什么時候發(fā)布?
好吧,我只能告訴你隨緣吧……而且沒有CSS4.0了,也不會有CSS5.0了。
來我們再看看國際友人的腦回路:
簡單地說,就是從CSS3開始,CSS規(guī)范就被拆成眾多模塊(module)單獨(dú)進(jìn)行升級,或者將新需求作為一個新模塊來立項(xiàng)并進(jìn)行標(biāo)準(zhǔn)化。因此今后不會再有CSS4、CSS5這種所謂大版本號的變更,有的只是CSS某個模塊級別的躍遷。
按照CSS工作組的說法,CSS歷史上并沒有版本的概念,有的只是“級別”(level)的概念。比如,CSS3其實(shí)是CSS Level 3,CSS2是CSS Level 2,而CSS Level 1當(dāng)然就是CSS1。每個級別都以上一個級別為基礎(chǔ)。
大家可能說這個命名好亂啊,這事兒我只想跟你說,你就把CSS工作組當(dāng)成你女朋友就好了,她開心就好,她說的都是對的,她說啥就是啥……
至于我們,會用就好了。
CSS出現(xiàn)的好處就是讓結(jié)構(gòu)和表現(xiàn)分離,可以更靈活的修飾網(wǎng)頁,學(xué)習(xí)也很簡單。這里我更想說說它的不足。
1.CSS只有一個全局的命名空間,所以是無法避免出現(xiàn)選擇器沖突的。
2.模塊化做的不夠好,所以造成嵌套和覆蓋混亂,容易產(chǎn)生一大堆亂糟糟的樣式。
所以現(xiàn)在CSS也在向“模塊化、JS化發(fā)展”
不過客觀地說,CSS的出現(xiàn)確實(shí)是互聯(lián)網(wǎng)里程碑式的進(jìn)步。
CSS其實(shí)就做了兩件事:
1.如何布局
2.元素怎么表現(xiàn)
說直白一點(diǎn)就是兩件事,一個房子是蓋成兩室一廳還是三室兩廳,另一件事是精裝修。
這里大家就會看到如果一個房子180平米隔成1個10平米的主臥170平米的廁所,你再怎么精裝修也不會是一個宜居的房間。所以布局在CSS中是極其重要的。與CSS發(fā)展簡史類似,CSS布局也經(jīng)歷了一代又一代的迭代,才成為當(dāng)前的樣子。
接下來我們就說說CSS布局簡史。
2.CSS布局簡史
初代table布局
在1997年的時候,David Siegel 改變了web,他自己研究出了一項(xiàng)網(wǎng)頁布局技術(shù),利用html中的table元素和gif圖片縫合在一起,創(chuàng)造了表格布局技術(shù),之后他就猶如一頭猛獸泛濫起來。
優(yōu)點(diǎn):布局容易、快捷、兼容性好
缺點(diǎn):改動不便,需要重新調(diào)整,工作量大
由于互聯(lián)網(wǎng)網(wǎng)站越來越復(fù)雜,內(nèi)容和業(yè)務(wù)更新頻繁,所以table布局是完全不能勝任的,以至于table布局的發(fā)明人都說:
“我把炸醬和面倒在了一起,并且沒法分開它。”
不過這個真不是我杜撰出來的,原文:
David Siegel:“有人說我毀掉了Web,我回答他們,的確如此。我毀掉了Web是因?yàn)槲野亚煽肆突ㄉu混合在一起卻再也不能把它們分開。我犯下了把結(jié)構(gòu)跟表現(xiàn)混合在一起的錯誤。”
然后第二代布局技術(shù)登場了,
CSS+div布局
CSS+div布局總結(jié)起來有三大優(yōu)點(diǎn),
1.省時,學(xué)習(xí)容易,寫代碼也很容易,很快,效率高
2.省事,如果業(yè)務(wù)邏輯變了,改起來特別方便快捷
3.省錢,代碼量少,省帶寬,適合seo
基于這三年不難看出CSS+div布局人畜無害,人見人愛,也就不難解釋為什么被廣泛地使用成為目前主流的布局技術(shù)了。當(dāng)然了他也有缺點(diǎn):
1.需要考慮平臺兼容性,對制作人員的技能要求較高。
2.在移動端布局顯得有些力不從心,如未知寬高float內(nèi)部元素居中、垂直水平布局、響應(yīng)式布局等方面略顯繁瑣。
基于此,第三代布局技術(shù)應(yīng)運(yùn)而生。
Flex布局
優(yōu)點(diǎn):
1.CSS3的布局方式,可以在不使用其他框架的情況下,簡便、完整、響應(yīng)式地實(shí)現(xiàn)各種頁面布局 2.移動端布局簡直太友好
缺點(diǎn):
兼容性較差,IE瀏覽器版本在9.0以上,基本要10.0 對于其他瀏覽器,要求兼容性寫法
Flex布局日漸成為移動端主流布局技術(shù),但是它是單一維度的布局,這個我會在專欄后面講到,有時候也會捉襟見肘,所以目前出現(xiàn)了第四代的布局技術(shù):
grid布局
因?yàn)槟壳按蟛糠譃g覽器并不支持這種技術(shù),但是它代表了網(wǎng)絡(luò)發(fā)展,這里大家保持關(guān)注就好,這里我重點(diǎn)說下它為什么可以稱為第四代網(wǎng)絡(luò)布局技術(shù)。首先一個觀點(diǎn)大家先記住:
它并不會取代第三代的布局技術(shù),而是顛覆和突破。就好像Flex遠(yuǎn)比div+CSS布局更方便,但是div+CSS依然有用武之地。
我們說下它的突破之處:
1.flex對標(biāo)的是float,本質(zhì)上還是一維布局,這就跟別人開著夏利,你開奔馳都是地面上跑沒啥本質(zhì)區(qū)別一樣。但是grid升維了,grid是飛機(jī),在地面馬路這條線一維之上讓人能夠思考高度這個維度,以前是汽車一維交通工具(你只能在水平方向一個方向開),飛機(jī)是二維(能俯沖了(橫向、縱向同時)),所以grid可以說是拓寬了CSS布局的維度。不排除將來會有三維布局的出現(xiàn)。到時候CSS不僅僅能控制橫向布局,縱向布局,還可以深度布局(這個要依賴于三維展示的出現(xiàn),如VR,AR三維立體的展示設(shè)備出現(xiàn))。
2.grid布局里面采用了“可視化布局(template部分,所見即所得)”,這個是顛覆了傳統(tǒng)的,寫一句代碼刷一下瀏覽器這樣的開發(fā)方式,不排除以后會出現(xiàn)代碼即效果的開發(fā)模式。比如你在一個設(shè)備上畫一個區(qū)域,然后畫輪播圖。
這種方式類似于vc++控件方式,但是更智能,也更友好。誰說不可能呢?大家不要忘了grid布局的來源是早就廢棄的table布局。說到這里我多說一句搞笑的微軟,frontpage沒火,dreamwaver火了,最早提出“canvas”概念的 VML沒火,最后html5的canvas火了,連CSS3網(wǎng)格布局也是由微軟創(chuàng)建的一個模塊 ,最后火起來居然沒人認(rèn)識它。心疼微軟一秒鐘。
說到這里大家對CSS簡史和布局也有所了解了,我們總結(jié)下,通過本文你應(yīng)該學(xué)到:
(1)CSS的發(fā)展歷史。
(2)熟知布局的發(fā)展歷史,以便對未來布局技術(shù)的發(fā)展有一個客觀的判斷,來選擇是否學(xué)習(xí)。
通過本文的學(xué)習(xí)大家已經(jīng)對CSS相關(guān)基礎(chǔ)知識有所了解,接下來我們就開始真正的進(jìn)入技術(shù)的學(xué)習(xí),大家是不是迫不及待了呢?
*請認(rèn)真填寫需求信息,我們會在24小時內(nèi)與您取得聯(lián)系。