[譯] 前端組件設計原則

原文地址:Front end component design principles

原文作者:Andrew Dinihan

文中示例代碼:傳送門

限于個人能力,如有錯漏之處,煩請不吝賜教。

前言

我在最近的工作中開始使用 Vue 進行開發,但是我在上一家公司積累了三年以上 React 開發經驗。雖然在兩種不同的前端框架之間進行切換確實需要學習很多,但是二者之間在很多基礎概念、設計思路上是相通的。其中之一就是組件設計,包括組件層次結構設計以及組件各自的職責劃分。

組件是大多數現代前端框架的基本概念之一,在 React 和 Vue 以及 Ember 和 Mithril 等框架中均有所體現。組件通常是由標記語言、邏輯和樣式組成的集合。它們被創建的目的就是作為可復用的模塊去構建我們的應用程序。

類似于傳統 OOP 語言中 class 的設計,在設計組件的時候需要考慮到很多方面,以便它們可以很好的復用,組合,分離和低耦合,但是功能可以比較穩定的實現,即使是在超出實際測試用例范圍的情況下。這樣的設計說起來容易做起來卻很難,因為現實中我們往往沒有足夠的時間按照最優的方式去做。

方法

在本文中,我想介紹一些組件相關的設計概念,在進行前端開發時應該考慮這些概念。我認為最好的方法是給每個概念一個簡潔精煉的名字,然后逐一解釋每個概念是什么以及為什么重要,對于比較抽象概念的會舉一些例子來幫助理解。

以下這個列表并不是不全面也不完整,但我注意到的只有 8 件事情值得一提,對于那些已經可以編寫基本組件但想要提高他們的技術設計技能的人來說。所以這是列表: 以下列舉的這個列表僅僅是是我注意到的 8 個方面,當然組件設計還有其他一些方面。在此我只是列舉出來我認為值得一提的。

對于已經掌握基本的組件設計并且想要提高自身的組件設計能力的開發者,我認為以下 8 項是我認為值得去注意的,當然這并不是組件設計的全部。

  1. 層次結構和 UML 類圖
  2. 扁平化、面向數據的 state/props
  3. 更加純粹的 State 變化
  4. 低耦合
  5. 輔助代碼分離
  6. 提煉精華
  7. 及時模塊化
  8. 集中/統一的狀態管理

請注意,代碼示例可能有一些小問題或有點人為設計。但是它們并不復雜,只是想通過這些例子來幫助更好的理解概念。

層次結構和類圖

應用內的組件共同形成組件樹, 而在設計過程中將組件樹可視化展示可以幫助你全面了解應用程序的布局。一個比較好的展示這些的辦法就是組件圖。

UML 中有一個在 OOP 類設計中經常使用的類型,稱為 UML 類圖。類圖中顯示了類屬性、方法、訪問修飾符、類與其他類的關系等。雖然 OOP 類設計和前端組件設計差異很大,但是通過圖解輔助設計的方法值得參考。對于前端組件,該圖表可以顯示:

  • State
  • Props
  • Methods
  • 與其他組件的關系( Relationship to other components )

因此,讓我們看一下下面這個基礎表組件的組件層次圖,該組件的渲染對象是一個數組。該組件的功能包括顯示總行數、標題行和一些數據行,以及在單擊其單元格標題格時對該列進行排序。在它的 props 中,它將傳遞列列表(具有屬性名稱和該屬性的人類可讀版本),然后傳遞數據數組。我們可以添加一個可選的'on row click'功能來進行測試。

雖然這樣的事情可能看起來有點多,但是它具有許多優點,并且在大型應用程序開發設計中所需要的。這樣會帶來的一個比較重要的問題是它會需要你在開始 codeing 之前就需要考慮到具體細節的實現,例如每個組件需要什么類型的數據,需要實現哪些方法,所需的狀態屬性等等。

