網(wǎng)站續(xù)費(fèi)收多少合適營(yíng)銷手段有哪些
昨天解決了焦點(diǎn)問題,今天就開始搬磚了。本以為可以一帆風(fēng)順,但是還是遇到了幾個(gè)問題,不過還好,都被一一解決,這里我分享一下JsValue的轉(zhuǎn)換體驗(yàn)以及關(guān)鍵字as
的使用淺析。
場(chǎng)景描述
我是在什么情況下遇到JsValue的轉(zhuǎn)換的呢?獲取當(dāng)前窗口的內(nèi)部寬度和內(nèi)部高度。api的接口定義如下:
pub fn inner_width(&self) -> Result<JsValue, JsValue>
pub fn inner_height(&self) -> Result<JsValue, JsValue>
我使用當(dāng)前窗口的內(nèi)部寬度和內(nèi)部高度的地方在Modal組件中:
#[derive(Properties, Clone, PartialEq)]
pub struct Props {...#[prop_or(200)]pub width: u32,#[prop_or(500)]pub height: u32,
}
也就是說,我要將JsValue轉(zhuǎn)換成u32類型。
問題解決
先看這個(gè)問題最終是怎么解決的吧。和Javascript代碼比起來,是稍微復(fù)雜了一點(diǎn)點(diǎn)。
pub fn get_window_size() -> Option<(u32, u32)> {if let Some(window) = get_window() {let width = window.inner_width().unwrap_or_else(|_| JsValue::from_f64(default_width1));let height = window.inner_height().unwrap_or_else(|_| JsValue::from_f64(default_height1));let width1: f64 = width.as_f64()?;let height1: f64 = height.as_f64()?;let width2 = width1 as u32;let height2 = height1 as u32;return Some((width2, height2));}None
}
邏輯比較簡(jiǎn)單,步驟如下
- 先通過window對(duì)象拿到
width
和height
; - 通過方法
as_f64
將JsValue轉(zhuǎn)換成f64
類型; - 通過rust的
as
關(guān)鍵字將f64
類型轉(zhuǎn)換成u32
類型;
問題展開
從問題的解決層面上來說,明確上面3步,就可以拿到我們需要的數(shù)據(jù),但是這顯然只是冰山一角。水下面的東西很多,這里我挑2個(gè)容易的來說。
關(guān)于JsValue的數(shù)據(jù)轉(zhuǎn)換
JsValue定義在wasm_bindgen
中,關(guān)于數(shù)據(jù)轉(zhuǎn)換的接口有下面這幾個(gè):
pub fn as_bool(&self) -> Option<bool>;
pub fn as_f64(&self) -> Option<f64>;
pub fn as_string(&self) -> Option<String>;pub const fn from_bool(b: bool) -> JsValue;
pub fn from_f64(n: f64) -> JsValue;
pub fn from_str(s: &str) -> JsValue;
也就是說,wasm_bindgen::JsValue
中,只關(guān)心布爾值,字符串和數(shù)字,而數(shù)字在rust中使用的是f64,即rust std中支持的容量最大,精度最高的數(shù)字。JsValue代表了Javascript環(huán)境中的數(shù)據(jù)。因此,了解這一點(diǎn),我們就可以自由的進(jìn)行Javascript和Rust的數(shù)據(jù)交換了。
關(guān)于as
在上面的代碼中,我們通過rust的as
關(guān)鍵字,將f64
數(shù)字類型轉(zhuǎn)換成了u32
數(shù)字類型。
在Rust中,as關(guān)鍵字可以用于類型轉(zhuǎn)換,將一個(gè)類型轉(zhuǎn)換為另一個(gè)類型,這里的類型必須原始類型(primitive types),但顯然不是指所有的原始類型。
什么是原始類型呢?原始類型是Rust語言的基本的數(shù)據(jù)類型,它們是語言的一部分。Rust語言的原始類型包括一下幾種:
布爾類型(bool):表示邏輯值,只能是true或false。
字符類型(char):表示單個(gè)Unicode字符。
整數(shù)類型(integer):包括有符號(hào)整數(shù)(i8、i16、i32、i64、isize)和無符號(hào)整數(shù)(u8、u16、u32、u64、usize)。
浮點(diǎn)數(shù)類型(floating-point):包括單精度浮點(diǎn)數(shù)(f32)和雙精度浮點(diǎn)數(shù)(f64)。
元組類型(tuple):可以包含多個(gè)不同類型的值。
數(shù)組類型(array):包含固定長(zhǎng)度的相同類型的值。
切片類型(slice):對(duì)數(shù)組的引用,可以動(dòng)態(tài)指定長(zhǎng)度。
指針類型(pointer):包括原始指針(const T和mut T)和引用(&T)。
在我們的問題場(chǎng)景中,我們用as
將f64
轉(zhuǎn)換成了u32
。難道還能將tuple
轉(zhuǎn)換成u32
不成,顯然是不可能的。還好編譯器會(huì)給出提示。
let num1 = (-33, -5);let num: u32 = num1 as u32;
報(bào)錯(cuò):
3 | let num: u32 = num1 as u32;| ^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
其實(shí)在這里,我用as
關(guān)鍵字是迫不得已的。因?yàn)槲覜]有在u32
這個(gè)類型上找到impl TryFrom<f64> for u32
這樣的方法。那將f64類型的數(shù)據(jù)轉(zhuǎn)換成u32類型的數(shù)據(jù),編譯器沒有報(bào)錯(cuò),是不是就意味著沒有問題呢?在我們的問題場(chǎng)景中,應(yīng)該是沒有問題的。但是從數(shù)據(jù)本身的角度,是有問題的。
fn main() {let num: f64 = -323.3;let num1: u32 = num as u32;println!("numbers:{}, {}", num, num1);
}
打印結(jié)果如下:
numbers:-323.3, 0
我想你應(yīng)該總結(jié)處理這里的規(guī)律了吧,再看看下面這段就讓你大跌眼鏡了:
fn main() {let num: i32 = -3;let num1: u32 = num as u32;println!("numbers:{}, {}", num, num1);
}
按照之前的f64
到u32
的經(jīng)驗(yàn),打印的結(jié)果應(yīng)該是:-3, 0,對(duì)吧?
錯(cuò),結(jié)果也讓我嚇一跳:
numbers:-3, 4294967293
而u32
的最大數(shù)值是:4294967295。
這里的水有多深,我就不往下說了,我怕淹死在這里,哈哈。
正確的做法是:
fn main() {let num: i32 = -3;let num1: u32 = u32::try_from(num).unwrap_or_else(|_| 0);println!("numbers:{}, {}", num, num1);
}
所以,關(guān)于使用as
來轉(zhuǎn)換數(shù)據(jù),如果類型本身實(shí)現(xiàn)了TryFrom<T> for ...
,那么就不要使用as
來進(jìn)行類型轉(zhuǎn)換。
總結(jié)
在基于wasm_bindgen的WebAssembly開發(fā)過程中,JsValue與Rust原始數(shù)據(jù)類型之間的轉(zhuǎn)換會(huì)是家常便飯。對(duì)于JsValue來說,它只關(guān)心布爾值,字符串和數(shù)字,分別對(duì)應(yīng)Rust中的bool
,String
和f64
。f64
與其它Rust數(shù)字之間的轉(zhuǎn)換需要依賴as
關(guān)鍵字。但是,如果數(shù)字類型實(shí)現(xiàn)了TryFrom<T>
這個(gè)trait,就不要使用as
關(guān)鍵字來進(jìn)行轉(zhuǎn)換。
今天就到這里,歡迎大家留言交流。