CSS in JS是一種解決css問題想法的集合,而不是一個指定的庫。從CSS in JS的字面意思可以看出,它是將css樣式寫在JavaScript文件中,而不需要獨立出.css、.less之類的文件。將css放在js中使我們更方便的使用js的變量、模塊化、tree-shaking。還解決了css中的一些問題,譬如:更方便解決基于狀態的樣式,更容易追溯依賴關系,生成唯一的選擇器來鎖定作用域。盡管CSS in JS不是一個很新的技術,但國內的普及程度并不高。由于Vue和Angular都有屬于他們自己的一套定義樣式的方案,React本身也沒有管用戶怎樣定義組件的樣式[1],所以CSS in JS在React社區的熱度比較高。
目前為止實現CSS in JS的第三方庫有很多:(http://michelebertoli.github.io/css-in-js/)。像JSS[2]、styled-components[3]等。在這里我們就不展開贅述了(相關鏈接已放在下方),這篇文章的重點是JS in CSS。
在上面我們提到CSS in JS就是把CSS寫在JavaScript中,那么JS in CSS我們可以推斷出就是可以在CSS中使用JavaScript腳本,如下所示。可以在CSS中編寫Paint API的功能。還可以訪問:ctx,geom。甚至我們還可以編寫自己的css自定義屬性等。這些功能的實現都基于CSS Houdini[4]。
.el {
--color: cyan;
--multiplier: 0.24;
--pad: 30;
--slant: 20;
--background-canvas: (ctx, geom) => {
let multiplier = var(--multiplier);
let c = `var(--color)`;
let pad = var(--pad);
let slant = var(--slant);
ctx.moveTo(0, 0);
ctx.lineTo(pad + (geom.width - slant - pad) * multiplier, 0);
ctx.lineTo(pad + (geom.width - slant - pad) * multiplier + slant, geom.height);
ctx.lineTo(0, geom.height);
ctx.fillStyle = c;
ctx.fill();
};
background: paint(background-canvas);
transition: --multiplier .4s;
}
.el:hover {
--multiplier: 1;
}
在如今的Web開發中,JavaScript幾乎占據了項目代碼的大部分。我們可以在項目開發中使用ES 2020、ES2021、甚至提案中的新特性(如:Decorator[5]),即使瀏覽器尚未支持,也可以編寫Polyfill或使用Babel之類的工具進行轉譯,讓我們可以將最新的特性應用到生產環境中(如下圖所示)。
JavaScript標準制定流程.png
而CSS就不同了,除了制定CSS標準規范所需的時間外,各家瀏覽器的版本、實戰進度差異更是曠日持久(如下圖所示),最多利用PostCSS、Sass等工具來幫我們轉譯出瀏覽器能接受的CSS。開發者們能操作的就是通過JS去控制DOM與CSSOM來影響頁面的變化,但是對于接下來的Layout、Paint與Composite就幾乎沒有控制權了。為了解決上述問題,為了讓CSS的魔力不在受到瀏覽器的限制,Houdini就此誕生。
CSS 標準制定流程.png
我們上文中提到JavaScript中進入提案中的特性我們可以編寫Polyfill,只需要很短的時間就可以講新特性投入到生產環境中。這時,腦海中閃現出的第一個想法就是CSS Polyfill,只要CSS的Polyfill 足夠強大,CSS或許也能有JavaScript一樣的發展速度,令人可悲的是編寫CSS Polyfill異常的困難,并且大多數情況下無法在不破壞性能的情況下進行。這是因為JavaScript是一門動態腳本語言[6]。它帶來了極強的擴展性,正是因為這樣,我們可以很輕松使用JavaScript做出JavaScript的Polyfill。但是CSS不是動態的,在某些場景下,我們可以在編譯時將一種形式的CSS的轉換成另一種(如PostCSS[7])。如果你的Polyfill依賴于DOM結構或者某一個元素的布局、定位等,那么我們的Polyfill就無法編譯時執行,而需要在瀏覽器中運行了。不幸的是,在瀏覽器中實現這種方案非常不容易。
頁面渲染流程.png
如上圖所示,是從瀏覽器獲取到HTML到渲染在屏幕上的全過程,我們可以看到只有帶顏色(粉色、藍色)的部分是JavaScript可以控制的環節。首先我們根本無法控制瀏覽器解析HTML與CSS并將其轉化為DOM與CSSOM的過程,以及Cascade,Layout,Paint,Composite我們也無能為力。整個過程中我們唯一完全可控制的就是DOM,另外CSSOM部分可控。
CSS Houdini草案中提到,這種程度的暴露是不確定的、兼容性不穩定的以及缺乏對關鍵特性的支持的。比如,在瀏覽器中的 CSSOM 是不會告訴我們它是如何處理跨域的樣式表,而且對于瀏覽器無法解析的 CSS 語句它的處理方式就是不解析了,也就是說——如果我們要用 CSS polyfill讓瀏覽器去支持它尚且不支持的屬性,那就不能在 CSSOM 這個環節做,我們只能遍歷一遍DOM,找到 <style> 或 <link rel="stylesheet"> 標簽,獲取其中的 CSS 樣式、解析、重寫,最后再加回 DOM 樹中。令人尷尬的是,這樣DOM樹全部刷新了,會導致頁面的重新渲染(如下如所示)。
即便如此,有的人可能會說:“除了這種方法,我們也別無選擇,更何況對網站的性能也不會造成很大的影響”。那么對于部分網站是這樣的。但如果我們的Polyfill是需要對可交互的頁面呢?例如scroll,resize,mousemove,keyup等等,這些事件隨時會被觸發,那么意味著隨時都會導致頁面的重新渲染,交互不會像原本那樣絲滑,甚至導致頁面崩潰,對用戶的體驗也極其不好。
綜上所述,如果我們想讓瀏覽器解析它不認識的樣式(低版本瀏覽器使用grid布局),然而渲染流程我們無法介入,我們也只能通過手動更新DOM的方式,這樣會帶來很多問題,Houdini的出現正是致力于解決他們。
Houdini是一組底層API,它公開了CSS引擎的各個部分,如下圖所示展示了每個環節對應的新API(灰色部分各大瀏覽器還未實現),從而使開發人員能夠通過加入瀏覽器渲染引擎的樣式和布局過程來擴展CSS。Houdini是一群來自Mozilla,Apple,Opera,Microsoft,HP,Intel和Google的工程師組成的工作小組設計而成的。它們使開發者可以直接訪問CSS對象模型(CSSOM),使開發人員可以編寫瀏覽器可以解析為CSS的代碼,從而創建新的CSS功能,而無需等待它們在瀏覽器中本地實現。
CSS Houdini-API
盡管當前已經有了CSS變量,可以讓開發者控制屬性值,但是無法約束類型或者更嚴格的定義,CSS Houdini新的API,我們可以擴展css的變量,我們可以定義CSS變量的類型,初始值,繼承。它是css變量更強大靈活。
CSS變量現狀:
.dom {
--my-color: green;
--my-color: url('not-a-color'); // 它并不知道當前的變量類型
color: var(--my-color);
}
Houdini提供了兩種自定義屬性的注冊方式,分別是在js和css中。
CSS.registerProperty({
name: '--my-prop', // String 自定義屬性名
syntax: '<color>', // String 如何去解析當前的屬性,即屬性類型,默認 *
inherits: false, // Boolean 如果是true,子節點將會繼承
initialValue: '#c0ffee', // String 屬性點初始值
});
我們還可以在css中注冊,也可以達到上面的效果
@property --my-prop {
syntax: '<color>';
inherits: false;
initial-value: #c0ffee;
}
這個API中最令人振奮人心的功能是自定義屬性上添加動畫,像這樣:transition: --multiplier 0.4s;,這個功能我們在前面介紹什么是js in css那個demo[8]用使用過。我們還可以使用+使syntax屬性支持一個或多個類型,也可以使用|來分割。更多syntax屬性值:
屬性值描述<length>長度值<number>數字<percentage>百分比<length-percentage>長度或百分比,calc將長度和百分比組成的表達式<color>顏色<image>圖像<url>網址<integer>整數<angle>角度<time>時間<resolution>分辨率<transform-list>轉換函數<custom-ident>ident
Worklets是渲染引擎的擴展,從概念上來講它類似于Web Workers[9],但有幾個重要的區別:
Worklet是一個JavaScript模塊,通過調用worklet的addModule方法(它是個Promise)來添加。比如registerLayout,registerPaint, registerAnimator 我們都需要放在Worklet中
//加載單個
await demoWorklet.addModule('path/to/script.js');
// 一次性加載多個worklet
Promise.all([
demoWorklet1.addModule('script1.js'),
demoWorklet2.addModule('script2.js'),
]).then(results => {});
registerDemoWorklet('name', class {
// 每個Worklet可以定義要使用的不同函數
// 他們將由渲染引擎在需要時調用
process(arg) {
return !arg;
}
});
Worklets的生命周期
Worklets lifecycle
Typed OM是對現有的CSSOM的擴展,并實現 Parsing API 和 Properties & Values API相關的特性。它將css值轉化為有意義類型的JavaScript的對象,而不是像現在的字符串。如果我們嘗試將字符串類型的值轉化為有意義的類型并返回可能會有很大的性能開銷,因此這個API可以讓我們更高效的使用CSS的值。
現在讀取CSS值增加了新的基類CSSStyleValue,他有許多的子類可以更加精準的描述css值的類型:
子類描述CSSKeywordValueCSS關鍵字和其他標識符(如inherit或grid)CSSPositionValue位置信息 (x,y)CSSImageValue表示圖像的值屬性的對象CSSUnitValue表示為具有單個單位的單個值(例如50px),也可以表示為沒有單位的單個值或百分比CSSMathValue比較復雜的數值,比如有calc,min和max。這包括子類 CSSMathSum, CSSMathProduct, CSSMathMin,CSSMathMax, CSSMathNegate 和 CSSMathInvertCSSTransformValue由CSS transforms組成的CSSTransformComponent列表,其中包括CSSTranslate, CSSRotate, CSSScale, CSSSkew, CSSSkewX, CSSSkewY, CSSPerspective 和 CSSMatrixComponent
使用Typed OM主要有兩種方法:
使用attributeStyleMap設置并獲取
myElement.attributeStyleMap.set('font-size', CSS.em(2));
myElement.attributeStyleMap.get('font-size'); // CSSUnitValue { value: 2, unit: 'em' }
myElement.attributeStyleMap.set('opacity', CSS.number(.5));
myElement.attributeStyleMap.get('opacity'); // CSSUnitValue { value: 0.5, unit: 'number' };
在線demo[10]
使用computedStyleMap
.foo {
transform: translateX(1em) rotate(50deg) skewX(10deg);
vertical-align: baseline;
width: calc(100% - 3em);
}
const cs = document.querySelector('.foo').computedStyleMap();
cs.get('vertical-align');
// CSSKeywordValue {
// value: 'baseline',
// }
cs.get('width');
// CSSMathSum {
// operator: 'sum',
// length: 2,
// values: CSSNumericArray {
// 0: CSSUnitValue { value: -90, unit: 'px' },
// 1: CSSUnitValue { value: 100, unit: 'percent' },
// },
// }
cs.get('transform');
// CSSTransformValue {
// is2d: true,
// length: 3,
// 0: CSSTranslate {
// is2d: true,
// x: CSSUnitValue { value: 20, unit: 'px' },
// y: CSSUnitValue { value: 0, unit: 'px' },
// z: CSSUnitValue { value: 0, unit: 'px' },
// },
// 1: CSSRotate {...},
// 2: CSSSkewX {...},
// }
開發者可以通過這個API實現自己的布局算法,我們可以像原生css一樣使用我們自定義的布局(像display:flex, display:table)。在Masonry layout library[11] 上我們可以看到開發者們是有多想實現各種各樣的復雜布局,其中一些布局光靠 CSS 是不行的。雖然這些布局會讓人耳目一新印象深刻,但是它們的頁面性能往往都很差,在一些低端設備上性能問題猶為明顯。
CSS Layout API 暴露了一個registerLayout方法給開發者,接收一個布局名(layout name)作為后面在 CSS中使用的屬性值,還有一個包含有這個布局邏輯的JavaScript類。
my-div {
display: layout(my-layout);
}
// layout-worklet.js
registerLayout('my-layout', class {
static get inputProperties() { return ['--foo']; }
static get childrenInputProperties() { return ['--bar']; }
async intrinsicSizes(children, edges, styleMap) {}
async layout(children, edges, constraints, styleMap) {}
});
await CSS.layoutWorklet.addModule('layout-worklet.js');
目前瀏覽器大部分還不支持
我們可以在CSS background-image中使用它,我們可以使用Canvas 2d上下文,根據元素的大小控制圖像,還可以使用自定義屬性。
await CSS.paintWorklet.addModule('paint-worklet.js');
registerPaint('sample-paint', class {
static get inputProperties() { return ['--foo']; }
static get inputArguments() { return ['<color>']; }
static get contextOptions() { return {alpha: true}; }
paint(ctx, size, props, args) { }
});
這個API讓我們可以控制基于用戶輸入的關鍵幀動畫,并且以非阻塞的方式。還能更改一個 DOM 元素的屬性,不過是不會引起渲染引擎重新計算布局或者樣式的屬性,比如 transform、opacity 或者滾動條位置(scroll offset)。Animation API的使用方式與 Paint API 和Layout API略有不同我們還需要通過new一個WorkletAnimation來注冊worklet。
// animation-worklet.js
registerAnimator('sample-animator', class {
constructor(options) {
}
animate(currentTime, effect) {
effect.localTime = currentTime;
}
});
await CSS.animationWorklet.addModule('animation-worklet.js');
// 需要添加動畫的元素
const elem = document.querySelector('#my-elem');
const scrollSource = document.scrollingElement;
const timeRange = 1000;
const scrollTimeline = new ScrollTimeline({
scrollSource,
timeRange,
});
const effectKeyframes = new KeyframeEffect(
elem,
// 動畫需要綁定的關鍵幀
[
{transform: 'scale(1)'},
{transform: 'scale(.25)'},
{transform: 'scale(1)'}
],
{
duration: timeRange,
},
);
new WorkletAnimation(
'sample-animator',
effectKeyframes,
scrollTimeline,
{},
).play();
關于此API的更多內容:(https://github.com/w3c/css-houdini-drafts/tree/main/css-animation-worklet-1)
允許開發者自由擴展 CSS 詞法分析器。
解析規則:
const background = window.cssParse.rule("background: green");
console.log(background.styleMap.get("background").value) // "green"
const styles = window.cssParse.ruleSet(".foo { background: green; margin: 5px; }");
console.log(styles.length) // 5
console.log(styles[0].styleMap.get("margin-top").value) // 5
console.log(styles[0].styleMap.get("margin-top").type) // "px"
解析CSS:
const style = fetch("style.css")
.then(response => CSS.parseStylesheet(response.body));
style.then(console.log);
它將提供一些方法來測量在屏幕上呈現的文本元素的尺寸,將允許開發者控制文本元素在屏幕上呈現的方式。使用當前功能很難或無法測量這些值,因此該API將使開發者可以更輕松地創建與文本和字體相關的CSS特性。例如:
Is Houdini ready yet
(https://ishoudinireadyyet.com/)
了解到這里,部分開發者可能會說:“我不需要這些花里胡哨的技術,并不能帶收益。我只想簡簡單單的寫幾個頁面,做做普通的Web App,并不想試圖干預瀏覽器的渲染過程從而實現一些實驗性或炫酷的功能?!比绻@樣想的話,我們不妨退一步再去思考。回憶下最近做過的項目,用于實現頁面效果所使用到的技術,grid布局方式在考慮兼容老版本瀏覽器時也不得不放棄。我們想控制瀏覽器渲染頁面的過程并不是僅僅為了炫技,更多的是為了幫助開發者們解決以下兩個問題:
幾年過后再回眸,當主流瀏覽器完全支持Houdini的時候。我們可以在瀏覽器上隨心所欲的使用任何CSS屬性,并且他們都能完美支持。像今天的grid布局在舊版本瀏覽器支持的并不友好的這類問題,那時我們只需要安裝對應的Polyfill就能解決類似的問題。
者:HXGNMSL來源:CSDN原文:https://blog.csdn.net/HXGNMSL/article/details/89076476
Javascript的歷史來源
94年網景公司 研發出世界上第一款瀏覽器。
95年 sun公司 java語言誕生
網景公司和sun合作。
Javascript ===> javascript
JavaScript和ECMAScript的關系
簡單來說ECMAScript不是一門語言,而是一個標準。符合這個標準的比較常見的有:JavaScript、Action Script(Flash中用的語言)
JavaScript的基本結構:
JavaScript的語法:
JavaScript的基礎語法
變量的聲明及使用
數據類型
運算符
邏輯控制語句
注釋
語法規則
變量的聲明語法:
var變量名;
例如:
Var num;
然后進行賦值:num = 10;也可以聲明時直接賦值:
Var num =10;
在JavaScript中,提供了常用的基本數據類型:
undefined 未定義;
null 空;
string 字符串類型;
boolean 布爾類型;
number 數值類型;
運算符:
算數運算符:+、-、*、/、%、++、–;
比較運算符:>、<、> =、< =、==、!=;
邏輯運算符:&&、||、??;
賦值運算符:=;
邏輯控制語句:
JavaScript的邏輯控制語句也分為兩類:條件結構和循環機構。
條件結構
條件機構分為if結構和switch結構:
If…else
Switch
循環結構
JavaScript的循環結構的執行順序與Java類似,主要包括以下幾種結構:
for循環
while循環
do…while循環
for…inx循環
示例:
for(var i=0;i<10;i++){
Document.write(“*”);
}
輸出結果:**********
循環中斷:
用于循環中斷的語句有以下兩種:
break.
continue.
與Java用法一樣,break是跳出循環,continue是跳入下一次循環。
函數
函數有兩種:一種是系統函數,一種是自定義函數。
常用的系統函數包括:
parseInt():轉換為整數。
parseFloat():轉換為浮點型。
isNaN():判斷非數字。
Eval():計算表達式值。
自定義函數:
自定義函數的語法
function 函數名(參數1,參數2,…){
…//語句
Return 返回值;//可選
}
函數的調用:
函數的調用方式有以下兩種
事件名=函數名(傳遞的實參值),例如:
“函數名()”
直接使用函數名(傳遞的實參值),例如:
var recult = add(2,3);
匿名函數
匿名函數的語法
var sumFun=function(num1,num2){
…
return(nun1,num2);
} ;
在語法中:
var sunFun=function(num1,num2)表示聲明一個變量等于某個函數體。
{…};是把整個函數體放在變量的后面,并把末尾添加一個分號。
匿名函數的調用:
由于匿名函數定義的整個語句,可以像賦值一樣賦給一個變量進行保存,所以可以使用如下方式調用語法中的匿名函數:
var sum=sumFun(2,3)
BOM概述
使用BOM可以移動窗口,改變狀態欄中的文本,執行其他與頁面內容不直接相關的動作。它包含的對象主要有以下幾種;
Window對象
Window對象是指整個窗口對象,可以通過操作Window對象的屬性和方法控制窗口,例如,打開或關閉一個窗口。
History對象
瀏覽器訪問過的歷史頁面對應History對象,通過History對象的屬性和方法實現瀏覽器的前進或后退的功能。
Location對象
瀏覽器的地址欄對應Location對象,通過Location對象的屬性和方法控制頁面跳轉。
Document對象
瀏覽器內的網頁內容對應Document對象,通過Document對象的屬性和方法,控制頁面元素。
Window常用的屬性有:
history:有關客戶訪問過的URL的信息。
location:有關當前URL的信息。
Screen: 有關客戶端的屏幕和顯示性能的信息。
Window對象常用的方法:
prompt():顯示可提示用戶輸入的對話框。
alert():顯示帶有一段消息和一個人“確認”按鈕的警告框。
confirm():顯示帶有一段消息以及“確認”按鈕“取消”按鈕的對話框。
close():關閉瀏覽器窗口。
open():打開一個新的瀏覽器窗口,加載給定URL所指定的文檔。
setTimeout():用于在指定(以毫秒計)后調用函數或計算表達式。
setTneerval():按照指定的周期 (以毫秒計)數來調用函數或計算表達式。
Window對象常用窗口特征屬性
height、width:窗口文檔顯示區的高度、寬度,以像素計。
left、top:窗口的x坐標y坐標,以像素計。
toolbar:yes|no|1|0:是否顯示瀏覽器的工具欄,默認是yes。
scrollbars =yes|no|1|0:是否顯示滾動條,默認是yes。
locationyes|no|1|0:是否顯示地址欄,默認是yes。
status|no|1|0:是否添加地址欄,默認是yes。
menubar|no|1|0:是否顯示菜單欄,默認是yes。
resizable|no|1|0:窗口是否可調節尺寸,默認是yes。
Window對象的常用事件:
onload:一個頁面或一副圖像完成加載。
onmouseover:鼠標指針移到某元素之上。
onclick:單擊某個對象。
onkeydown:某個鍵盤按鍵被按下。
onchange:域的內容被改變。
History對象的方法:
back():加載History對象列表中的上一個URL。
forward():加載History對象列表中的下一個URL。
go():加載History對象列表中的某個具體URL。
Location對象的屬性:
host:設置或返回主機名和當前URL的端口號。
hostname:設置或返回當前URL的主機名。
href:設置或返回完整的URL。
Location對象的方法:
reload():重新加載當前文檔。
replace():用新的文檔替換當前文檔。
Document對象常用的屬性:
referrer:返回載入當前文檔的URL。
URL:返回當前文檔的URL。
Document對象的常用方法:
getElementById():返回對擁有指定id的第一個對象的引用。
getElementsByName():返回帶有指定名稱的對象的集合。
getElementsByTagName():返回帶有指定標簽名的對象的集合。
write():向文檔寫文本、HTML表達式代碼。
內置對象
系統的內置對象有Date對象、Array對象、String對象和Math對象等。
Date:用于操作日期和時間。
Array:用于在單獨的變量名中儲存一系列的值。
String:用于支持對字符串的處理。
Math:用于執行數學任務,包含了若干數字常量和函數。
Date對象:
1:創建日期對象
Date對象包含日期和時間兩個信息,創建日期對象的基本語法有兩種:
創建日期的基本語法1: var 日期實例化=new Date(參數);
創建日期的基本語法2: var 日期實例化=new Date();
Date對象的常用方法:
getDate():從Date對象返回一個月中的某一天,其值介于1到31之間。
getDay():從Date對象返回星期中的某一天,其值介于0到6之間。
getHours():返回Date對象的小時,其值介于0到23之間。
getMinutes():返回Date對象的分鐘,其值介于0到59之間。
getSeconds():返回Date對象的秒數,其值介于0到59之間。
getMonth():返回Date對象的月份,其值介于0到11之間。
getFullYear():返回Date對象的年份,其值為4位數。
getTime():返回自某一時刻(2010年1月1日)以來的毫秒數。
DOM概述
什么是DOM
DOM是文檔對象的縮寫,和語言無關。它提供了訪問、動態修改結構文檔的接口,W3C制定了DOM規范,主流瀏覽器都支持。
使用Core DOM操作節點
訪問節點:
使用getElement系列方法訪問指定節點。
getElementById():返回對擁有指定id的第一個對象的引用。
getElementsByName():返回帶有指定名稱的對象的集合。
getElementsByTagName():返回帶有指定標簽名的對象的集合。
使用層次關系訪問節點。
parenNode:返回節點的父節點。
firstChild:返回節點的首個節點。文本和屬性節點沒有父節點,會返回一個空數組,對于元素節點,若是沒有子節點會返回null。
lastChild:返回節點的最后一個子節點,返回值同firstChild。
操作節點屬性值
CoreDOM的標準方法包括以下兩種:
getAttribute(“屬性名”):獲取屬性值。
getAttribute(“屬性名”,“屬性值”):設置屬性值
創建和增加節點:
創建節點
createElement(tagName):按照給定的標簽名稱創建一個新的元素節點
appendChild(nodeName):向以存在節點列表的末尾添加新的節點。
inserBefore(newNode,oldNode):向指定的節點之前插入一個新的子節點。
cloneNode(deep):復制某個指定的節點。
刪除和替換節點
removeChild(node):刪除指定的節點。
replaceChild(newNode,oldNode):用其他的節點替換指定的節點。
Table對象的屬性和方法
屬性:
rows[]:返回包含表格中所有行的一個數組。
rows[]用于返回表格中所有行的一個數組。
方法:
inserRow():在表格中插入一個新行。
deleteRow():從表格中刪除一行。
數組
數組是具有相同數據類型的一個或多個值得集合
創建數組的語法:
var 數組名稱=new Array(size);
數組的賦值的兩種方式:
先聲明在賦值
var province = new Array(4);
province[0]=“河北省”;
province[1]=“河南省”;
索引也可以使用標識(字符串),例如:
var province=new Array(4);
province[‘河北省’]=“河北省”;
province[‘河南省’]=“河南省”;
聲明時同時初始化
var province=new Array(“河北省”,“河南省”,“湖北省”,“廣東省”);
Array對象的常用屬性和方法:
屬性:
length:設置或返回數組中元素的數目。
方法:
join():把數組的所有元素放入一個字符串,通過一個分隔符進行分割。
sort():對數組的元素進行排序。
在本教程中,我們有一個使用 HTML、CSS 和 JS 制作的待辦事項列表應用程序,我們將把它與 Cerbos 集成以向應用程序添加授權。授權確定用戶是否可以執行特定操作或訪問某些資源或數據。它使組織能夠控制和保護對敏感數據庫、私人和個人數據以及公司資源的訪問。在我們的 JS 應用程序中,授權將定義用戶可以執行的操作(創建待辦事項并閱讀待辦事項)以及管理員可以執行的操作(創建、閱讀和刪除待辦事項)。
基于角色的訪問控制 (RBAC)是一種訪問控制方法,它根據最終用戶的組織角色為其分配權限。RBAC 提供細粒度的控制,提供了一種簡單、易于管理的訪問管理方法,與單獨分配權限相比,這種方法不容易出錯。
使用 RBAC 的優點是管理授權權限變得更加容易,因為系統管理員可以批量管理用戶和權限,而不是逐個管理。
我們已經定義了 RBAC 策略,并將集成 Cerbos 以根據用戶身份授權創建、讀取和刪除待辦事項。我們對誰可以做什么的業務要求如下:
Cerbos 是一個開源授權層,可讓您輕松實現應用程序的授權。在Cerbos,我們提供細粒度的訪問控制來增強安全性,同時使您的應用程序更快、更具可擴展性。使用 Cerbos 進行授權具有使用嚴格的 JS 代碼無法獲得的各種優勢
當組織采用 RBAC 訪問模型時,必須遵守有關安全和管理的最佳實踐,并致力于不斷改進其訪問協議以防范新出現的威脅。
以下列表包含一些您必須遵循的 RBAC 最佳實踐:
我們將在示例代碼中使用這些角色來演示訪問控制如何工作。
使用 Cerbos,訪問規則始終面向資源,您編寫的策略會映射到系統中的這些資源。資源可以是任何東西,而您建模策略的方式則由您決定 — 您可以通過多種方式實現相同的邏輯結果:以操作為主導、以角色為主導、以屬性為主導或以它們的組合為主導。
話雖如此,有些模式更適合特定場景——讓我們看看一些不同的方法。考慮這個權限模型:
Actions | Roles | ||||
CPO | CTO | Exec-1 | Exec-2 | Exec-3 | |
View | Allowed | Allowed | Allowed | Allowed | Allowed |
Add | Allowed | Allowed | Allowed | Allowed | Allowed |
Delete | Allowed | Allowed | Not Allowed | Not Allowed | Not Allowed |
我們將描述以行動為主導的政策,因為我們已經為我們的 JS 應用程序實施了以行動為主導的政策。
在這里,我們關注一個動作并列出可以執行該動作的所有角色。為了更好地理解這一點,我們文檔中列出了一個示例,如下所示:
# Principals in the following three roles can perform the `run` action
- actions:
- "run"
effect: EFFECT_ALLOW
roles:
- JR_MANAGER
- SR_MANAGER
- CFO
# All principals can perform the `view` action
- actions:
- "view"
effect: EFFECT_ALLOW
roles:
- ["*"]
如果您的系統符合以下任一情況,則此方法可能適用:
構建成功后,您應該會看到網頁在瀏覽器的localhost:5500上加載。
目前,沒有任何策略,此應用程序中的 CPO 和 CTO 被授予刪除待辦事項的權限,而高管(1、2 和 3)只能查看和添加待辦事項。但是,由于我們尚未將 Cerbos 與應用程序集成以進行權限管理,因此 CTO 和 CPO 無法刪除待辦事項。成功集成 Cerbos 后,CTO 和 CPO 將能夠刪除待辦事項。
要將 Cerbos 集成到我們的 JavaScript 應用程序中,我們首先要啟動 Cerbos Docker 容器。在根目錄 (/to-dolist-cerbos) 中使用以下命令運行 Docker 容器:
docker run --rm --name cerbos -d -v $(pwd)/cerbos/policies:/policies -p 3592:3592 -p 3593:3593 ghcr.io/cerbos/cerbos:0.34.0
Cerbos Playground是一款用于在線創建和測試策略的實用程序。Cerbos Playground 是了解策略創建甚至生成可用策略的絕佳方式:https://play.cerbos.dev/new ?generator 。
如何使用 RBAC 策略生成器為我們的 javascript 應用程序生成策略?
我們有兩個角色:用戶和管理員(其中 CTO/CPO 是管理員,而高管是用戶)。添加操作并根據我們要授予的權限選擇復選框。
根據偏好選擇后,我們可以點擊**生成**按鈕,生成一個名為to-dos.yaml的YAML策略文件。
使用生成器生成策略后,只需將其復制并添加到應用程序的文件結構中即可。策略生成器還會生成一個 to-dos_test.yaml 文件,該文件旨在幫助自動測試訪問控制策略。確保測試文件始終以 _test 后綴結尾。以下是它通常包含的內容和功能:
現在我們已經將 Cerbos 與 JS 應用程序集成,我們將運行它來檢查策略是否按預期工作。
讓我們使用測試文件和 Cerbos RBAC 策略生成器生成的 _testdata _ 來測試策略文件。
您可以使用此 Docker 命令(在 PowerShell 終端中)來運行測試:
docker run -i -t -v "$(Get-Location)/cerbos/policies:/policies" ghcr.io/cerbos/cerbos:latest compile /policies
運行此命令后,測試成功執行。
如果高管(具有角色:用戶)嘗試刪除待辦事項:
隨著政策的實施,高管不得刪除待辦事項;他們會收到一條警告:您無權刪除此待辦事項。該權限僅授予 CPO 和 CTO 角色。
根據政策,高管可以將待辦事項添加到列表中:
將任務添加到文本框并單擊添加待辦事項按鈕將其添加到待辦事項列表中。
CPO 已授權,待辦事項已成功刪除。
這個實際演示成功地描繪了 Cerbos 與我們的 JS 應用程序的集成。
Q1. 制定 RBAC 政策時我們必須考慮哪些最佳實踐?
A1:當組織采用 RBAC 訪問模型時,必須遵守有關安全和管理的最佳實踐,并致力于不斷改進其訪問協議,以防范新出現的威脅。
以下列表包含 RBAC 最佳實踐的公平樣本:
問題 2:在政策生效之前,可以使用 Cerbos 進行測試嗎?
A2:是的,可以在策略生效之前使用 Cerbos 對其進行測試。Cerbos 提供強大的策略測試功能,允許您在將訪問控制規則部署到生產環境之前對其進行驗證。使用 Cerbos Policy Generator 中提供的 Cerbos 測試框架,您可以確保策略強制執行所需的訪問控制規則并避免實際場景中的潛在問題。這種部署前測試有助于維護訪問控制策略的完整性和安全性,降低未經授權訪問的風險并確保遵守組織的安全準則。
您已通過以下關鍵步驟成功將 Cerbos 集成到演示待辦事項列表應用程序中:
*請認真填寫需求信息,我們會在24小時內與您取得聯系。