一旦你對如何構建一個組件(或一組組件)的整體有大概的思路,就會很容易認為當自己真正開始編碼實現時,它會如自己所期望的按部就班的完成,但事實上往往會出現一些預料之外的事情, 當然你肯定不希望因此去重構之前的某些部分,或者忍受初始設想中的缺點并因此擾亂你的代碼思路。而這些類圖的以下優點可以幫助你有效的規避以上問題,優點如下:

  1. 一個易于理解的組件組成和關聯視圖
  2. 一個易于理解的應用程序 UI 層次結構的概述
  3. 一個結構數據層次及其流動方式的視圖
  4. 一個組件功能職責的快照
  5. 便于使用圖表軟件創建

順帶一提,上圖并不是基于某些官方標準,比如 UML 類圖,它是我基本上創建的一套表達規則。例如,在 props 、方法的參數和返回值的數據類型定義聲明都是基于 Typescript 語法。我還沒有找到書寫前端組件類圖的官方標準,可能是由于前端 Javascript 開發的相對較新且生態系統不夠完善所致,但如果有人知道主流標準,請在回復中告訴我!

扁平的,面向數據的 state/props

在 state 和 props 頻繁被 watch 和 update 的情況下,如果你有使用嵌套數據,那么你的性能可能會受到影響,尤其是在以下場景中,例如一些因為淺對于而觸發的重新渲染;在涉及 immutability 的庫中,比如 React,你必須創建狀態的副本而不是像在 Vue 中那樣直接更改它們,并且使用嵌套數據這樣做可能會創建笨拙,丑陋的代碼。

即使使用展開運算符,這種寫法也并不夠優雅。扁平 props 也可以很好地清除組件正在使用的數據值。如果你傳給組件一個對象但是你并不能清楚的知道對象內部的屬性值,所以找出實際需要的數據值是來自組件具體的屬性值則是額外的工作。但如果 props 足夠扁平化,那么起碼會方便使用和維護。

state / props 還應該只包含組件渲染所需的數據。You shouldn’t store entire components in the state/props and render straight from there.

(此外,對于數據繁重的應用程序,數據規范化可以帶來巨大的好處,除了扁平化之外,你可能還需要考慮一些別的優化方法)。

更加純粹的 State 變化

對 state 的更改通常應該響應某種事件,例如用戶單擊按鈕或 API 的響應。此外它們不應該因為別的 state 的變化而做出響應,因為 state 之間這種關聯可能會導致難以理解和維護的組件行為。state 變化應該沒有副作用。

如果你濫用watch而不是有限考慮以上原則,那么在 Vue 的使用中就可能由此引發的問題。我們來看一個基本的 Vue 示例。我正在研究一個從 API 獲取一些數據并將其呈現給表的組件,其中排序,過濾等功能都是后端完成的,因此前端需要做的就是 watch 所有搜索參數,并在其變化時觸發 API 調用。其中一個需要 watch 的值是“zone”,這是一個過濾器。當更改時,我們想要使用過濾后的值重新獲取服務端數據。watcher 如下:

你會發現一些奇怪的東西。如果他們超出了結果的第一頁,我們重置頁碼然后結束?這似乎不對,如果它們不在第一頁上,我們應該重置分頁并觸發 API 調用,對吧?為什么我們只在第 1 頁上重新獲取數據?實際上原因是這樣,讓我們來看下完整的 watch:

當分頁改變時,應用首先會通過 pagination 的處理函數重新獲取數據。因此,如果我們改變了分頁,我們并不需要去關注數據更新這段邏輯。

讓我們一下來考慮以下流程:如果當前頁面超出了第 1 頁并且更改了 zone,而這個變化會觸發另一個狀態(pagination)發生變化,進而觸發 pagination 的觀察者重新請求數據。這樣并不是預料之中的行為,而且產生的代碼也不夠直觀。

解決方案是改變頁碼這個行為的事件處理函數(不是觀察者,用戶更改頁面的實際處理函數)應該更改頁面值觸發 API 調用請求數據。這也將消除對觀察者的需求。通過這樣的設置,直接從其他地方改變分頁狀態也不會導致重新獲取數據的副作用。

