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 亚洲一区二区三区免费看,日韩中文字幕高清在线专区,久久夜夜视频

          整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          FlexSearch.js:快速、零依賴的Javas

          FlexSearch.js:快速、零依賴的Javascript全文搜索庫

          句話介紹

          Web端最快且最具內存靈活性的全文搜索庫,零依賴性。

          Github地址:https://github.com/nextapps-de/flexsearch

          github截圖

          中文翻譯介紹

          在原始搜索速度方面,FlexSearch優于每一個搜索庫,并提供靈活的搜索功能,如多字段搜索,語音轉換或部分匹配。 根據使用的選項,它還提供最高內存效率的索引。 FlexSearch引入了一種新的評分算法,稱為“上下文索引”,基于預先評分的詞典字典體系結構,與其他庫相比,實際執行的查詢速度提高了1,000,000倍。 FlexSearch還為您提供非阻塞異步處理模型以及Web工作者,以通過專用平衡線程并行地對索引執行任何更新或查詢。

          安裝

          可以到官網下載經過壓縮的js文件或者使用cdn,也可以使用npm安裝

          //使用最新版:
          <script src="https://cdn.jsdelivr.net/gh/nextapps-de/flexsearch@master/dist/flexsearch.min.js"></script>
          //或者特定版
          <script src="https://cdn.jsdelivr.net/gh/nextapps-de/flexsearch@0.3.51/dist/flexsearch.min.js"></script>
          
          • npm安裝
          npm install flexsearch
          

          用法

          • 創建一個索引
          var index=new FlexSearch();
          //或者
          var index=FlexSearch.create();
          //或者給定一個默認值
          var index=new FlexSearch("speed");
          //自定義配置
          var index=new FlexSearch({
           // default values:
           encode: "balance",
           tokenize: "forward",
           threshold: 0,
           async: false,
           worker: false,
           cache: false
          });
          //在或者
          var index=new FlexSearch("memory", {
           encode: "balance",
           tokenize: "forward",
           threshold: 0
          });
          
          • 將文本添加到索引

          Index.add(id, string)

          index.add(10025, "John Doe");
          
          • 搜索

          Index.search(string | options, <limit>, <callback>)

          index.search("John");
          
          • 限制數量
          index.search("John", 10);
          
          • 異步搜索
          //基于回調函數
          index.search("John", function(result){
           
           // array of results
          });
          //基于Promise
          index.search("John").then(function(result){
           
           // array of results
          });
          //es6寫法
          async function search(query){
           const result=await index.search(query);
           
           // ...
          }
          
          • 自定義搜索
          index.search({
           query: "John",
           limit: 1000,
           threshold: 5, // >=threshold
           depth: 3, // <=depth
           callback: function(results){
           // ...
           }
          });
          //或者
          index.search("John", {
           limit: 1000,
           threshold: 5,
           depth: 3
           
          }, function(results){
           
           // ....
          });
          
          • 分頁
          var response=index.search("John Doe", {
           limit: 5,
           page: true
          });
          index.search("John Doe", {
           limit: 10,
           page: response.next
          });//下一頁
          
          • 建議

          獲取查詢建議

          index.search({
           query: "John Doe",
           suggest: true
          });
          

          啟用建議后,將填寫所有結果(直到限制,默認為1000),并按相關性排序相似的匹配。

          • 更新

          Index.update(id, string)

          index.update(10025, "Road Runner");
          
          • 移除

          Index.remove(id)

          index.remove(10025);
          
          • 重置索引
          index.clear();
          
          • 銷毀
          index.destroy();
          
          • 重新初始化

          Index.init(<options>)

          //使用相同配置重新初始化
          index.init();
          //使用新的配置重新初始化
          index.init({
           /* options */
          });
          //重新初始化會銷毀舊的索引
          
          • 獲取長度
          var length=index.length;
          
          • 獲取寄存器
          var index=index.index;
          

          寄存器的格式為“@”+ id

          請不要手動修改寄存器,用作只讀即可

          • 添加自定義匹配器

          FlexSearch.registerMatcher({REGEX: REPLACE})

          • 為所有實例添加全局匹配:
          FlexSearch.registerMatcher({
           '?': 'a', // replaces all '?' to 'a'
           'ó': 'o',
           '[?úù]': 'u' // replaces multiple
          });
          
          • 為特定實例添加私有匹配:
          index.addMatcher({
           '?': 'a', // replaces all '?' to 'a'
           'ó': 'o',
           '[?úù]': 'u' // replaces multiple
          });
          
          • 添加定制編碼

          通過在索引創建/初始化期間傳遞函數來分配自定義編碼

          var index=new FlexSearch({
           encode: function(str){
           
           // do something with str ...
           
           return str;
           }
          });
          

          編碼器函數獲取一個字符串作為參數,返回修改后的字符串

          直接調用自定義編碼器:

          var encoded=index.encode("sample text");
          
          • 注冊全局編碼

          FlexSearch.registerEncoder(name, encoder)

          所有實例都可以共享/使用全局編碼

          FlexSearch.registerEncoder("whitespace", function(str){
           return str.replace(/\s/g, "");
          });
          

          初始化索引并分配全局編碼

          var index=new FlexSearch({ encode: "whitespace" });
          

          直接調用全局編碼

          var encoded=FlexSearch.encode("whitespace", "sample text");
          
          • 混合/擴展多個編碼
          FlexSearch.registerEncoder('mixed', function(str){
           
           str=this.encode("icase", str); // built-in
           str=this.encode("whitespace", str); // custom
           
           // do something additional with str ...
           
           return str;
          });
          
          • 添加自定義標記

          在創建/初始化期間定義私有自定義標記

          var index=new FlexSearch({
           tokenize: function(str){
           return str.split(/\s-\//g);
           }
          });
          
          • 添加特定于語言的詞干分析器和/或過濾器

          Stemmer: several linguistic mutations of the same word (e.g. "run" and "running")

          Filter: a blacklist of words to be filtered out from indexing at all (e.g. "and", "to" or "be")

          在創建/初始化期間分配私有自定義詞干分析器或過濾器

          var index=new FlexSearch({
           stemmer: {
           
           // object {key: replacement}
           "ational": "ate",
           "tional": "tion",
           "enci": "ence",
           "ing": ""
           },
           filter: [ 
           
           // array blacklist
           "in",
           "into",
           "is",
           "isn't",
           "it",
           "it's"
           ]
          });
          

          使用自定義詞干分析器

          var index=new FlexSearch({
           stemmer: function(value){
           // apply some replacements
           // ...
           
           return value;
           }
          });
          

          使用自定義過濾器

          var index=new FlexSearch({
           filter: function(value){
           
           // just add values with length > 1 to the index
           
           return value.length > 1;
           }
          });
          

          或者將詞干分析器/過濾器全局分配給一種語言

          Stemmer作為對象(鍵值對)傳遞,過濾為數組

          FlexSearch.registerLanguage("us", {
           stemmer: { /* ... */ },
           filter: [ /* ... */ ]
          });
          

          或者使用一些預定義的詞干分析器或首選語言的過濾器

          <html>
          <head>
           <script src="js/flexsearch.min.js"></script>
           <script src="js/lang/en.min.js"></script>
           <script src="js/lang/de.min.js"></script>
          </head>
          ...
          

          現在您可以在創建/初始化期間分配內置詞干分析器

          var index_en=new FlexSearch({
           stemmer: "en", 
           filter: "en" 
          });
          var index_de=new FlexSearch({
           stemmer: "de",
           filter: [ /* custom */ ]
          });
          

          在Node.js中,只需要語言包文件即可使用它們

          require("flexsearch.js");
          require("lang/en.js");
          require("lang/de.js");
          

          總結

          本文知識大致翻譯了部分使用方法,更加強大和完整的用法參考官方Github文檔,里面有更加詳細的用法!

          好,本文屬于技術類文章,建議有本領域的技術基礎者閱讀,以便更好地理解。

          這篇文章分兩個步驟講解,如下:

          第一步:什么是 flex + div 呢?

          flex 是CSS的一套布局方案,一個一維布局模型;是Flexible Box的縮寫,意思就算“彈性布局”,理解flex概念使用,記住下面兩點即可:

          1. flex布局的兩根軸線:x軸和y軸(有些會叫主軸與交叉軸、水平線與垂直線,我喜歡用x與y描述更簡潔些)。
          2. flex容器和flex子元素(任何一元素標簽都可以設置為flex容器,而被設置flex容器包裹在內的子元素,就是flex子元素)。

          div 其就是一個普通HTML元素標簽,大部分內容都是可以基于這個元素標簽封裝的,形成一個復用性大,共用性好的新元素標簽。

          第二步:如何使用 flex + div 來繪制作品,哪些場景的作品可以使用?

          首先如何使用,下面我們直接看一個封裝好的例子元素標簽,給拆解出來講解如何使用,其他舉一反三即可:

          圖-1-1

          這是一個普通貨品上架的卡片信息內容,它就是一個flex+div結構繪制,被紅線圈出來,都是一個個的flex+div內容布局,外層定義flex容器,內部就是該flex容器子元素內容,這些內容子元素,都flex布局排列x-y軸方向的信息,簡單吧!所以幾乎大部分的頁面內容都可以使用這flex+div方式可以封裝你的業務標簽組件,以便復用,flex布局元素排列好,設置每個元素的內外邊距、樣式、字體、顏色這些標簽屬性,就看到這樣一個通用的普通組件標簽場景了。

          簡單吧!這就是一個flex+div繪制互聯網作品,商品上架的貨品卡片,多個就復用該標簽組件形成一個列表展示了。

          如下代碼標簽,就是這個貨品使用flex + div方式繪制的,只有你確定了頁面內容flex結構層級,即可快速繪制出來:

          圖-1-2

          哪些場景會用到了,網站、小程序、管理系統等這些互聯網作品基本都會用它的,按業務需求場景去封裝你的作品輸出服務。

          簡單吧!學會flex + div,在你的互聯網產品繪制之路,快速便捷的實戰,無論是自由原創、還是看圖仿制都是可以的,不限制你的想象空間,就像我們畫家一樣,可以自由創作作品,也可看圖,看景創景作品,實際工作是會溝通好場景需求,在去創作,才服務滿足顧客需求意向,以更好去交付獲得收益。

          拜拜!下期再見!

          要: 作者:閑魚技術-意境 Flutter作為一種全新的響應式,跨平臺,高性能的移動開發框架。從開源以來,已經得到越來越多開發者的喜愛。閑魚是最早一批與谷歌展開合作,并在重要的商品詳情頁中使用上線的公司。一路走來,積累了大量的開發經驗。

          Flutter作為一種全新的響應式,跨平臺,高性能的移動開發框架。從開源以來,已經得到越來越多開發者的喜愛。閑魚是最早一批與谷歌展開合作,并在重要的商品詳情頁中使用上線的公司。一路走來,積累了大量的開發經驗。雖然越來越多的技術大牛在flutter世界中弄得風聲水起,但是肯定有很多的flutter小白希望能快速上手,享受flutter編程的樂趣。本文就是面向剛剛踏上futter的同學,從Flutter體系中最基本的一個概念widget入手學習Flutter。希望能助力每一位初學者。

          可能大家要問的第一個問題是為什么從Widget開始?

          從flutter的架構圖中不難看出widget是整個視圖描述的基礎。Flutter 的核心設計思想便是

          即一切即Widget。在flutter的世界里,包括views,view controllers,layouts等在內的概念都建立在Widget之上。widget是flutter功能的抽象描述。所以掌握Flutter的基礎就是學會使用widget開始。

          本文會從大家熟悉的UI繪制視角來介紹flutter組件和布局的基礎知識。首先羅列了UI開發中最為常用,最為基礎的組件。下面逐一進行介紹。

          1 組件篇

          1.1 Text

          Text幾乎是UI開發中最為重要的組件之一了,UI上面文字的展示基本上都要靠Text組件來完成。Flutter提供了原生的Text組件。Text的配置屬性是很豐富的,屬性主要分為兩個部分一個是對齊&顯示控制相關的在Text類的屬性中,另一類是樣式相關的屬性使用單獨的類TextStyle進行控制。跟native控件相比(以android為例),Text的組件基本上提供了同等的能力,并且提供了更加豐富的樣式裝飾能力。詳細的屬性可以參考官方文檔flutter text.(https://docs.flutter.io/flutter/widgets/Text-class.html?spm=a2c4e.11153940.blogcont634392.6.14f56cd4VVp3Nm)

          1.1.1 實踐Coding

          設置文字&文字大小&顏色&行數限制&文本對齊

          效果如下:

          1.2 Image

          圖片也是UI部分開發最為重要的組件之一。在能看圖隨看文字的年代,圖片是頁面展示的重中之重!Flutter同樣原生提供了Image組件。下面重點介紹一下幾個重點:

          1.2.1 縮放

          怎樣設置圖片顯示的縮放方式呢?

          Flutter中的圖片縮放是fit字段來控制的。這是對最終圖片展示效果影響很大的一個參數,也是容易出錯的點。下面逐個分析一下flutter Image組件提供的縮放方式。

          縮放屬性值在BoxFit枚舉中

          下面列出的圖片是flutter官方對各種縮放做的圖片示例。基本上都表述很清楚了,就整理出來供大家查閱。

          1.2.2 圖片獲取

          怎樣從各種來源加載圖片?

          默認的Image組件不能直接顯示圖片,他需要一個ImageProvider來提供具體的圖片資源的(即Image中的image字段需要賦值)。咋一看這確實非常麻煩,但是實際上ImageProvider并不需要完全重新自己實現。在Image類中目前提供了一下幾個實現好的ImageProvider,基本能滿足常見的需求。

          Image同樣支持GIF圖片

          網絡請求Image是大家最常見的操作。這里重點說明兩個點:

          • 緩存

          ImageCache是ImageProvider默認使用的圖片緩存。ImageCache使用的是LRU的算法。默認可以存儲1000張圖片。如果覺得緩存太大,可以通過設置ImageCache的maximumSize屬性來控制緩存圖片的數量。也可以通過設置maximumSizeBytes來控制緩存的大小(默認緩存大小10MB)。

          • CDN優化

          如果想要使用cdn優化,可以通過url增加后綴的方式實現。默認實現中沒有這個點,但是考慮到cdn優化的可觀收益,建議大家利用好這個優化。

          1.2.3 FadeInImage

          在實際開發中,考慮到圖片加載速度可能不能達到預期。所以希望能增加漸入效果&增加placeHolder的功能。Flutter同樣提供的這樣的組件——FadeInImage。

          FadeInImage也提供了從多種渠道加載圖片的能力。這塊跟上面所說差異不大。這里不再贅述。

          1.2.4 實踐Coding

          • 從網絡獲取圖片保持圖片比例并盡可能大的放入

          • 效果如下:

          1.3 Container

          Flutter的設計思想就是完全的widget化。這也就是說連最基本的padding,Center都是widget。設想一下如果每次寫view,連padding,Center都要自己包一個組件是一種怎樣的體驗?作為一個工程師,別給只給我談思想,實際操作的操作效率也同樣非常重要。flutter 官方也意識到了這個問題,他們從實際編寫效率的角提供了一個友好高效的封裝,這就是Container!首先沒有任何疑問,Container 本身也是一個widget。但是他卻提供了對基礎widget的封裝,提高了UI基礎裝飾能力的表達效率。Container類似于android中的ViewGroup。

          相信大部分的屬性大家都會感覺非常親切,結合代碼注釋都比較容易理解,這里就不再贅述。其中需要重點解釋一下的是:Decoration和BoxConstraints。

          1.3.1 裝飾

          Decoration是對Container進行裝飾的描述。其概念類似與android中的shape。一般實際場景中會使用他的子類BoxDecoration。BoxDecoration提供了對背景色,邊框,圓角,陰影和漸變等功能的定制能力。

          需要注意幾個點:

          • BoxDecoration的image屬性相當于設置的是背景圖。但是image會繪制在color 和gradient之上。
          • image是需要一個DecorationImage類的實現。DecorationImage的屬性和Image組件比較類似,可以復用Image組件中的ImageProvider。

          1.3.2 大小

          BoxConstraints其實是對Container組件大小的描述。BoxConstraints屬性比較簡單。如果不太清楚可以研究一下盒子模型。這里有個點需要重點說明一下:

          • 如何表達盡可能大這樣的意思?(類似于android中的match_parent)Flutter中可以使用double.infinity來做出類似的表達。

          1.3.3 實踐Coding

          • 設置邊框&padding&margin&圓角&背景圖

          • 效果如下:

          1.4 手勢操作

          手勢操作是最常見的UI交互操作。在Flutter中手勢識別也是一個widget!這點對新人來說又是一個新鮮的地方。通常來說可以通過GestureDetector類來完成點擊事件的處理。使用時只需要將GestureDetector包裹在目標widget外面,再實現對應事件的函數即可。從點擊到長按,從縮放到拖動,這個類基本上都有相應的實現。具體可以參見組件文檔。

          2. 布局

          頁面布局應該是UI編寫最為根本的知識,其主要的描述的是父子組件子子組件之間的位置關系。首先我們理解一下官方文檔的邏輯:

          將布局分為單孩子和多孩子是Flutter布局的一大特色。這點對native研發同學來說會比較新鮮。單孩子組件主要繼承自SingleChildRenderObjectWidget。這些組件能提供豐富的裝飾能力(例如container),也能提供部分特定的布局能力(例如center)。多孩子組件繼承自MultiChildRenderObjectWidget,能提供更加豐富的布局能力(Flex,Stack,flow),但幾乎沒有裝飾的能力。下面介紹幾個重點布局:

          2.1 Flex

          Flutter在布局上也提供了完整的Flex布局能力。但是在Flutter官方文檔中Layout Widgets,是看不到任何Flex的影子的。映入眼簾的卻是Row,Column,這些是什么鬼?其實不難發現類似Row,Column 這樣的組件,他們的基類都是Flex。Row和Column差別是設置了不同的flex-direction。而之所這么設計,是因為Flutter的widget從開始設計之初就考慮到UI布局語義保持的重要性。這塊應該部分借鑒了前端的經驗,極力避免一個div搞定全部頁面的尷尬(當然flutter也可以使用Flex來做同樣的事情,但是并不建議這么做)。

          Flutter使用的Flex模型基本上跟傳統的Css類似。這塊前端同學可以快速上手。但是Flex對于客戶端同學來說是一種全新的布局方式。Flex的基礎知識可以參看flex布局基礎。由于篇幅有限這里不展開敘述。這里只重點強調一個點:

          如下圖flex布局概念如下:

          flex通過direction設置了flex的主軸方向即main axis。和主軸垂直的方向叫做cross axis。flex布局中對子布局的控制是從main axis 和cross axis兩個方向上進行的。例如居中有main axis居中和cross axis居中。兩者都居中才是容器的完全居中。這點是客戶端同學可能會容易弄混的地方。重點關注一下。

          2.1.1 實踐Coding

          ok,看完這些知識,我們實際需求角度實際操作幾個case來熟悉一下Flex。

          • 居中

          • 效果如下:

          • weight left:right=2:1 通過設置Flexible的flex值大小完成比例設置

          • 效果如下:

          2.2 stack

          在實際開發中,還是需要在一些Widgets的上面再覆蓋上新的Widgets。這時候就需要層式布局了。這種布局在Native上,以android為例,類似于relativeLayout 或者FrameLayout。在Flutter中使用的是Stack。

          實際使用中Stack中的子Widgets分為兩種:

          • positioned
          • 是包裹在組件Positioned中的組件
          • 可以通過Positioned屬性靈活定位
          • non-positioned
          • 沒有包裹在Positioned組件中
          • 需要通過父Widget Stack 的屬性來控制布局

          對于non-positioned children, 我們通過控制Stack的alignment屬性來控制對齊方式。Positioned的布局方式類似于H5&weex中的position布局中的absolute布局方式。通過設置距離父組件上下左右的距離,Positioned對象能在Stack布局中更加靈活的控制view的展現方式。

          2.2.1 實踐Coding

          • 層疊布局

          • 效果如下:

          3. Visibility

          當你看完Flutter Widge文檔的時候,我們突然發現一個略顯尷尬的問題:組件是否顯示怎么控制?貌似所有的組件中都沒有這個屬性!這不坑了,咋辦?

          目前看方法無非如下幾個:

          3.1 刪除法

          核心將該真實widget或者widget樹從renderTree中移除。

          具體到實踐級別主要分為兩個:

          • 單個組件‘隱藏’自己。在build方法中返回一個空的Container.

          • 多個child

          在父容器的children字段的list中,刪除掉對應的cell。

          3.2 Offstage

          Offstage 是一個widget。Offstage的offstage屬性設置為true,那么Offstage以及他的child都將不會被繪制到界面上。

          sample code如下:

          3.3 透明度

          設置widget的透明度,使之不可見。但是這樣的方法是副作用的。因為這個對應的widget樹是已經經過了完整的layout&paint過程,成本高。同時設置透明度本身也要耗費一定的計算資源,造成了二次浪費。需要注意的是即便變透明了,占據的位置還在。大家慎重選擇使用。

          sample code如下:

          visibility的控制還是比較麻煩的。這是Flutter設計上不符合正常習慣的一個點,需要大家重點關注。

          4 生命周期

          4.1 state 生命周期

          widget是immutable的,發生變化的時候需要重建,所以談不上狀態。StatefulWidget 中的狀態保持其實是通過State類來實現的。State擁有一套自己的生命周期,下面做一個簡單的介紹。

          生命周期狀態圖如下:

          幾個注意點

          • didChangeDependencies有兩種情況會被調用。
          • 創建時候在initState 之后被調用
          • 在依賴的InheritedWidget發生變化的時候會被調用
          • 正常的退出流程中會執行deactivate然后執行dispose。但是也會出現deactivate以后不執行dispose,直接加入樹中的另一個節點的情況。
          • 這里的狀態改變包括兩種可能:1.通過setState內容改變 2.父節點的state狀態改變,導致孩子節點的同步變化。

          4.2 App生命周期

          需要指出的是如果想要知道App的生命周期,那么需要通過WidgetsBindingObserver的didChangeAppLifecycleState 來獲取。通過該接口可以獲取是生命周期在AppLifecycleState類中。常用狀態包含如下幾個:

          一個實際場景中的例子:

          在不考慮suspending的情況下:從后臺切入前臺生命周期變化如下:

          • AppLifecycleState.inactive->AppLifecycleState.resumed;

          從前臺壓后臺生命周期變化如下:

          • AppLifecycleState.inactive->AppLifecycleState.paused;

          5 初學者的困惑

          5.1 為什么使用dart語言?

          Dart語言對大部分開發者而言是很陌生的一種語言。google為啥會選擇如此'冷門'的語言來開發flutter?主要原因如下:

          1. dart具有jit&Aot雙重編譯執行方式。這樣就能利用JIt進行開發階段的hot reload開發,提升研發效率。同時在最終release版本中使用aot將dart代碼直接變成目標平臺的指令集代碼。簡單高效,最大限度保障了性能。
          2. dart針對flutter中頻繁創建銷毀Widget的場景做了專門的gc優化。通過分代無鎖垃圾回收器,將gc對性能的影響降至最低。
          3. dart語言在語法上面是類java的,易學易用。

          5.2 為什么widget都是immutable?

          個人認為是兩個主要的點:

          • 提高渲染效率
          • flutte在頁面渲染上面的核心思想是simple is fast!將widget設計成immutable,所以在數據變化時,flutter選擇重建widget樹的方式進行數據更新。采用這樣方式的好處是框架不需要關心數據影響的范圍,簡單高效。缺點就是對GC會造成壓力。
          • 組件描述的復用
          • 既然widget都是不可變的。那widget可以以較低成本進行復用。在一個真實的渲染樹中可能存在同一個widget渲染樹中不同節點的情況。

          5.3 widget是view么?

          可能剛開始接觸flutter的同學最疑惑的一個問題就是widget和view的關系了。那么簡單分析一下:

          widget是對頁面UI的一種描述。他功能類有點似于android中的xml,或者web中的html。widget在渲染的時候會轉化成element。Element相比于widget增加了上下文的信息。element是對應widget,在渲染樹的實例化節點。由于widget是immutable的,所以同一個widget可以同時描述多個渲染樹中的節點。但是Element是描述固定在渲染書中的某一個特定位置的點。簡單點說widget作為一種描述是可以復用的,但是element卻跟需要繪制的節點一一對應。那element是最終渲染的view么?抱歉,還不是。element繪制時會轉化成rendObject。RendObject才是真正經過layout和paint并繪制在屏幕上的對象。在flutter中有三套渲染相關的tree,分別是:widget tree, element tree & rendObject tree。三者的渲染流程如下:

          那可能有人會問,為什么需要增增加中間這層的Element tree?

          flutter是響應式的框架。在某一時刻頁面的布局,可能受不同的輸入源的影響。Element這層實際上做了對某一時刻事件的匯總,在將真正需要修改的部分同步到真實的rendObject tree上。這么做有兩個好處:

          • 1.不需要直接操作UI,改為通過數據驅動視圖。代碼表達可以更加精煉。
          • 2.最大層度降低對最終真實視圖(rendObject tree)的修改,提高頁面渲染效率。

          5.4 StatelessWidget 和 StatefulWidget的區別

          StatelessWidget是狀態不可變的widget。初始狀態設置以后就不可再變化。如果需要變化需要重新創建。StatefulWidget可以保存自己的狀態。那問題是既然widget都是immutable的,怎么保存狀態?其實Flutter是通過引入了State來保存狀態。當State的狀態改變時,能重新構建本節點以及孩子的Widget樹來進行UI變化。注意:如果需要主動改變State的狀態,需要通過setState()方法進行觸發,單純改變數據是不會引發UI改變的。


          更多資訊,盡在阿里云科技快訊~

          來科技快訊看新聞鴨~

          快點關注我認識我愛上我啊~~~


          主站蜘蛛池模板: 色欲精品国产一区二区三区AV| 午夜视频在线观看一区| 在线精品视频一区二区| 一区二区视频在线免费观看| 亚洲毛片不卡av在线播放一区| 精品一区二区三区高清免费观看 | 精品国产一区二区三区麻豆 | 日韩人妻不卡一区二区三区 | 亚洲一本一道一区二区三区| 国产激情一区二区三区 | 北岛玲在线一区二区| 亚洲av乱码一区二区三区| 亚洲国产精品无码久久一区二区| 国模大尺度视频一区二区| 国产91精品一区二区麻豆亚洲| 国产麻豆剧果冻传媒一区| 国产乱人伦精品一区二区在线观看| 国产精品一级香蕉一区| 极品尤物一区二区三区| 最新欧美精品一区二区三区| 精品无码一区二区三区电影 | 国产伦精品一区二区三区免费迷 | 亚洲电影唐人社一区二区| 日本不卡一区二区视频a| 日本不卡一区二区三区视频| 精品亚洲一区二区| 国产精品亚洲专一区二区三区| 亚洲高清毛片一区二区| 日韩久久精品一区二区三区| 日韩国产一区二区| 国产亚洲福利精品一区| 久久精品国产一区二区三区肥胖| 无码av免费一区二区三区试看| 久久无码人妻一区二区三区| 国产一区二区三区影院| 国产综合无码一区二区色蜜蜜| 亚洲AV无码一区二区三区国产 | 久久精品国产一区二区三| 亚洲伦理一区二区| 亚州AV综合色区无码一区| 日本一区二区高清不卡|