整合營銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費咨詢熱線:

          前端Rust生態(tài)的背后napi-rs如何讓Rust與

          前端Rust生態(tài)的背后napi-rs如何讓Rust與JavaScript可以相互調(diào)用

          napi-rs 是一個用于在 Rust 中構(gòu)建 Node.js 預(yù)編譯插件的框架。得益于 Rust 的卓越性能表現(xiàn),它正逐漸在前端工具鏈中占據(jù)一席之地,而 napi-rs 則在 Rust 與 JavaScript 交互的實現(xiàn)中扮演著關(guān)鍵角色,因此得到了廣泛的應(yīng)用。

          本文將深入探討如何通過 napi-rs 實現(xiàn) Rust 和 JavaScript 函數(shù)之間的互相調(diào)用,并剖析背后的工作機(jī)制。

          napi-rs 與 N-API 的關(guān)系

          N-API 是 Node.js 官方維護(hù)的一組 API,專為構(gòu)建穩(wěn)定且兼容各版本的 Node.js 原生插件而設(shè)計。

          napi-rs 是基于 N-API 構(gòu)建的,通過提供方便的 Rust 接口,它簡化了在 Rust 中構(gòu)建 Node.js 原生插件的過程。N-API 是 Node.js 提供的原生 API,而 napi-rs 是 N-API 的 Rust 封裝,兩者組合使得 Rust 開發(fā)者能夠更容易地編寫和集成 Node.js 的原生模塊。

          JavaScript 調(diào)用 Rust 函數(shù)

          使用

          在 napi-rs 中,將 Rust 函數(shù)暴露給 JavaScript 使用是異常直觀。通過 napi-rs 的文檔和工具,你可以迅速地得到一個 Rust 寫的 sum 函數(shù),并暴露給了 JavaScript。

          #[napi] pub fn sum(a: i32, b: i32) -> i32 { a + b }

          你可以在 JavaScript 中直接調(diào)用它。

          sum(1, 2)

          實現(xiàn)原理

          為了深入理解 napi-rs 的運作,我們可以使用 cargo expand 命令對 #[napi] 宏進(jìn)行展開,揭示其背后執(zhí)行的具體步驟。

          第一步

          napi-rs 生成 __napi__sum 函數(shù),此函數(shù)作為 Node.js 插件中的橋梁,實現(xiàn) Rust sum 函數(shù)與 JavaScript 環(huán)境之間的參數(shù)接收和返回值傳遞。

          #[doc(hidden)] #[allow(non_snake_case)] #[allow(clippy::all)] extern "C" fn __napi__sum( env: napi::bindgen_prelude::sys::napi_env, cb: napi::bindgen_prelude::sys::napi_callback_info, ) -> napi::bindgen_prelude::sys::napi_value { unsafe { napi::bindgen_prelude::CallbackInfo::<2usize>::new(env, cb, None, false) .and_then(|mut cb| { let arg0={ <i32 as napi::bindgen_prelude::FromNapiValue>::from_napi_value( env, cb.get_arg(0usize), )? }; let arg1={ <i32 as napi::bindgen_prelude::FromNapiValue>::from_napi_value( env, cb.get_arg(1usize), )? }; napi::bindgen_prelude::within_runtime_if_available(move || { let _ret={ sum(arg0, arg1) }; <i32 as napi::bindgen_prelude::ToNapiValue>::to_napi_value(env, _ret) }) }) .unwrap_or_else(|e| { napi::bindgen_prelude::JsError::from(e).throw_into(env); std::ptr::null_mut::<napi::bindgen_prelude::sys::napi_value__>() }) } }
          1. extern "C" 表示這個函數(shù)使用 C 語言的調(diào)用約定,它告訴編譯器生成的函數(shù)應(yīng)與外部 C 代碼或其他語言兼容,這是創(chuàng)建 Node.js 原生模塊所必需的。
          2. 函數(shù)簽名:定義了函數(shù)的參數(shù)和返回類型。根據(jù) N-API 的要求,參數(shù)包括環(huán)境句柄 napi_env 和回調(diào)信息 napi_callback_info。返回類型是 napi_value,這表示了 JavaScript 值。
          3. unsafe 塊:因為涉及到 FFI (Foreign Function Interface 外部函數(shù)接口) 與 Node.js 的交互,所以需要在 unsafe 代碼塊中運行。
          4. CallbackInfo::<2usize>:一個幫助器結(jié)構(gòu),封裝了回調(diào)信息,并知道期望兩個參數(shù)。
          5. 參數(shù)提取:使用 from_napi_value 方法將 JavaScript 參數(shù)轉(zhuǎn)換為 Rust 的 i32 類型。
          6. 計算和返回:調(diào)用 Rust 中的 sum 函數(shù),并使用 to_napi_value 方法將結(jié)果轉(zhuǎn)換回 JavaScript 可以識別的值。
          7. 錯誤處理:如果在參數(shù)轉(zhuǎn)換或函數(shù)執(zhí)行過程中發(fā)生錯誤,通過 unwrap_or_else 來捕獲并處理,這包括將錯誤轉(zhuǎn)換為 JavaScript 錯誤并拋出。

          第二步

          napi-rs 生成 sum_js_function 函數(shù),定義了一個用作 N-API 的原生函數(shù),名為 __napi__sum。它允許你在 JavaScript 環(huán)境中調(diào)用一個名為 sum 的函數(shù),當(dāng) JavaScript 代碼調(diào)用 sum 函數(shù)時,底層調(diào)用的將是 __napi__sum Rust 函數(shù)。

          #[allow(non_snake_case)] #[allow(clippy::all)] unsafe fn sum_js_function( env: napi::bindgen_prelude::sys::napi_env, ) -> napi::bindgen_prelude::Result<napi::bindgen_prelude::sys::napi_value> { let mut fn_ptr=std::ptr::null_mut(); { let c=napi::bindgen_prelude::sys::napi_create_function( env, "sum>#[allow(non_snake_case)] #[allow(clippy::all)] unsafe fn sum_js_function( env: napi::bindgen_prelude::sys::napi_env, ) -> napi::bindgen_prelude::Result<napi::bindgen_prelude::sys::napi_value> { let mut fn_ptr=std::ptr::null_mut(); { let c=napi::bindgen_prelude::sys::napi_create_function( env, "sum\0".as_ptr().cast(), 3usize, Some(__napi__sum), std::ptr::null_mut(), &mut fn_ptr, ); match c { ::napi::sys::Status::napi_ok=> Ok(()), _=> { Err( ::napi::Error::new( ::napi::Status::from(c), { let res=::alloc::fmt::format( format_args!("Failed to register function `{0}`", "sum"), ); res }, ), ) } } }?; napi::bindgen_prelude::register_js_function( "sum\0", sum_js_function, Some(__napi__sum), ); Ok(fn_ptr) }<".as_ptr().cast(), 3usize, Some(__napi__sum), std::ptr::null_mut(), &mut fn_ptr, ); match c { ::napi::sys::Status::napi_ok=> Ok(()), _=> { Err( ::napi::Error::new( ::napi::Status::from(c), { let res=::alloc::fmt::format( format_args!("Failed to register function `{0}`", "sum"), ); res }, ), ) } } }?; napi::bindgen_prelude::register_js_function( "sum>#[allow(non_snake_case)] #[allow(clippy::all)] unsafe fn sum_js_function( env: napi::bindgen_prelude::sys::napi_env, ) -> napi::bindgen_prelude::Result<napi::bindgen_prelude::sys::napi_value> { let mut fn_ptr=std::ptr::null_mut(); { let c=napi::bindgen_prelude::sys::napi_create_function( env, "sum\0".as_ptr().cast(), 3usize, Some(__napi__sum), std::ptr::null_mut(), &mut fn_ptr, ); match c { ::napi::sys::Status::napi_ok=> Ok(()), _=> { Err( ::napi::Error::new( ::napi::Status::from(c), { let res=::alloc::fmt::format( format_args!("Failed to register function `{0}`", "sum"), ); res }, ), ) } } }?; napi::bindgen_prelude::register_js_function( "sum\0", sum_js_function, Some(__napi__sum), ); Ok(fn_ptr) }<", sum_js_function, Some(__napi__sum), ); Ok(fn_ptr) }
          1. unsafe fn sum_js_function(...) 聲明是 unsafe 的,因為它調(diào)用了 FFI(外國函數(shù)接口)相關(guān)代碼,這些代碼可能會觸碰到編譯器正常安全檢查之外的領(lǐng)域。
          2. napi_env 是一個表示當(dāng)前 Node.js 環(huán)境的句柄。
          3. 在閉包中,napi_create_function 由 napi crate 提供,它是 N-API 的 Rust 綁定。這個函數(shù)用于創(chuàng)建一個新的 JavaScript 函數(shù),該函數(shù)的名稱是 sum(C 風(fēng)格的字符串,以空字節(jié)結(jié)尾 >在閉包中,napi_create_function 由 napi crate 提供,它是 N-API 的 Rust 綁定。這個函數(shù)用于創(chuàng)建一個新的 JavaScript 函數(shù),該函數(shù)的名稱是 sum(C 風(fēng)格的字符串,以空字節(jié)結(jié)尾 \0),函數(shù)指針是 Some(__napi__sum)。<),函數(shù)指針是 Some(__napi__sum)。
          4. napi_create_function 返回的是 napi_status 枚舉,標(biāo)明操作是否成功。如果操作成功,Ok(()) 被返回;如果失敗,則構(gòu)建一個錯誤信息并返回 Err。
          5. ? 操作符用于提前返回錯誤。 如果前面的調(diào)用失敗返回 Err,? 將立即將錯誤傳播出當(dāng)前函數(shù),后續(xù)操作不會執(zhí)行。
          6. register_js_function 可能是另一個在當(dāng)前環(huán)境中注冊 JavaScript 函數(shù)的幫助器功能(不是 N-API 的一部分,可能是作者自己建立的額外封裝)。
          7. 放置到 fn_ptr 的函數(shù)指針(napi_value)被返回,這樣 JavaScript 端就能拿到并使用這個函數(shù)。

          第三步

          napi-rs 生成 __napi_register__sum_0 函數(shù),在 Node.js 環(huán)境中使用 N-API 注冊本地模塊的功能。整段代碼的功能是注冊一個名為 sum 的 JavaScript 函數(shù),并關(guān)聯(lián)我們編寫的 Rust 函數(shù)。

          #[allow(clippy::all)] #[allow(non_snake_case)] #[cfg(all(not(test), not(feature="noop"), not(target_family="wasm")))] extern fn __napi_register__sum_0() { napi::bindgen_prelude::register_module_export(None, "sum>#[allow(clippy::all)] #[allow(non_snake_case)] #[cfg(all(not(test), not(feature="noop"), not(target_family="wasm")))] extern fn __napi_register__sum_0() { napi::bindgen_prelude::register_module_export(None, "sum\0", sum_js_function); }<", sum_js_function); }

          第四步

          napi-rs 生成 __napi_register__sum_0___rust_ctor___ctor 靜態(tài)變量,用于在 Node.js 原生模塊被加載時自動執(zhí)行 __napi_register__sum_0 函數(shù)。這是 Rust 中創(chuàng)建初始化函數(shù)的一種方式,用于在動態(tài)庫加載到應(yīng)用程序時設(shè)置某些狀態(tài)或執(zhí)行某些初始化任務(wù)。

          在深入解析下述代碼前,重要的是要知道 Node.js 擴(kuò)展通常是以 .node 擴(kuò)展名出現(xiàn)的文件,這些文件實質(zhì)上是動態(tài)鏈接庫(DLL)。Node.js 在運行時會動態(tài)地加載這些 .node 文件并執(zhí)行其中的代碼。

          #[used] #[allow(non_upper_case_globals)] #[doc(hidden)] #[link_section="__DATA,__mod_init_func"] static __napi_register__sum_0___rust_ctor___ctor: unsafe extern "C" fn() -> usize={ unsafe extern "C" fn __napi_register__sum_0___rust_ctor___ctor() -> usize { __napi_register__sum_0(); 0 } __napi_register__sum_0___rust_ctor___ctor };
          1. #[used]: 這個屬性是為了確保鏈接器在最終的程序中包含這個靜態(tài)變量,即使它看起來未被使用。
          2. #[allow(non_upper_case_globals)]: 允許這個全局靜態(tài)變量命名為非大寫格式,Rust 的規(guī)范是全局變量應(yīng)該命名為大寫格式。
          3. #[link_section="__DATA,__mod_init_func"]: 指定了該靜態(tài)變量要放置在鏈接器的哪個段中。在 Mac系統(tǒng)中,__DATA,__mod_init_func 是用來存放模塊初始化函數(shù)的鏈接器段。當(dāng)動態(tài)庫被加載時,這段里的函數(shù)會自動被執(zhí)行。
          4. static __napi_register__sum_0___rust_ctor___ctor: 定義了一個名為 __napi_register__sum_0___rust_ctor___ctor 的全局靜態(tài)變量,它是一個函數(shù)指針,指向下面定義的 unsafe extern "C" 函數(shù)。
          5. unsafe extern "C" fn __napi_register__sum_0___rust_ctor___ctor(): 這是一個實際的函數(shù)實現(xiàn),它將由靜態(tài)變量引用,并在庫加載時執(zhí)行。此函數(shù)調(diào)用 __napi_register__sum_0(),執(zhí)行 Node.js 原生模塊的初始化代碼。
          6. 函數(shù)返回0:通常用于表示成功,這是 Unix 程序的一種傳統(tǒng)習(xí)慣。

          Rust 調(diào)用 JavaScript 函數(shù)

          有時,在我們的應(yīng)用中,需要從 Rust 發(fā)起對 JavaScript 函數(shù)的調(diào)用,通常這種情況出現(xiàn)在異步操作完成后,例如執(zhí)行回調(diào)函數(shù)。

          使用

          我們以實現(xiàn)一個類似于 Node.js 中的 fs.readFile() 方法為例,但更為簡化。其在 JavaScript 中的類型定義如下:

          function readFile(path: string, callback: (err: Error | null, data?: string)=> void): void;

          使用 napi-rs 可以輕松地用 Rust 語言編寫這個函數(shù)的實現(xiàn):

          #[napi(js_name="readFile", ts_return_type="void")] pub fn read_file(env: Env, path: String, callback: JsFunction) { // ... }

          這里的參數(shù) callback 是 napi::JsFunction 類型,指明了它是 JavaScript 中的一個函數(shù)。

          那么我們?nèi)绾握{(diào)用這個 JavaScript 函數(shù)呢?

          同步調(diào)用

          當(dāng)我們在同一個線程里執(zhí)行 callback 函數(shù)時,事情變得相對簡單。我們可以直接利用 JsFunction 提供的 call 方法來同步執(zhí)行 JavaScript 函數(shù)。

          fn sync_read_file(path: String) -> Result<String> { let mut file=File::open(path)?; let mut contents=String::new(); file.read_to_string(&mut contents)?; Ok(contents) } #[napi(js_name="readFile", ts_return_type="void")] pub fn read_file(env: Env, path: String, callback: JsFunction) { let contents=sync_read_file(path); match contents { Ok(contents)=> { let js_contents=env.create_string(&contents).unwrap(); let js_null=env.get_null().unwrap(); callback.call(None, &[js_null.into_unknown(), js_contents.into_unknown()]).unwrap(); }, Err(err)=> { let js_error=env.create_error(err.into()).unwrap(); callback.call(None, &vec![js_error]).unwrap(); } } }

          此實現(xiàn)為同步調(diào)用,在 Rust 中進(jìn)行文件讀取時會導(dǎo)致 JavaScript 線程停下來等待,直至讀取操作完成。通常當(dāng)我們使用 callback 時,希望異步執(zhí)行此操作,以讓 Node.js 主線程保持非阻塞狀態(tài)。

          異步調(diào)用

          如果我們嘗試將這個同步的 readFile 方法內(nèi)部簡單地創(chuàng)建一個新的線程來進(jìn)行異步處理,會遇到問題:

          #[napi(js_name="readFile", ts_return_type="void")] pub fn read_file(env: Env, path: String, callback: JsFunction) { + spawn(move || { let contents=sync_read_file(path); match contents { Ok(contents)=> { let js_contents=env.create_string(&contents).unwrap(); let js_null=env.get_null().unwrap(); callback.call(None, &[js_null.into_unknown(), js_contents.into_unknown()]).unwrap(); }, Err(err)=> { let js_error=env.create_error(err.into()).unwrap(); callback.call(None, &vec![js_error]).unwrap(); } } + }); }

          我們需要先回頭看一下先前編寫的同步調(diào)用代碼,其中 read_file() 函數(shù)的第一個參數(shù)是 env: Env,這個參數(shù)由 napi-rs 自動提供,而不是由 JavaScript 傳遞的。此 Env 用于在對應(yīng)的 JavaScript 環(huán)境中創(chuàng)建傳遞給 callback 的參數(shù),我們使用 create_string() 創(chuàng)建 JavaScript 字符串,使用 env.create_error() 或 get_null() 方法創(chuàng)建 JavaScript 異常。

          在多線程環(huán)境中,無法直接訪問 Env,因為 Node.js 是設(shè)計為單線程運行的,你無法在另外一個線程上訪問 env: Env。

          Node-API 提供了 Threadsafe Function API 來安全地在其他線程上調(diào)用 JavaScript 函數(shù)。盡管它的實現(xiàn)較為復(fù)雜,很多開發(fā)者可能還不熟悉如何正確使用它,但 napi-rs 提供了一個更簡潔易用的 Threadsafe Function API 封裝,我們可以使用這個封裝后的版本。

          fn sync_read_file(path: String) -> Result<String> { let mut file=File::open(path)?; let mut contents=String::new(); file.read_to_string(&mut contents)?; Ok(contents) } #[napi(js_name="readFile", ts_return_type="void")] pub fn read_file(path: String, callback: JsFunction) { let tsfn: ThreadsafeFunction<Result<String>, ErrorStrategy::CalleeHandled>=callback .create_threadsafe_function(0, |ctx: ThreadSafeCallContext<std::prelude::v1::Result<String, Error>>| { match ctx.value { Ok(value)=> { let js_contents=ctx.env.create_string(&value).unwrap(); Ok(vec![js_contents]) }, Err(err)=> { Err(err) }, } }).unwrap(); spawn(move || { let contents=sync_read_file(path); tsfn.call(Ok(contents), ThreadsafeFunctionCallMode::Blocking); }); }

          當(dāng)在 JavaScript 中執(zhí)行 readFile() 方法,Rust 會開啟一個新的線程來處理 IO 操作,避免阻塞 JavaScript 的主線程。這樣,JavaScript 主線程便能無干擾地繼續(xù)處理其他任務(wù)。一旦 Rust 完成文件內(nèi)容的讀取,它就會在該線程上觸發(fā) callback,執(zhí)行回調(diào)函數(shù)。

          參考資料

          • Working with JavaScript functions
          • N-API ThreadSafeFunction
          • napi-rs ThreadsafeFunction


          作者:聰聰正在遞歸下降
          鏈接:https://juejin.cn/post/7322288075850039359
          來源:稀土掘金
          著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。

          、HTML簡介

          1.HTML是什么?

          HTML:htper text markup language超文本標(biāo)記(標(biāo)簽)語言

          由各種標(biāo)簽組成,用來制作網(wǎng)頁,告訴瀏覽器如何顯示頁面

          2.作用

          • 制作網(wǎng)頁,控制網(wǎng)頁和內(nèi)容的顯示
          • 插入圖片、音樂、視頻、動畫等多媒體
          • 通過鏈接來檢索信息
          • 使用表單獲取用戶的信息,實現(xiàn)交互

          3.版本

          w3c:world wide web consortium萬維網(wǎng)聯(lián)盟,制定web技術(shù)相關(guān)標(biāo)準(zhǔn)和規(guī)范的組織,HTML技術(shù)hi由w3c制定的標(biāo)準(zhǔn)

          兩個版本:HTML4.0.1、HTML5.0-----通常H5

          官網(wǎng):http://www.W3shcool.com.cn

          4.擴(kuò)展名

          HTML文檔是以.html或.htm結(jié)尾

          二、HTML文檔結(jié)構(gòu)

          1.基本結(jié)構(gòu)

          1.1簡介

          • HTML標(biāo)簽是由尖括號括起來的關(guān)鍵詞,如,通常是成對出現(xiàn)的,如<html></html>
          • <html>為根標(biāo)簽,包含: <head>頭部和<body>主體部分
          • 頭部提供關(guān)于網(wǎng)頁的相關(guān)信息,如標(biāo)題、文檔類型、字符編碼、關(guān)鍵字等摘要信息
          • 主體部分提供網(wǎng)頁的顯示內(nèi)容,真正顯示在頁面中的內(nèi)容
          • 合理地進(jìn)行縮進(jìn)
          • 標(biāo)簽名不區(qū)分大小寫,但是一般要用小寫

          1.2.開發(fā)工具

          記事本notepad、sublime、Notepad++、Dreamweaver、VScode、Webstorm等

          使用步驟:

          1. 新建文件(cltr+N),然后保存(ctrl+s),指定擴(kuò)展名為.html
          2. 編寫HTML代碼
          3. 在瀏覽器中打開文件

          使用技巧:

          • 先保存再寫代碼,否則代碼無顏色提示
          • 創(chuàng)建一個文件夾,用于保存所有的網(wǎng)頁內(nèi)容,將文件夾拖拽到sublime中,便于管理
          • 顯示/隱藏側(cè)邊欄方式1:查看–>側(cè)邊欄–>顯示/隱藏側(cè)邊欄方式2:ctrl+K緊接著按B
          • 顯示多欄方式1:查看–>布局–>列數(shù):2列方式2:Alt+shift+2

          1.3瀏覽器

          常見的瀏覽器:IE瀏覽器微軟、chrome谷歌瀏覽器、fifirefox火狐、safari蘋果

          瀏覽器的作用是讀取html文件,并以網(wǎng)頁的形式來顯示

          瀏覽器不會直接顯示html標(biāo)簽,而是使用標(biāo)簽來解釋網(wǎng)頁的內(nèi)容

          2.標(biāo)簽

          2.1標(biāo)簽的組成

          一個完整的html標(biāo)簽的組成:

          <標(biāo)簽名 屬性名="屬性值">內(nèi)容</標(biāo)簽名>

          <!DOCTYPE html>
          <html lang="en">
          	<head>
          		<meta charset="UTF-8">
          		<title>標(biāo)簽</title>
          	</head>
          	<body  bgcolor="red" text="blue">
          		html從入門到精通!
              </body>
          </html>
          12345678910

          屬性值要用雙撇號括起來,一般用雙引號

          2.2標(biāo)簽的分類

          根據(jù)標(biāo)簽是否關(guān)閉,分為,關(guān)閉型和非關(guān)閉型

          • 關(guān)閉型:有結(jié)束標(biāo)簽,即標(biāo)簽成對出現(xiàn)
          <html></html>
          <head></head>
          <title></title>

          非關(guān)閉型:沒有結(jié)束標(biāo)簽

          <meta>
          <br>
          <h1>....<h6>

          根據(jù)標(biāo)簽是否獨占一行,分為塊級標(biāo)簽和行級標(biāo)簽

          塊級標(biāo)簽:顯示為塊狀,獨占一行

          <h1>大家好</h1>
          <hr>

          行級標(biāo)簽:在行內(nèi)顯示,可與其他內(nèi)容在同一行顯示

          <span></span>

          2.3注釋

          注釋在瀏覽器中不會顯示,是用來標(biāo)注解釋html語句,但通過查看源代碼的方式可以看到

          語法:

          <--注釋內(nèi)容-->

          2.4實體字符

          也稱為特殊字符,用于顯示一些特殊符號,如<>&空格等

          語法:

          <&實體字符的名稱>

          2.5文檔類型

          在html文檔的第一行,使用<!DOCTYPE html>

          聲明HTML文檔的類型用來告訴瀏覽器頁面的文檔嘞型,用來制定html版本的規(guī)范

          目前基本上最常用的html5

          <!DOCTYPE html>
          <html lang="en">
          <head>
          	<meta charset="UTF-8">
          	<title>Document</title>
          </head>
          <body>
          	
          </body>
          </html>
          12345678910

          三\常用標(biāo)簽

          3.1基本標(biāo)簽

          • 塊級標(biāo)簽\親啊后有明顯的間隔 |
            | h1…h(huán)5 | 標(biāo)題標(biāo)簽 | 按照h1到h6逐漸變小.塊級標(biāo)簽 |
            | | | |
            | | | |


          • 三、常用標(biāo)簽

          1.基本標(biāo)簽

          1.1 有序列表
          ol:ordered listli:list item默認(rèn)使用阿拉伯?dāng)?shù)字、從1開始標(biāo)記,可以通過屬性進(jìn)行修改
          · type屬性:設(shè)置列表的符號標(biāo)記、取值;數(shù)字1(默認(rèn))、字母(a或A)、羅馬數(shù)字(i或I) · start屬性:設(shè)置起始值,值必須是數(shù)字
          1.2 無序列表
          ul:unodered list
          li:list item
          默認(rèn)情況下使用實心圓表作為符號標(biāo)記,可以通過屬性進(jìn)行修改
          · type屬性:設(shè)置列表的符號標(biāo)記、取值:disc實心圓(默認(rèn))、circle空心圓、square正方形、none不 顯示項目符號
          1.3 定義列表
          dl:definition list
          dt:definition title
          dd:definition description
          1.4 水平線標(biāo)簽
          hr:horizontal
          常用屬性:
          · color:顏色

          兩種方式:

          顏色名稱:如red、green、blue、white、black、pink、orange等

          16進(jìn)制的RGB表示法:Red、Green、Blue用法:#RRGGBB 每種顏色的取值范值0-255,轉(zhuǎn)換為16 進(jìn)制00-FF

          如: #FF0000 紅色 #00FF00綠色 #0000FF藍(lán)色 #FFFFFF白色、#CCCCCC #FF7300桔色

          · size:粗細(xì),數(shù)值

          · width寬度

          兩種寫法:

          ? 像素:絕對值(固定值)

          ? 百分比:相對值,相對于水平線標(biāo)簽所在父容器寬度的百分比

          · align對齊

          ? 取值:center居中 left right
          1.5圖像標(biāo)簽
          img:image
          常見的圖片格式:.jpg .png .gif .bmp
          常見的屬性:
          · src:source指定圖片的路徑(來源),必選叁數(shù)

          如果圖片與html源代碼在同一個文件夾中,可以直接在src中寫圖片名稱即可

          習(xí)慣上,我們會將多個圖片與html代碼文檔分別放在同一個文件夾project中的不同目錄下,此時需要 在src中指定圖片的路徑為相對路徑

          路徑的分類:

          ? · 相對路徑

          ? 表示: ./當(dāng)前路徑
          …/當(dāng)前位置的上一級文件夾

          ? 提示:…/image

          ? · alt:當(dāng)圖片無法顯示時顯示的提示信息

          ? · title:當(dāng)鼠標(biāo)放到圖片上時顯示的提示信息

          ? · width和 height:設(shè)置圖片的寬度和高度
          默認(rèn)圖片以原始尺寸顯示

          ? 如果只設(shè)置其中一個,則另一個會按比例縮放

          ? 如果同時設(shè)置寬和高,可能導(dǎo)致圖片變形

          ? 兩種寫法:

          ? 像素:絕對值(固定值)

          ? 百分比:相對值,相對于父容器的尺寸的百分比
          2.其他標(biāo)簽

          為了更好語義化
          3.頭部標(biāo)簽
          · meta定義網(wǎng)頁的摘要信息,如字符編碼,關(guān)鍵詞,描述,作者等
          · title定義網(wǎng)頁的標(biāo)題
          · style定義內(nèi)容css樣式
          · link引用外部css樣式
          · script定義或引用腳本
          · base定義基礎(chǔ)路徑
          默認(rèn)以當(dāng)前頁面文件所在的位置為相對路徑參照
          4.標(biāo)簽嵌套
          一個標(biāo)簽中嵌套另外一個標(biāo)簽
          標(biāo)簽不能亂嵌套
          瀏覽器渲染后顯示的頁面代碼與編碼時有所不同
          chrome瀏覽器提供的開發(fā)工具:幫助開發(fā)人員查看和調(diào)試頁面的
          如何打開:
          · Elements:從瀏覽器的角度來看頁面,瀏覽器渲染頁面時內(nèi)部的結(jié)構(gòu)
          · console:控制臺,顯示各種警告和錯誤信息
          · network:查看網(wǎng)絡(luò)請求信息,瀏覽器向服務(wù)器請求了哪些資源,資源大小,
          加載資源所消耗的時間

          四、超鏈接
          1.簡介
          使用超鏈接可以從一個頁面跳轉(zhuǎn)到另外一個頁面,實現(xiàn)頁面之間導(dǎo)航
          當(dāng)鼠標(biāo)移動到超鏈接文本或圖片時,鼠標(biāo)箭頭會變成一只小手
          超鏈接有三種類型:
          普通鏈接/頁面間的鏈接,跳轉(zhuǎn)到另一個頁面 錨鏈接:鏈接到錨點(鏈接到同一個頁面的指定位置) 功能鏈接:實現(xiàn)特殊功能(發(fā)郵件,下載)
          2.基本用法
          使用 標(biāo)簽來創(chuàng)建超鏈接
          語法格式:

          常用屬性:
          href:鏈接地址或路徑,鏈接地址

          world

          鏈接文本或圖片

          1 2 3 4 5 1 target:鏈接打開的位置,取值

          路徑分類:
          絕對路徑 以根開始的路徑
          file:///D:/software/b.html https://www.baidu.com/img/bd_logo1.png
          相對路徑 相對于當(dāng)前頁面文件所在的路徑,不是以根開始的路徑 ./ 當(dāng)前路徑 …/ 當(dāng)前位置上一級目錄

          3.錨鏈接
          3.1簡介
          點擊鏈接后跳轉(zhuǎn)到某一個頁面的指定位置(錨點anchor)
          錨鏈接的分類:
          頁面內(nèi)的錨鏈接 頁面間的錨鏈接
          3.2 頁面內(nèi)的錨鏈接
          步驟:

          1. 定義錨點(標(biāo)記)
          2. 鏈接錨點
            _self 自身,當(dāng)前,默認(rèn)值 _blank新的,空白的 _parent父層框架 _top頂層框架
            目標(biāo)位置
            1 2 3 4
            1

          3.3 頁面間的錨鏈接

          4.功能鏈接
          5.URL
          5.1 簡介
          URL:Uniform Resource Locator 統(tǒng)一資源定位器,用來定位資源所在的位置,最常見的就是網(wǎng)址

          5.2 組成
          一個完整的URL由8個部分組成:
          協(xié)議:prococol 如 http:超文本傳輸協(xié)議,用來訪問WEB網(wǎng)站Hyper text Transfer protocal https:更加安全的協(xié)議 SSL安全套接子層 ftp文件傳輸協(xié)議,用來訪問服務(wù)器上的文件,實現(xiàn)文件的上傳和下載File Transfer protocol file:文件協(xié)議,用來訪問本地文件 主機(jī)名hostname服務(wù)器地址或服務(wù)器Netbios名稱,如www.baidu.com ftp://10.255.254.254 端口:port位于主機(jī)名的后面,使用冒號進(jìn)行分隔 不同的協(xié)議使用不同的端口,如http使用80端口,https使用的443端口,ftp使用20和21 如果使用的是默認(rèn)端口,則端口可以省略 如果使用的不是默認(rèn)端口,則必須指定端口http://59.49.32.213:7070/ 路徑:path目標(biāo)文件所在的路徑結(jié)構(gòu),如:www.baidu.com/img/ 資源resource要訪問的目標(biāo)文件,如bd_logo1.png 查詢字符串:query string 也稱為參數(shù) 在資源后面使用?開頭的一組名稱/值
          鏈接文本
          鏈接文本
          https://www.baidu.com/img/bd_logo1.png?name=tom&age=2&sex=male https://www.w3school.com.cn/html/html_quotation_elements.asp file:///C:/Users/Administrator/Desktop/project/code/09.%E5%B8%B8%E7%94%A8%E6%A0%87%E7%A D%BE3.html http://www.sxgjpx.net/ ftp://10.255.254.253/
          1
          1
          1 2 3
          4 5
          名稱和值之間以=分隔,多個之間用&分隔,如:name=tom&age=2&sex=male 錨點anchor,在資源后面使用#開頭的文本,如#6 身份認(rèn)證authentication,指定身份信息,如:ftp://賬戶:密碼@ftp.bbshh010.com
          五、表格
          1.簡介
          表格是一個規(guī)則的行列結(jié)構(gòu),每個表格是由若干行組成,每行由若干個單元格組成
          table row column
          2.基本結(jié)構(gòu)
          2.1 table標(biāo)簽
          用來定義表格
          常用屬性:
          border:表格邊框 默認(rèn)為0 width/height:寬度/高度 bordercolor:邊框的顏色 align:對齊方式,取值:left(默認(rèn)) center居中 right居右 bgcolor:背景顏色 background:背景圖片 cellspacing間距:單元格與單元格之間的距離 cellpadding邊距:單元格中的內(nèi)容到邊界之間的距離
          2.2 tr標(biāo)簽
          用來定義行:table row
          常用屬性:
          align:水平對齊 取值:left(默認(rèn)) center right valign垂直對齊 取值:top center bottom bgcolor:背景顏色 background:背景圖片
          2.3 td標(biāo)簽
          用來定義單元格,table data
          常用屬性:align、valign、bgcolor、background
          注意:表格必須是由行組成,行必須由單元格來組成,數(shù)據(jù)必須放到單元格中
          3.合并單元格
          合并單元格也稱為單元格的跨行跨列
          兩個屬性:
          rowspan 設(shè)置單元格所跨的行數(shù) colspan 設(shè)置單元格所跨的列數(shù)
          步驟:

          1. 在跨越的單元格中設(shè)置rowspan/colspan屬性 2. 將被跨越的單元格刪除
            必須要保證每行的實際列數(shù)是相同的,否則表格可能會出錯亂
            4.高級標(biāo)簽
            4.1caption標(biāo)簽
            表格的標(biāo)題標(biāo)簽
            4.2thead標(biāo)簽
            表格的頭部table head
            4.3th標(biāo)簽
            表格的頭部標(biāo)題table head title
            一般用在thead中,設(shè)置頭部的標(biāo)題,替代td標(biāo)簽,與td的區(qū)別,th中的文本會加粗且居中顯示
            4.4tbody標(biāo)簽
            表格的主體table body
            4.5tfoot標(biāo)簽
            表格的底部table foot




          六、表單
          1.簡介
          表單是一個包含若干個表單元素的區(qū)域,用于獲取瑣類型的用戶數(shù)據(jù)

          表單元素是允許用戶在表單輸入信息的元素,如文本框、密碼框、單選按鈕、復(fù)選框、下拉列表、按鈕等
          2.表單結(jié)構(gòu)
          2.1表單語法

          1

          2.2form標(biāo)簽
          用來定義表單,可以包含多個表單元素
          常用屬性:
          action:提交數(shù)據(jù)給誰處理,即處理數(shù)據(jù)的程序,默認(rèn)為當(dāng)前頁面 method:提交數(shù)據(jù)的方式或方法,取值:get(默認(rèn)),post get和post的區(qū)別: get:以查詢字符串的形式提交,在地址欄中能看到,長度有限制,不安全 post以表單數(shù)據(jù)組的形式進(jìn)行提交,在地址欄中看不到,長度無限制,安全 enctype(encode type)編碼類型:提交數(shù)據(jù)的編碼,取值:application/X-www-form-urlencoded(默 認(rèn))、multipart/form-data(文件上傳)
          3.表單元素
          大多數(shù)的表單元素都是使用 標(biāo)簽來定義的,通過設(shè)置屬性type來定義不同的表單元素

          1

          3.1單行文本框
          常用屬性:
          ·name名稱,很重要,如果沒有定義name屬性,則該表單元素的數(shù)據(jù)是無法提交的

          ·value初始值

          ·size顯示寬度

          ·maxlength:大字符數(shù),默認(rèn)是沒有限制

          ·readonly只讀:readonly=“readonly”,可簡寫readonly,即只寫屬性名

          ·disabled禁用:disabled=“disabled”, 可簡寫disabled完全禁用

          表單元素被提交的兩個條件,1.有name屬性2.非disabled

          3.2 單選按鈕
          常用屬性:

          ·name名稱:多個radio的name屬性必須相同,才能實現(xiàn)互斥(單選)

          ·value值

          ·checked:是否被選中,兩種狀態(tài),選中,未選中 checked=“checked” 簡寫 checked

          3.3 復(fù)選框
          常用屬性與單選按鈕radio類似

          3.4 文件選擇器
          常用屬性:

          ·name:名稱

          ·accept設(shè)置可選擇的文件類型,用來限制上傳的文件類型

          使用MIME格式字符串對資源類型進(jìn)行限制

          常見的MIME類型:

          ·純文本:text/plain text/xml text/html

          · 圖像:image/png image/jpeg image/gif

          4.特殊表單元素

          4.1下拉列表

          select常用屬性:

          ·name名稱

          ·size行數(shù),同時顯示多個選項

          ·multiple允許同時選擇多個

          option常用屬性:

          ·value選項值

          ·selected設(shè)置默認(rèn)選中項

          optgroup常用屬性:

          ·label分組的標(biāo)簽

          4.2文本域

          ·name名稱

          ·rows行數(shù)

          ·cols列數(shù)


          5、其他標(biāo)簽

          5.1 label標(biāo)簽

          為表單元素提供標(biāo)簽,當(dāng)選中l(wèi)abel標(biāo)簽中的文本內(nèi)容時會自動將光標(biāo)切換到與之相關(guān)聯(lián)的表單元素。

          常用屬性:

          ·for必須將該屬性值設(shè)置為與相關(guān)聯(lián)的表單元素的Id屬性值相同。

          注:幾乎所有HTML標(biāo)簽都具有id屬性,且id值必須唯一。

          5.2 button標(biāo)簽

          也表示按鈕,與input按鈕類似

          語法:

          1按鈕文字或圖像

          常用屬性:

          ·type按鈕的類型,取值: submit(默認(rèn))、reset、button

          5.3 fieldset和legend標(biāo)簽

          fieldset標(biāo)簽,對表單元素進(jìn)行分組

          legend標(biāo)簽,對分組添加標(biāo)題

          七、內(nèi)嵌框架
          1、簡介

          使用iframe可以在一個頁面中引用另一個頁面,實現(xiàn)復(fù)用、靈活

          2、基本用法

          語法:

          1

          常用屬性:

          · src:引用的頁面

          · width/height寬度/高度 ,像素或百分比

          · frameborder是否顯示邊框,取值:1(yes) 0(no)—默認(rèn)

          · scrolling是否顯示滾動條,取值:yes no auto

          · name屬性 為框架定義名稱

          3、在框架中打開鏈接

          1

          2

          3鏈接的文本或圖像

          八、HTML5簡介

          1、發(fā)展

          W3C于1992年12月發(fā)布了HTML4.0.1標(biāo)準(zhǔn)
          W3C于2014年10月發(fā)布了HTML5標(biāo)準(zhǔn)

          2、特點

          · 取消了過時的標(biāo)簽,如font、center等,它們僅具有展示外觀的功能

          · 增加了一些更具有語義化的標(biāo)簽,如header、footer、aside等

          · 增加了一些新功能標(biāo)簽,如canvas、audio、video

          · 增加了一些表單控件,如email、date、time、url、search等

          · 可以直接在瀏覽器中繪畫(canvas),無需flash

          · 增加了本地存儲的支持

          3、兼容性

          http://caniuse.com

          提供了各種瀏覽器版本對HTML5和CSS規(guī)范的支持度

          九、HTML5新增內(nèi)容
          1、結(jié)構(gòu)相關(guān)的標(biāo)簽

          用來進(jìn)行頁面結(jié)構(gòu)布局,本身無任何特殊樣式,需要使用CSS進(jìn)行樣式設(shè)置

          · article定義一個獨立的內(nèi)容,完整的文章

          · section定義文檔的章節(jié)、段落

          · header文章的頭部、頁眉、標(biāo)題

          · footer文章的底部、頁腳、標(biāo)注

          · aside定義側(cè)邊欄

          · figure圖片區(qū)域

          · figcaption為圖片區(qū)域定義標(biāo)題

          · nav定義導(dǎo)航菜單

          結(jié)構(gòu)標(biāo)簽只是表明各部分的角色,并無實際的外觀樣式,與普通div相同

          2、語義相關(guān)的標(biāo)簽
          2.1 mark標(biāo)簽
          標(biāo)注,用來突出顯示文本,默認(rèn)添加黃色背景
          2.2 time標(biāo)簽
          定義日期和時間,便于搜索引擎智能查找
          2.3 details和 summary標(biāo)簽
          默認(rèn)顯示summary中的內(nèi)容,點擊后顯示details中的內(nèi)容
          注:并不是所有的瀏覽器都兼容,chrome、opera支持、Firefox、IE瀏覽器不支持
          2.4 meter標(biāo)簽
          計數(shù)儀,表示度量
          常用屬性:

          · max定義大值,默認(rèn)為1

          · min定義小值,默認(rèn)為0

          · value定義當(dāng)前值

          · high定義限定為高的值

          · low定義限定為低的值

          · optimum定義佳值

          規(guī)則:

          1. 如果optimum大于high,則表示值越大越好

          當(dāng)value大于high時為綠色

          當(dāng)value在low與high之間時為黃色

          當(dāng)value小于low時為紅色

          1. 如果optimum小于low,則表示值越小越好

          當(dāng)value小于low時為綠色

          當(dāng)value在low與high之間時為黃色

          當(dāng)value大于high時為紅色

          1. 當(dāng)optimum介于low和high之間,則表示值在low和high之間好當(dāng)value在low與high之間時顯示綠色,否則顯示黃色

          2.5 progress標(biāo)簽
          進(jìn)度條,表示運行中的進(jìn)度
          常用屬性:

          · value定義當(dāng)前值

          · max定義完成的值

          3.表單相關(guān)
          3.1 新增表單元素
          新增以下type類型:

          · email接收郵箱

          · url接收URL

          · tel接收電話號碼,目前僅在移動設(shè)備上有效

          · search搜索文框

          · number/range接收數(shù)字/數(shù)字滑塊,包含min,max,step屬性

          · date/month/week/time/datetime日期時間選擇器,兼容性不好

          · color顏色拾取

          作用:

          · 具有格式校驗的功能

          · 可以與移動設(shè)備的鍵盤相關(guān)聯(lián)

          3.2新增表單屬性
          form標(biāo)簽的屬性:

          · autocomplete是否啟動表單的自動完成功能, 取值:on(默認(rèn))、o?

          · novalidate提交表單時不進(jìn)行校驗,默認(rèn)會進(jìn)行表單校驗

          3.3 新增表單元素的屬性
          新增表單元素屬性:input/select/textarea等

          · placeholder提示文字

          · required是否必填

          · autocomplete是否啟用該表單元素的自動完成功能

          · autofocus設(shè)置初始焦點元素

          · pattern使用正則表達(dá)式(RegExp后面會講解),進(jìn)行數(shù)據(jù)校驗

          · list使文本元素具有下拉列表的功能,需要配合datalist和option標(biāo)簽一起使用

          · form可以將表單元素寫在form標(biāo)簽外面,然后通過該屬性關(guān)聯(lián)指定的表單

          4、多媒體標(biāo)簽
          4.1audio標(biāo)簽
          在頁面中插入音頻,不同的瀏覽器對音頻格式的支持不一樣
          audio常用屬性:

          · src音頻文件的來源

          · controls是否顯示控制面板,默認(rèn)不顯示

          · autoplay是否自動播放,默認(rèn)不自動播放

          · loop是否循環(huán)播放

          · muted是否靜音

          · preload是否預(yù)加載,取值:none不預(yù)加載、auto預(yù)加載(默認(rèn))、metadata只加載元數(shù)據(jù)

          如果設(shè)置了autoplay屬性,則該屬性無效

          可以結(jié)合source標(biāo)簽使用,指定多個音頻文,瀏覽器會檢測并使用第一個可用的音頻文件

          4.2 video標(biāo)簽
          在頁面中插入視頻,不同的瀏覽器對視頻格式的支持不一樣
          用法與audio標(biāo)簽基本相同,增加屬性:

          · widht/height視頻播放器的寬度/高度

          · poster在視頻加載前顯示的圖片

          案例1hello.html

          <html>
          	<body>
          		<tiele>HTML技術(shù)</tiele>
          	</body>
          	<body>
          		大家好,歡迎學(xué)習(xí)html技術(shù)!
          	</body>
          </html>1234567

          效果

          [外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-h271e4v6-1593240920352)(C:\Users\lenovo\Desktop\新建文件夾\靜態(tài)網(wǎng)頁2\案例\result\案例1.png)]

          案例2標(biāo)簽的組成.html

          <!DOCTYPE html>
          <html lang="en">
          <head>
          	<meta charset="UTF-8">
          	<title>標(biāo)簽</title>
          </head>
          <body text="blue">
          	標(biāo)簽的組成
          	<br>
          	html從入門到精通!
          	<hr>
          	<h1>標(biāo)簽的分類</h1>
          	<hr>
          
          	<h2>標(biāo)簽的分類</h2>
          	<hr>
          
          	<h6>標(biāo)簽的分類</h6>
          	<hr>
          
          	<span>哈哈</span>嘿嘿
          	
          </body>
          </html>1234567891011121314151617181920212223

          效果

          [外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-jx6zJE1P-1593240920354)(C:\Users\lenovo\Desktop\新建文件夾\靜態(tài)網(wǎng)頁2\案例\result\案例2.png)]

          案例3實體字符.html

          <!DOCTYPE html>
          <html lang="en">
          <head>
          	<meta charset="UTF-8">
          	<title>Document</title>
          </head>
          <body>
          	圖書:<<HTML從入門到精通<<
          	<hr>
          
          	北京      上海      廣州
          	<hr>
          
          	在HTML中用<表示<小于號
          	<hr>
          
          	“HTML語言” 或 &qout;HTML語言&qout;
          	<hr>
          
          	版權(quán)所有? 2000-2020 高教培訓(xùn)
          	<hr>
          
          	×關(guān)閉符號
          </body>
          </html>123456789101112131415161718192021222324

          效果

          [外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-nuFLl3hm-1593240920355)(C:\Users\lenovo\Desktop\新建文件夾\靜態(tài)網(wǎng)頁2\案例\result\案例3.png)]

          (剩下的下期出)

          原文鏈接:https://blog.csdn.net/WanXuang/article/details/106982782?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522160513384519724835852804%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=160513384519724835852804&biz_id=&utm_medium=distribute.pc_search_top_result.none-task-code-2~all~top_position~default-1-106982782-12.nonecase&utm_term=html

          作者:WanXuang

          出處:從CSDN

          MACSS(Sentence Modular And Compound Structure)是一種將 CSS 代碼分解為相互關(guān)聯(lián)的獨立模塊的方法。它可以提高 CSS 代碼的可重用性、可維護(hù)性和可讀性。

          SMACSS 的優(yōu)勢

          * 可重用性:使用模塊可以提高 CSS 代碼的可重用性。

          * 可維護(hù)性:結(jié)構(gòu)化代碼簡化了維護(hù)。

          * 可讀性:清晰的模塊結(jié)構(gòu)易于閱讀和理解。

          SMACSS 的核心概念

          1. 句法 (Sentence)

          * 完整的 CSS 語句。

          * 應(yīng)該表示一個可重用的獨立功能或外觀。

          2. 模塊 (Module)

          * 組織 CSS 規(guī)則的組。

          * 每個模塊應(yīng)表示界面設(shè)計中的特定概念或功能。

          3. 組合 (Compound)

          * 簡單的 CSS 選擇器,包含多個元素。

          * 應(yīng)用于將多個元素組合成更復(fù)雜的結(jié)構(gòu)。

          工具和集成

          * 各種工具可用于使用 SMACSS。

          * 許多 IDE 和 CSS 管理工具集成了 SMACSS 功能。

          使用 SMACSS 的優(yōu)點

          * 提高 CSS 代碼的可重用性。

          * 提高 CSS 代碼的可維護(hù)性。

          * 提高 CSS 代碼的可讀性。

          結(jié)論

          SMACSS 是一種強(qiáng)大的 CSS 組織方法,可以提高 CSS 代碼的可重用性、可維護(hù)性和可讀性。它是現(xiàn)代 web 開發(fā)中使用最廣泛的組織方法之一。


          主站蜘蛛池模板: 日韩美女视频一区| 日本内射精品一区二区视频| 亚洲国产精品一区二区九九| 无码精品人妻一区二区三区AV| 亚洲韩国精品无码一区二区三区| 日韩美一区二区三区| 亚洲国产成人久久一区二区三区| 麻豆AV无码精品一区二区 | 亚洲欧美日韩一区二区三区在线| 中文字幕一区二区三区永久| 久久精品岛国av一区二区无码| 色一乱一伦一区一直爽| 国产福利一区二区在线视频 | 国产拳头交一区二区| 美女毛片一区二区三区四区| 欧洲精品一区二区三区| 亚洲日韩一区精品射精| 亚洲一区二区三区四区视频 | 亲子乱av一区二区三区| 国产乱码精品一区二区三区麻豆| 日韩免费一区二区三区在线播放| 亚洲一区日韩高清中文字幕亚洲| 久久久综合亚洲色一区二区三区 | 亚洲av无码片vr一区二区三区| 国产成人无码AV一区二区| 在线观看一区二区精品视频| 区三区激情福利综合中文字幕在线一区亚洲视频1 | 天堂Aⅴ无码一区二区三区| 中文人妻av高清一区二区| 一区二区精品在线| 亚洲一区二区三区在线观看网站| 亚洲福利一区二区| 午夜福利国产一区二区| 极品人妻少妇一区二区三区| chinese国产一区二区| 寂寞一区在线观看| 丰满岳乱妇一区二区三区| 最美女人体内射精一区二区| 日本精品视频一区二区三区| 日韩一区二区三区不卡视频 | 精品无码人妻一区二区三区18|