雖然這個例子非常簡單,但不難看出將更復雜的狀態更改關聯在一起會產生令人難以理解的代碼,這些代碼不僅不可擴展并且是調試的噩夢。

松耦合

組件的核心思想是它們是可復用的,為此要求它們必須具有功能性和完整性。“耦合”是指實體彼此依賴的術語。松散耦合的實體應該能夠獨立運行,而不依賴于其他模塊。就前端組件而言,耦合的主要部分是組件的功能依賴于其父級及其傳遞的 props 的多少,以及內部使用的子組件(當然還有引用的部分,如第三方模塊或用戶腳本)。

緊密耦合的組件往往更不容易被復用,當它們作為特定父組件的子項時,就很難正常工作,當父組件的一個子組件或一系列子組件只能在該父組件才能夠正常發揮作用時,就會使得代碼寫的很冗余。因為父子組件別過度的關聯在一起了。

在設計組件時,你應該考慮到更加通用的使用場景,而不僅僅只是為了滿足最開始某個特定場景的需求。雖然一般來說組件最初都是出于特定目的進行設計,但沒關系,如果在設計它們站在更高的角度去看待,那么很多組件將具有更好的適用性。

讓我們看一個簡單的 React 示例,你想在寫出一個帶有一個 logo 的鏈接列表,通過連接可以訪問特定的網站。最開始的設計可能是并沒有跟內容合理的進行解耦。下面是最初的版本:

雖然這這樣會滿足預期的使用場景,但卻很難被復用。如果你想要更改鏈接地址該怎么辦?你必須重新復制一份相同代碼,并且手動去替換鏈接地址。而且, 如果你要去實現一個用戶可以更改連接的功能,那么意味著不可能將代碼寫“死”,也不能期望用戶去手動修改代碼,那么讓我們來看一下復用性更高的組件應該如何設計:

在這里我們可以看到,雖然它的原始鏈接和 logo 具有默認值,但我們可以通過 props 傳入的值去覆蓋掉默認值。讓我們來看一下它在實際中的使用:

并不需要重新編寫新的組件!如果我們解決上文中用戶可以自定義鏈接的使用場景,可以考慮動態構建鏈接數組。此外,雖然在這個具體的例子中沒有解決,但我們仍然可以注意到這個組件沒有與任何特定的父/子組件建立密切關聯。它可以在任何需要的地方呈現。改進后的組件明顯比最初版本具有更好的復用性。

如果不是要設計需要服務于特定的一次性場景的組件,那么設計組件的最終目標是讓它與父組件松散耦合,呈現更好的復用性,而不是受限于特定的上下文環境。

輔助代碼分離

這個可能不那么的偏理論,但我仍然認為這很重要。與你的代碼庫打交道是軟件工程的一部分,有時一些基本的組織原則可以使事情變得更加順暢。在長時間與代碼相處的過程中,即使改變一個很小的習慣也可以產生很大的不同。其中一個有效的原則就是將輔助代碼分離出來放在特定的地方,這樣你在處理組件時就不必考慮這些。以下列舉一些方面:

  • 配置代碼
  • 假數據
  • 大量非技術說明文檔

因為在嘗試處理組件的核心代碼時,你不希望看到與技術無關的一些說明(因為會多滾動幾下鼠標滾輪甚至打斷思路)。在處理組件時,你希望它們盡可能通用且可重用。查看與組件當前上下文相關的特定信息可能會使得設計出來的組件不易與具體業務解耦。

提煉精華

雖然這樣做起來可能具有挑戰性,但開發組件的一個好方法是使它們包含渲染它們所需的最小 Javascript。一些無關緊要的東西,比如數據獲取,數據整理或事件處理邏輯,理想情況下應該將通用的部分移入外部 js 或或者放在共同的祖先中。

