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
介紹新的 CSS 屬性 contain 之前,讀者首先需要了解什么是頁面的重繪與重排。
之前已經描述過很多次了,還不太了解的可以先看看這個提高 CSS 動畫性能的正確姿勢。
OK,下面進入本文正題,
contain 屬性允許我們指定特定的 DOM 元素和它的子元素,讓它們能夠獨立于整個 DOM 樹結構之外。目的是能夠讓瀏覽器有能力只對部分元素進行重繪、重排,而不必每次都針對整個頁面。
The contain property allows an author to indicate that an element and its contents are, as much as possible, independent of the rest of the document tree. This allows the browser to recalculate layout, style, paint, size, or any combination of them for a limited area of the DOM and not the entire page.
看看它的語法:
{
/* No layout containment. */
contain: none;
/* Turn on containment for layout, style, paint, and size. */
contain: strict;
/* Turn on containment for layout, style, and paint. */
contain: content;
/* Turn on size containment for an element. */
contain: size;
/* Turn on layout containment for an element. */
contain: layout;
/* Turn on style containment for an element. */
contain: style;
/* Turn on paint containment for an element. */
contain: paint;
}
復制代碼
除去 none,取值還有 6 個,我們一個一個來看看。
contain: size: 設定了 contain: size 的元素的渲染不會受到其子元素內容的影響。
The value turns on size containment for the element. This ensures that the containing box can be laid out without needing to examine its descendants.
我開始看到這個定義也是一頭霧水,光看定義很難明白到底是什么意思。還需實踐一番:
假設我們有如下簡單結構:
<div class="container">
</div>
復制代碼
.container {
width: 300px;
padding: 10px;
border: 1px solid red;
}
p {
border: 1px solid #333;
margin: 5px;
font-size: 14px;
}
復制代碼
并且,借助 jQuery 實現每次點擊容器添加一個 <p>Coco</p> 結構:
$('.container').on('click', e=> {
$('.container').append('<p>Coco</p>')
})
復制代碼
那么會得到如下結果:
可以看到,容器 .container 的高度是會隨著元素的增加而增加的,這是正常的現象。
此刻,我們給容器 .container 添加一個 contain: size,也就會出現上述說的:設定了 contain: size 的元素的渲染不會受到其子元素內容的影響。
.container {
width: 300px;
padding: 10px;
border: 1px solid red;
+ contain: size
}
復制代碼
再看看會發生什么:
正常而言,父元素的高度會因為子元素的增多而被撐高,而現在,子元素的變化不再影響父元素的樣式布局,這就是 contain: size 的作用。
接下來再說說 contain: style、contain: layout 、contain: paint。先看看 contain: style。
截止至本文書寫的過程中,contain: style 暫時被移除了。
CSS Containment Module Level 1: Drop the at-risk “style containment” feature from this specification, move it Level 2。
嗯,官方說辭是因為存在某些風險,暫時被移除,可能在規范的第二版會重新定義吧,那這個屬性也暫且放一放。
contain: paint:設定了 contain: paint 的元素即是設定了布局限制,也就是說告知 User Agent,此元素的子元素不會在此元素的邊界之外被展示,因此,如果元素不在屏幕上或以其他方式設定為不可見,則還可以保證其后代不可見不被渲染。
This value turns on paint containment for the element. This ensures that the descendants of the containing box don’t display outside its bounds, so if an element is off-screen or otherwise not visible, its descendants are also guaranteed to be not visible.
這個稍微好理解一點,先來看第一個特性:
這個特點有點類似與 overflow: hidden,也就是明確告知用戶代理,子元素的內容不會超出元素的邊界,所以超出部分無需渲染。
簡單示例,假設元素結構如下:
<div class="container">
<p>Coco</p>
</div>
復制代碼
.container {
contain: paint;
border: 1px solid red;
}
p{
left: -100px;
}
復制代碼
我們來看看,設定了 contain: paint 與沒設定時會發生什么:
CodePen Demo -- contain: paint Demo
通過使用 contain: paint, 如果元素處于屏幕外,那么用戶代理就會忽略渲染這些元素,從而能更快的渲染其它內容。
contain: layout:設定了 contain: layout 的元素即是設定了布局限制,也就是說告知 User Agent,此元素內部的樣式變化不會引起元素外部的樣式變化,反之亦然。
This value turns on layout containment for the element. This ensures that the containing box is totally opaque for layout purposes; nothing outside can affect its internal layout, and vice versa.
啟用 contain: layout 可以潛在地將每一幀需要渲染的元素數量減少到少數,而不是重新渲染整個文檔,從而為瀏覽器節省了大量不必要的工作,并顯著提高了性能。
使用 contain:layout,開發人員可以指定對該元素任何后代的任何更改都不會影響任何外部元素的布局,反之亦然。
因此,瀏覽器僅計算內部元素的位置(如果對其進行了修改),而其余DOM保持不變。因此,這意味著幀渲染管道中的布局過程將加快。
描述很美好,但是在實際 Demo 測試的過程中(截止至2021/04/27,Chrome 90.0.4430.85),僅僅單獨使用 contain:layout 并沒有驗證得到上述那么美好的結果。
設定了 contain: layout 的指定元素,該元素的任何后代的任何更改還是會影響任何外部元素的布局,點擊紅框會增加一條 <p>Coco<p> 元素插入到 container 中:
簡單的代碼如下:
<div class="container">
<p>Coco</p>
...
</div>
<div class="g-test"></div>
復制代碼
html,
body {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
gap: 10px;
}
.container {
width: 150px;
padding: 10px;
contain: layout;
border: 1px solid red;
}
.g-test {
width: 150px;
height: 150px;
border: 1px solid green;
}
復制代碼
CodePen Demo -- contain: layout Demo
截止至 2021-04-27,Can i Use 上的 CSS Contain 兼容性,已經可以開始使用起來:
鏈接:https://juejin.cn/post/6958990366888607757
來源:掘金
SS的布局有太多種方式,元素的表現也有很多的形式。
像我們熟悉的那些:行內元素、塊元素、列表元素、表格元素、絕對定位、固定定位、浮動、彈性布局、網格布局等等等等。
一個元素的具體渲染可能會受到父子元素、兄弟元素的影響。
大多數情況我們都可以通過一些手段,來解決我們遇到的布局或表現問題。
比如給一個元素賦予了浮動,那么可以通過清除浮動來消除影響,再比如通過絕對定位來調整元素的位置,也可以通過padding或margin等避免其他元素被覆蓋。
但是也有那么一些情況,我們不太好處理,比如某一個元素希望相對于它的父級區域做固定定位,而不是基于整個頁面,能做到嗎?再比如給定一個盒容器,無論子元素怎么排序布局或者浮動,也不會影響其他相鄰盒子的渲染,該怎么做到?
其實不止這些,還有很多的實際場景讓我們很棘手,你是否在設計和實現方面做過平衡和妥協?
對于現在的瀏覽器來說,所支持的CSS功能不允許我們說:我不行,我做不到。
別的不說,今天要講的contain就能用來解決上面的問題,它能做的事情還有很多,基于自身天然的屬性,甚至能輕松提升你的性能!
contain表明該元素要獨立于頁面中的其他元素,該元素中的所有內容都被局限在一個獨立的區域,跟其他元素隔離開來,從而使得基于該元素的所有計算都是獨立的,被限制在該DOM子樹中,而不是整個頁面。這樣能夠讓頁面的性能提升。
該元素構成的容器,可以控制其產生的尺寸范圍、樣式作用域、布局方式、繪制區域。會生成新的包含區塊、新的層疊上下文、新的區塊格式化上下文。這些控制手段都對應著不同的局限屬性,在容器內對局限屬性的修改,不會影響容器外的部分,也就不會使得頁面經常重新渲染,尤其在動態修改頁面元素時會帶來更好的性能受益。
我們理解它的時候,不要把它想成是包含的意思,理解成它的作用,是對包含內容的一個局限,之后也會多次用到"局限"這個詞。
一、關鍵詞
通過關鍵詞,可以指定不同的局限屬性,從而產生不同的局限效果。
二、組合值
也就是上面2-6關鍵字的任意組合,跟順序無關,多個值之間用空格分隔開。跟個數也無關,可以設置任意的數量。不過要注意,size和inline-size同時只能設置一個,因為它倆是沖突的。
三、全局值
全局值的作用,可以參考我在font-size那篇文章中的解釋說明,它們的作用機制和原理都是一樣的,這里不在重復贅述。
我們來對上面所說的內容,做一些示例,來看看它們的實際工作方式。
先構建一個基本的代碼,之后都以這個為基礎改造和演示:
<div style="background-color: bisque;">
我是父元素
<div style="background-color: coral;">
我是子元素
</div>
</div>
<div style="background-color: lightpink;">
我是父兄弟元素
</div>
看下現在的效果:
效果
記住這個效果,因為我們接下來就要改變contain屬性,觀察它所發生的變化。
<div style="contain: size;background-color: bisque;">
我是父元素
<div style="background-color: coral;">
我是子元素
</div>
</div>
<div style="background-color: lightpink;">
我是父兄弟元素
</div>
給父元素加上contain:size樣式:
效果
可以看到,"我是父元素"和"我是父兄弟元素"重合了,也就說,父兄弟元素的渲染,直接從父元素渲染開始的位置開始渲染的。就好像父元素不存在一樣。
這里面的奧妙通過控制臺看一下,其實就很容易解開了:
效果
就是因為父元素的高度為0了。在解釋之前先說明一下,行向指的是我們書寫的方向,就是指的從左往右,你就可以理解成是多個行內元素排列的方向,一直往后面追加的方向。塊向指的是我們折行的方向,也就是指的從上往下,你就可以理解成是多個塊級元素排列的方向,一直往下追加的方向。
理解了這兩個之后,我們就知道,由于size影響著這兩個方向上的局限,它會變得無視子元素。因為如果沒有主動設置尺寸的話,就好像子元素不存在一樣,那么它就沒有高度,所以兄弟元素就自然而然的頂上來了。
這時,我們改一下設置,讓它只在行向上有局限:
<div style="contain: inline-size;background-color: bisque;">
我是父元素
<div style="background-color: coral;">
我是子元素
</div>
</div>
<div style="background-color: lightpink;">
我是父兄弟元素
</div>
通過設置contain:inline-size:
效果
可以看到,效果又回來了,這是因為我們沒有在塊向上做局限,因此高度會自然撐開。
既然說到了這里,我們再看一下,它是如何在行向上進行局限的,構造如下代碼:
<div style="contain: inline-size;display: inline-block;background-color: bisque;">
我是父元素
<div style="background-color: coral;">
我是子元素
</div>
</div>
<div style="background-color: lightpink;">
我是父兄弟元素
</div>
設置父元素為行內塊,增加display:inline-block:
效果
瞬間又變成了這樣,這同樣是因為,行內局限使得父元素獨立計算尺寸,而我們又沒手動指定,因此它的寬度為0,子元素也跟著寬度為0,所以就變成了一個字一換行。
這時即使你給子元素加上寬度,在行向上父元素也會無視你:
效果
你看我們給子元素加上100px的寬度,但是鼠標查看父元素,依然是寬度為0。
指定contain:layout,可以讓該元素獨立計算它的內部布局,不受外界影響,我們先將子元素設定一個固定定位:
<div style="background-color: bisque;">
我是父元素
<div style="position: fixed;top: 10px;background-color: coral;">
我是子元素
</div>
</div>
<div style="background-color: lightpink;">
我是父兄弟元素
</div>
看下現在的效果:
效果
完全沒毛病,子元素固定到頁面頂部的10px位置。
現在應用一下我們的布局限制:
<div style="contain: layout;background-color: bisque;">
我是父元素
<div style="position: fixed;top: 10px;background-color: coral;">
我是子元素
</div>
</div>
<div style="background-color: lightpink;">
我是父兄弟元素
</div>
再看下顯示的效果:
效果
咦?明明是固定定位,它的位置卻是相對于父元素的。這就是布局限制的作用,相當于父元素告訴頁面,從現在開始,這片的布局歸我管,所有的行為都向我請示,由我指揮。
同樣,其他的position值,也都是基于父元素的布局限制來渲染的,這里就不做一一演示了。
其實,不光是position,只要是關于布局的,都會在此局限下生效,這里再演示一個浮動的例子:
<div style="height: 80px;padding: 5px;background-color: bisque;">
<h2 style="margin-bottom: 7px;">我是父元素</h2>
<p style="float: left;background-color: coral;">
我是子元素
</p>
</div>
<div style="height: 80px;padding: 5px;background-color: lightpink;">
<h2>我是父兄弟元素</h2>
<p style="background-color: coral;">
我是父兄弟子元素
</p>
</div>
兩個父元素各包含兩個子元素,其中第一個父元素的第二個子元素設置為左浮動,為了更好的演示,我把子元素改成了h2和p標簽,看下現在的效果:
效果
父元素的兩個子元素正常顯示,但是父兄弟元素的第一個子元素里面的文字,被擠的偏移了,這是由于父元素的第二個子元素設置浮動引起的,通過控制臺看下就明白了:
效果
紅線是我標出來的,可以看到,父兄弟元素的h2和父元素的浮動有一丁點的重合,導致文字被推開,這就是浮動產生的影響。
我們通過布局局限,來控制浮動只發生在局限內,稍微改下代碼:
<div style="contain: layout;height: 80px;padding: 5px;background-color: bisque;">
<h2 style="margin-bottom: 7px;">我是父元素</h2>
<p style="float: left;background-color: coral;">
我是子元素
</p>
</div>
<div style="height: 80px;padding: 5px;background-color: lightpink;">
<h2>我是父兄弟元素</h2>
<p style="background-color: coral;">
我是父兄弟子元素
</p>
</div>
給父元素添加了contain:layout,這是浮動就不會影響后面的布局了:
效果
通過布局局限,我們可以把所有的關于布局的影響,都控制在容器內,這樣即使容器內布局發生了改變,也完全不會影響頁面其他內容,在動態頁面中,如果需要頻繁的修改某些元素,通過這種方式管理和設計頁面,就能很有效的改善渲染的性能。
這里的樣式主要是針對計數器和引號的作用域,能控制它們只在所局限的范圍內單獨計算,而不會影響全局的結果,就好像它們是單獨拿出來作為一個獨立的文檔一樣,看個例子:
body {
counter-reset: my-list;
}
div > div::before {
counter-increment: my-list;
content: "(" counter(my-list) "):";
}
<div>
<div>第1行</div>
<div>第2行</div>
<div>第3行</div>
<div>第4行</div>
<div>第5行</div>
<div>第6行</div>
</div>
我們設計這樣一個列表,通過自定義的計數器,設置一個前綴的顯示:
效果
如果我們希望第三行獨立出來,進行樣式局限,不參與外部計數:
<div>
<div>第1行</div>
<div>第2行</div>
<div style="contain: style;">第3行</div>
<div>第4行</div>
<div>第5行</div>
<div>第6行</div>
</div>
那么它就會展現成這個樣子:
效果
注意第三行的計數,已經重置為1,并且第四行從3開始,接著第二行的值繼續計數。
這個也比較厲害,就是父元素啥樣就是啥樣,子元素永遠不會在容器外渲染:
<div style="background-color: bisque;width: 100px;height: 100px;">
<div>
海客談瀛洲,煙濤微茫信難求。
越人語天姥,云霞明滅或可睹。
天姥連天向天橫,勢拔五岳掩赤城。
</div>
</div>
有這樣一個代碼塊,容器的寬高為100px,內容有超出部分:
效果
我們可以通過繪制局限來使容器外的內容不顯示:
<div style="contain: style;background-color: bisque;width: 100px;height: 100px;">
<div>
海客談瀛洲,煙濤微茫信難求。
越人語天姥,云霞明滅或可睹。
天姥連天向天橫,勢拔五岳掩赤城。
</div>
</div>
添加contain:paint,只讓繪制區域被限制在容器內部:
效果
這個跟overflow:hidden有一點區別,就是繪制局限真的就是正常繪制,只不過不繪制容器外的部分,而hidden雖然隱藏,但是依然能通過js進行滾動。
我們也可以通過任意的值的組合來控制所需要的局限,也可以通過strict或content關鍵字來快速的做到這一點。這里就不再重復演示了
合理的使用contain,不但能快速實現我們的需求,也能減少我們的修改量,而且會降低不理解現象的情況的出現頻率,更能提升頁面的性能。
尤其是布局局限,提供給了我們更多的發揮空間,而且任意的復制到其他地方,也不會對外部元素有影響。
每天一點小知識,希望能夠幫助到你。
hat about covers the basics of the mail function; now let’s really get fancy and explore mail headers and what we can do with them!
上篇文章涵蓋了郵件功能的基本知識;現在,讓我們真正開始想象和探索郵件標題以及我們可以用它們做什么!
HTML Email and Other Headers
HTML電子郵件和其他頭信息
So now you can send email from your PHP scripts. How exciting! Although I’m sure you’re already drunk with power, would you like to know how to send HTML email too? Of course you would!
現在您可以從PHP腳本發送電子郵件了。多么令人興奮!雖然我肯定你已經被權力迷住了,但你想知道如何發送HTML電子郵件嗎?你當然會!
To understand HTML email, first you need to understand mail headers. Any given email message is made up of two parts: the headers and the message body. Here’s how a simple message looks when your email program fetches it from your ISP:
要理解HTML電子郵件,首先需要理解郵件頭信息。任何給定的電子郵件都由兩部分組成:頭信息和郵件正文。下面是當您的電子郵件程序從ISP獲取簡單郵件時的展現:
Return-Path: <sender@elsewhere.com>
Delivered-To: you@some.net
Received: ...several lines like this...
From: Sender <sender@elsewhere.com>
To: You <you@some.net>
Subject: A Simple Message
Date: Mon, 11 Feb 2002 16:08:19 -0500
Organization: Sender's Company
X-Mailer: Microsoft Outlook, Build 10.0.2616
Hi there! <tap> <tap> Is this thing on?
Everything up to the blank line makes up the headers for this message. In actual fact, most email messages will have many more header lines than this; however, to keep our focus I trimmed this example down to the bare essentials.
到空白行的所有內容構成了該消息的標頭。實際上,大多數電子郵件的頭信息都比這多很多;然而,為了保持我們的關注點,我把這個例子縮減到了最基本的部分。
As you can see, every line of the headers begins with the name of the header (From:, To:, Subject:, Date:, etc.), followed by some value. Most headers are standardized, and have a specific meaning, either to your mail program or to the mail servers that were responsible for getting the message to you. Non-standard headers exist as well, and they all begin with X- (e.g. X-Mailer:, a non-standard header, often appears to indicate the program that was used to send the message).
如您所見,標題的每一行都以標題的名稱(From:、To:、Subject:、Date:,等等)開頭,后跟一些值。大多數郵件頭都是標準化的,對您的郵件程序或負責向您發送郵件的郵件服務器都有特定的含義。非標準標頭也存在,它們都以X開頭(例如,X-Mailer:,一個非標準標頭,通常顯示為指示用于發送消息的程序)。
NOTE: If a header’s value needs more than one line, additional lines should begin with a space. We’ll see an example of this in the next section.
如果標頭的值需要多行,則其他行應以空格開頭。我們將在下一節中看到一個例子。
As soon as your mail program gets to a blank line, it knows the headers are over and the rest of the email is the message body, which it should display. In this case, the message body is the last line above.
一旦你的郵件程序到達一個空行,它就知道郵件頭已經結束,郵件的其余部分就是郵件正文,應該顯示出來。在本例中,消息正文是上面的最后一行。
PHP’s mail function lets you specify your own headers, which it adds to those it generates automatically to get your message where it needs to go. For example, the following call to the mail function will add an X-Mailer: header to the outgoing message, identifying PHP 4.x as the sending program:
PHP的郵件功能允許您指定自己的郵件頭,并將其添加到自動生成的郵件頭中,以便將郵件發送到需要的地方。例如,以下對mail函數的調用將向傳出消息添加一個X-Mailer:header,將PHP 4.X標識為發送程序:
<?php
mail('recipient@some.net', 'Subject', 'Your message here.',
'X-Mailer: PHP 4.x');
?>
This optional fourth parameter is most often used to specify a ‘from’ address other than the default specified in php.ini. Let’s add a From: header to do just that:
這個可選的第四個參數最常用于指定“from”地址,而不是php.ini中指定的默認地址。讓我們添加一個From:header來實現這一點:
<?php
mail('recipient@some.net', 'Subject', 'Your message here.',
"From: sender@some.netnX-Mailer: PHP 4.x");
?>
Note that since headers each appear on a single line, we must separate our two headers with a new line character (n), which means I need to use double quotes around the header string (single quoted strings don’t recognize special character codes like n).
請注意,由于每個標題都顯示在一行上,因此我們必須用新行字符(n)分隔兩個標題,這意味著我需要在標題字符串周圍使用雙引號(單引號字符串不能識別像n這樣的特殊字符代碼)。
Additional headers also let you assign names to email addresses by specifying them in the format name <email>. Here’s our example again, but this time with names “The Sender” and “The Receiver” attached to the relevant addresses:
其他標題還允許您通過在格式名稱<email>中指定電子郵件地址來為其分配名稱。下面是我們的示例,但這一次在相關地址上附加了名稱“發件人”和“收件人”:
<?php
mail('recipient@some.net', 'Subject', 'Your message here.',
"To: The Receiver <recipient@some.net>n" .
"From: The Sender <sender@some.net>n" .
"X-Mailer: PHP 4.x");
?>
Notice that to do this, we’ve had to specify the To: header manually, since the first parameter of PHP’s mail function doesn’t support this more advanced address format. We must still list all the recipients of the message as bare email addresses in the first parameter, however.
注意,要做到這一點,我們必須手動指定to:頭,因為PHP郵件函數的第一個參數不支持這種更高級的地址格式。但是,我們仍然必須在第一個參數中將郵件的所有收件人列為裸電子郵件地址。
The cc: and Bcc: headers provide the ability to send carbon copies and blind carbon copies of a message as well:
cc:和Bcc:標頭還提供發送郵件的復寫副本和盲復寫副本的功能:
<?php
mail('recipient@some.net, someone@some.net, metoo@some.net',
'Subject', 'Your message here.',
"To: The Receiver <recipient@some.net>n" .
"From: The Sender <sender@some.net>n" .
"cc: Interested <someone@some.net>n" .
"Bcc: Me Too <metoo@some.net>n" .
"X-Mailer: PHP 4.x");
?>
See how the email addresses of all recipients, be they actual addressees (To), carbon copies (Cc), or blind carbon copies (Bcc) are listed in the first parameter? This isn’t documented anywhere, but in my testing I’ve found that it’s absolutely vital if you want the message to get to everyone it’s supposed to, especially on Windows servers where PHP’s mail function is especially sensitive.
查看如何在第一個參數中列出所有收件人的電子郵件地址,無論是實際收件人(收件人)、復寫副本(抄送)還是盲復寫副本(密件抄送)?這在任何地方都沒有文檔記錄,但在我的測試中,我發現,如果希望消息傳遞給所有人,尤其是在PHP郵件功能特別敏感的Windows服務器上,這是絕對重要的。
What does all this have to do with HTML email, you ask? Well, a few special headers will cause the message body to be interpreted as HTML by email clients that support it:
你會問,這一切與HTML電子郵件有什么關系?好的,一些特殊的標題將導致支持郵件正文的電子郵件客戶端將郵件正文解釋為HTML:
<?php
mail('recipient@some.net', 'Subject',
'<html><body><p>Your <i>message</i> here.</p></body></html>',
"To: The Receiver <recipient@some.net>n" .
"From: The Sender <sender@some.net>n" .
"MIME-Version: 1.0n" .
"Content-type: text/html; charset=iso-8859-1");
?>
Note both the message in HTML format as well as the two new headers: Mime-Version: and Content-type:.
請注意HTML格式的消息以及兩個新標頭:Mime-Version:和Content-type:。
The MIME-Version: header indicates that the standard extended mail format will be used (MIME stands for Multipurpose Internet Mail Extensions), which allows for messages to be sent content types other than plain text. The Content-type: header then specifies that the message with contain HTML (and sets the character set to the standard for that format).
MIME-Version:標頭表示將使用標準的擴展郵件格式(MIME代表多用途Internet郵件擴展),它允許發送除純文本以外的內容類型的郵件。然后,Content-type:頭指定消息包含HTML(并將字符集設置為該格式的標準)。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。