單獨從組件分的“視圖”部分來看,即你看到的內容(html 和 樣式)。其中的 Javascript 僅用于幫助渲染視圖,可能還有一些針對特定組件的邏輯(例如在其他地方使用時)。除此之外的任何事情,例如 API 調用,數值的格式化(例如貨幣或時間)或跨組件復用的數據,都可以移動外部的 js 文件中。讓我們看一下 Vue 中的一個簡單示例,使用嵌套列表組件。我們可以先看下下面這個有問題的版本。

這是第一個層級:

這是嵌套列表組件:

在這里我們可以看到此列表的兩個層級都具有外部依賴關系,最上層導引入外部 js 文件中的函數和 JSON 文件的數據,嵌套組件連接到 Vuex 存儲并使用 axios 發送請求。它們還具有僅適用于當前場景的嵌入功能(最上層中源數據處理和嵌套列表的中度 click 時間的特定響應功能)。

雖然這里采用了一些很好的通用設計技術,例如將通用的 數據處理方法移動到外部腳本而不是直接將函數寫死,但這樣仍然不具備很高的復用性。如果我們是從 API 的響應中獲取數據,但是這個數據跟我們期望的數據結構或者類型不同的時候要怎么辦?或者我們期望單擊嵌套項時有不同的行為?在遇到這些需求的場景下,這個組件無法被別的組件直接引用并根據實際需求改變自身的特性。

讓我們看看我們是否可以通過提升數據并將事件處理作為 props 傳遞來解決這個問題,這樣組件就可以簡單地呈現數據而不會封裝任何其他邏輯。

這是改進后的第一級別:

而新的第二級:

使用這個新列表,我們可以獲得想要的數據,并定義了嵌套列表的 onClick 處理函數,以便在父級中傳入任何我們想要的操作,然后將它們作為 props 傳遞給頂級組件。這樣,我們可以將導入和邏輯留給單個根組件,所以不需要為了能夠在新的場景下使用去重新再實現一個類似組件。

有關此主題的簡短文章可以在這里找到。它由 Redux 的作者 Dan Abramov 編寫,雖然是用 React 舉例說明。但是組件設計的思想是通用的。

及時模塊化

我們在實際進行組件抽離工作的時候,需要考慮到不要過度的組件化,誠然將大塊代碼變成松散耦合且可用的部分是很好的實踐,但是并不是所有的頁面結構(HTML 部分)都需要被抽離成組件,也不是所有的邏輯部分都需要被抽出到組件外部。

在決定是否將代碼分開時,無論是 Javascript 邏輯還是抽離為新的組件,都需要考慮以下幾點。同樣,這個列表并不完整,只是為了讓你了解需要考慮的各種事項。(記住,僅僅因為它不滿足一個條件并不意味著它不會滿足其他條件,所以在做出決定之前要考慮所有條件):

  1. 是否有足夠的頁面結構/邏輯來保證它? 如果它只是幾行代碼,那么最終可能會創建更多的代碼來分隔它,而不僅僅是將代碼放入其中。
  2. 代碼重復(或可能重復)? 如果某些東西只使用一次,并且服務于一個不太可能在其他地方使用的特定用例,那么將它嵌入其中可能會更好。如果需要,你可以隨時將其分開(但不要在需要做這些工作的時候將此作為偷懶的借口)。
  3. 它會減少需要書寫的模板嗎? 例如,假設你想要一個帶有特定樣式的 div 屬性結構和一些靜態內容/功能的組件,其中一些可變內容嵌套在內部。通過創建可重用的包裝器(與 React 的 HOC 或 Vue 的 slot 一樣),你可以在創建這些組件的多個實例時減少模板代碼,因為你不需要重新再寫外部的包裝代碼。
  4. 性能會收到影響嗎? 更改 state/props 會導致重新渲染,當發生這種情況時,你需要的是 只是重新去渲染經過 diff 之后得到的相關元素節點。在較大的、關聯很緊密的組件中,你可能會發現狀態更改會導致在不需要它的許多地方重新呈現,這時應用的性能就可能會開始受到影響。
  5. 你是否會在測試代碼的所有部分時遇到問題? 我們總是希望能夠進行充分的測試,比如對于一個組件,我們會期望它的正常工作不依賴特定的用例(上下文),并且所有 Javascript 邏輯都按預期工作。當元素具有某個特定假設的上下文或者分別將一大堆邏輯嵌入到單個函數中時,這樣將會很難滿足我們的期望。如果測試的組件是具有比較大模板和樣式的單個巨型組件,那么組件的渲染測試也會很難進行。
  6. 你是否有一個明確的理由? 在分割代碼時,你應該考慮它究竟實現了什么。這是否允許更松散的耦合?我是否打破了一個邏輯上有意義的獨立實體?這個代碼是否真的可能在其他地方被重復使用?如果你不能清楚地回答這個問題,那最好先不要進行組件抽離。因為這樣可能導致一些問題(比如拆解掉原本某些潛在的耦合關系)。
  7. 這些好處是否超過了成本? 分離代碼不可避免地需要時間和精力,其數量根據具體情況而變化,并且在最終做出此決定時會有許多因素(例如此列表中列舉出來的一些)。一般來說,進行一些對抽象的成本和收益研究可以幫助更快更準確去做出是否需要組件化的決策。最后,我提到了這一點,因為如果我們過分關注優勢,就很容易忘記達成目標所需要做的努力,所以在做出決定以前需要權衡這兩個方面。

集中/統一的狀態管理

許多大型應用程序使用 Redux 或 Vuex 等狀態管理工具(或者具有類似 React 中的 Context API 狀態共享設置)。這意味著他們從 store 獲得 props 而不是通過父級傳遞。在考慮組件的可重用性時,你不僅要考慮直接的父級中傳遞而來的 props,還要考慮 從 store 中獲取到的 props。如果你在另一個項目中使用該組件,則需要在 store 中使用這些值。或許其他項目根本不使用集中存儲工具,你必須將其轉換為從父級中進行 props 傳遞 的形式。

由于將組件掛接到 store(或上下文)很容易并且無論組件的層次結構位置如何都可以完成,因此很容易在 store 和 web 應用的組件之間快速創建大量緊密耦合(不關心組件所處的層級)。通常將組件與 store 進行關聯只需簡單幾行代碼。但是請注意一點,雖然這種連接(耦合)更方便,但它的含義并沒有什么不同,你也需要考慮盡量符合如同在使用父級傳遞方式時的要點。

最后

我想提醒大家的是:應該更注重以上這些組件設計的原則和你已知的一些最佳實踐在實際中的應用。雖然你應該盡力維護良好的設計,但是不要為了包裝 JIRA ticket 或一個取消請求而有損代碼完整性,同時總是把理論置于現實世界結果之上的人也往往會讓他們的工作受到影響。大型軟件項目有許多活動部分,軟件工程的許多方面與編碼沒有特別的關系,但仍然是不可或缺的,例如遵守最后期限和處理非技術期望。

雖然充分的準備很重要,應該成為任何專業軟件設計的一部分,但在現實世界中,切實的結果才是最為重要的。當你被雇用來實際創造一些東西時,如果在最后期限到來之前,你有的只是一個如何構建完美產品的驚人計劃,但卻沒有實際的成果,你的雇主可能不會太高興吧?此外,軟件工程中的東西很少完全按計劃進行,因此過度具體的計劃往往會在時間使用方面得到適得其反的效果。

此外,組件規劃和設計的概念也適用于組件重構。雖然用了 50 年的時間來計劃一切令人難以忍受的細節,然后從一開始就完美地編寫它就會很好,回到現實世界,我們往往會遇到這種情況,即為了趕進度而不能使代碼達到完美的預期。然而,一旦我們有了空閑時間,那么一個推薦的做法就是回過頭來重構早期不夠理想的的代碼,這樣它就可以作為我們向前發展的堅實基礎。

在一天結束時,雖然你的直接責任可能是“編寫代碼”,但你不應忽視你的最終目標,即建立一些東西。創建產品。為了產生一些你可以引以為豪的東西并幫助別人,即使它在技術上并不完美,永遠記得找到一個平衡點。不幸的是,在一周內每天 8 小時盯著眼前的代碼會使得眼界和角度變得更為“狹窄”,這個時候你需要的你是退后一步,確保你不要為了一顆樹而失去整個森林。

轉載于:https://juejin.im/post/5c49cff56fb9a049bd42a90f

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/252461.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/252461.shtml
英文地址,請注明出處:http://en.pswp.cn/news/252461.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

imu_utils標定imu問題解決

在編譯過程中遇到的一些問題可以參照這個女生的文章 https://blog.csdn.net/fang794735225/article/details/92804030 下面是imu_utils的主頁,可以下載代碼,也有使用步驟 https://github.com/gaowenliang/imu_utils 我下載了imu_utils主頁最后面提供…

術語-服務:PaaS

ylbtech-術語-服務:PaaSPaaS是Platform-as-a-Service的縮寫,意思是平臺即服務。 把服務器平臺作為一種服務提供的商業模式。通過網絡進行程序提供的服務稱之為SaaS(Software as a Service),而云計算時代相應的服務器平臺或者開發環境作為服務…

PostgreSQL安裝和簡單配置

PostgreSQL安裝與使用 目錄 依賴包的安裝源碼編譯和安裝初始化數據庫集簇簡單配置依賴包安裝 PostgreSQL源碼安裝依賴以下四個軟件包 readline zlib flex bison 在Ubuntu中可是應用以下命令直接進行安裝: sudo apt-get install libreadline6 libreadline6-dev zlib1…

1.App瘦身經驗總結

為什么apk越來越大? 1.項目不斷發展,功能越多,代碼量增加的同時,資源文件也在不斷的增多2.app支持的主流dpi越來越多,如ldpi、mdpi、hdpi、xh xxh xxxh等等,間接導致資源增多3.引入的第三方sdk或開源庫越來…

研究相機和IMU坐標系變換

剛開始錄制的數據時沒有考慮相機和IMU之間的坐標變換,但是后來發現跟蹤效果不好,去查驗imu數據時,發現,我采集保存的imu數據格式沒有和euroc數據集中的imu數據保存格式統一,所以需要研究的是在euroc用于數據采集的設備…

第五天:Swift拖動 item 重排 CollectionView

參考鏈接:https://www.jianshu.com/p/96f956f1479e 1 import UIKit2 3 enum VC: String {4 case ViewController5 case CollectionViewController6 7 func segueIdentifier() -> String {8 switch self {9 case .ViewController:10 …

MIT Kimera閱讀筆記

這兩天在調研SLAM的最新算法,找到了2019CVPR上的一篇文章,出自于MIT,因為要給其他同事講解,所以就把文章的重點內容在我個人理解的情況下翻譯了出來,有理解不到位的還請各位大佬多多批評指正。 最后附上了Delaunay Tri…

C#中的ForEach

public void ForEach(Action<T> action) 針對List<T>集合中的每個元素執行操作Action<T> action,Action<T>是只接受一個類型為T的傳入參數返回值為void的委托,對于泛型List<T>來說,Action<T>中的類型與List<T>中的類型是相同的.acti…

哈希映射

哈希來源問題&#xff1a;關于統計一個字符串集合中&#xff0c;求出現次數最多的字符串思路&#xff1a;建立一個哈希映射&#xff08;HashMap&#xff09;&#xff0c;其鍵為"字符串"&#xff0c;值為"字符串出現次數"&#xff0c;然后遍歷字符串集合&am…

1月28日云棲精選夜讀 | 終于等到你!阿里正式向 Apache Flink 貢獻 Blink 源碼

如同我們去年12月在 Flink Forward China 峰會所約&#xff0c;阿里巴巴內部 Flink 版本 Blink 將于 2019 年 1 月底正式開源。今天&#xff0c;我們終于等到了這一刻。 熱點熱議 終于等到你&#xff01;阿里正式向 Apache Flink 貢獻 Blink 源碼 作者&#xff1a;技術小能手 發…

ZOJ-3537

題目大意&#xff1a;給你一個n (n<300) 邊形&#xff0c;給出它所有的頂點坐標&#xff0c;讓你把它劃分成n-2個三角形的花費最小值&#xff0c;頂點 a 和 b 相連的花費為 abs(a.xb.x)*abs(a.yb.y)。 如果是凹多邊形輸出無解。 思路&#xff1a;先跑個凸包判斷是不是凸多邊…

你會等待還是離開(大理)---寫的一個推文

你會等待還是離開 -----出發和遇見大理 上關花鬧 下關風薰 蒼山雪寂 洱海月遲 但聞肆季弦雀起 才吹小雨又需晴 現實很調皮&#xff0c;很容易就讓人沒有力氣&#xff0c;就像變與不變&#xff0c;并不復雜&#xff0c;也不遙遠&#xff0c;一個寒假的距離&#xff0c;一句話的力…

sudo rosdep init ERROR: cannot download default sources list from: https://raw.githubusercontent.com

安裝上ros無法進行rosdep init.解決方法如下&#xff1a;https://zhuanlan.zhihu.com/p/77483614 因此&#xff0c;在/usr/lib/python2.7/dist-packages/rosdep2/sources_list.py中頂部直接插入兩行代碼取消SSL驗證 import ssl ssl._create_default_https_context ssl._crea…

YodaOS: 一個屬于 Node.js 社區的操作系統

開發四年只會寫業務代碼&#xff0c;分布式高并發都不會還做程序員&#xff1f; >>> 大家好&#xff0c;很開心在這里宣布 YodaOS開源了。他將承載 Rokid 4年以來對于人工智能和語音交互領域的沉淀&#xff0c;并選擇 Node.js 作為操作系統的一等開發公民&#xff0…

Android頂部粘至視圖具體解釋

不知從某某時間開始&#xff0c;這樣的效果開始在UI設計中流行起來了。讓我們先來看看效果&#xff1a;大家在支付寶、美團等非常多App中都有使用。要實現這個效果&#xff0c;我們能夠來分析下思路&#xff1a;我們肯定要用2個一樣的布局來顯示我們的粘至布局。一個是正常的、…

在實際項目開發中keil的調試方法

轉載2015-06-14 20:23:04 一.在keilc的調試狀態下&#xff0c;如何觀察各個片內外設的運行狀態&#xff1f;如何修改它們的設置&#xff1f;? 在調試狀態下&#xff0c;點擊Peripherals菜單下的不同外設選項命令&#xff0c;就會顯示或隱藏對應外設的觀察窗口。 在程序運行時&…

slam 常用數據集的幀率

1. kitti數據集的幀率約約為10fps,圖像分辨率為1241x376 2. Euroc數據集的幀率約為20fps,圖像分辨率為752x480 3.TUM數據集的幀率約為30fps, 圖像分辨率為640x360 zed相機獲取的HD圖像的分辨率為1280x720p,獲取的VGA圖像分辨率為672x376,mynt相機獲取的VGA圖像的分辨率為640x…

小李飛刀:用python刷題ing....

叨逼叨 默認每天都要刷兩道題。今天目標已完成。 第一題 26. 刪除排序數組中的重復項難度&#xff1a;簡單類型&#xff1a;數組 給定一個排序數組&#xff0c;你需要在原地刪除重復出現的元素&#xff0c;使得每個元素只出現一次&#xff0c;返回移除后數組的新長度。不要使用…

【Log4J】

學習mybatis中用到了Log4J 在此記錄下 引入 引入Maven配置 <!-- https://mvnrepository.com/artifact/log4j/log4j --><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version></de…

VI-ORB環境配置

參考博客:https://blog.csdn.net/qq_38589460/article/details/82559816 https://blog.csdn.net/Robot_Starscream/article/details/90245456 本機安裝的是opencv3.0 在Examples/ROS/ORB-VIO以及/VI-ORB/src/LearnVIORB-RT下的CMakeLists.txt都要進行修改 將find_package(O…