摘要:屬性我們還可以使用來書寫樣式,它會自動幫我們編譯為格式內(nèi)容語法高亮建議使用配合該擴展支持語法高亮擴展開發(fā)項目,當(dāng)然你可以把文件當(dāng)作對待。
Omil 是什么?
Omil是一個 webpack 的 loader,它允許你以一種名為單文件組件(SFCs)的格式撰寫 Omi 組件:
${this.data.title}
Omil 還提供了很多酷炫的特性:
允許為 Omi 組件的每個部分使用其它的 webpack loader,例如在的部分使用 Sass 和在的部分使用 jsx;
允許在一個 .omi 文件中使用自定義塊,并對其運用自定義的 loader 鏈;
使用 webpack loader 將和中引用的資源當(dāng)作模塊依賴來處理;
在開發(fā)過程中使用熱重載來保持狀態(tài)。
簡而言之,webpack 和 Omi Loader 的結(jié)合為你提供了一個現(xiàn)代、靈活且極其強大的前端工作流,來幫助撰寫 Omi.js 應(yīng)用。
起步 Omi CLI如果你不想手動設(shè)置 webpack,我們推薦使用 Omi CLI 直接創(chuàng)建一個項目的腳手架。通過 Omi CLI 創(chuàng)建的項目會針對多數(shù)常見的開發(fā)需求進行預(yù)先配置,做到開箱即用。
如果Omi CLI提供的內(nèi)建沒有滿足你的需求,或者你樂于從零開始創(chuàng)建你自己的 webpack 配置,那么請繼續(xù)閱讀這篇指南。
手動設(shè)置 安裝首先先安裝好Omil
npm install -D omil
如果你使用的是 Visual Studio Code 進行開發(fā),強烈建議下載 Omi Snippets 擴展,它會提供給你語法高亮,局部編譯等功能。您可以在 VSC 擴展界面里面搜索 omi 這個關(guān)鍵詞出現(xiàn)Omi Snippets點擊安裝即可,稍等片刻,當(dāng)它安裝成功后會提醒你需要重新加載編輯工具,點擊重新加載即可使用。
每個Omil包的新版本發(fā)布時,一個相應(yīng)版本的Omi Snippets也會隨之發(fā)布。
webpack 配置Omi Loader 的配置和其它的 loader 基本一樣。
// webpack.config.js module.exports = { module: { rules: [ // ... 其它規(guī)則 { test: /.omi|eno$/, loader: "omil" } ] } }
一個更完整的 webpack 配置示例看起來像這樣:
module.exports = { mode: "development", module: { rules: [{ test: /.omi|eno$/, use: [{ loader: require.resolve("omil"), options: { // Use in development, You should remove in production sourceMaps: "both", // Config babel plugins for async, await and other many features plugins: [ [ "@babel/plugin-transform-runtime", { "absoluteRuntime": false, "corejs": false, "helpers": true, "regenerator": true, "useESModules": false } ] ] } }], // Or you can use eno-loader or omil directly // use: ["eno-loader"] // use: ["omil"] }] } }Omi Snippets
在配置完 Omil 之后,我們可以在 VS Code 上同時安裝好 Omi Snippets 擴展,這個插件可以方便的讓你把 .omi 和 .eno 后綴文件在未經(jīng)過 webpack 處理前轉(zhuǎn)化為 .js 文件,讓你可以直觀了解到單文件組件經(jīng)過 omil 轉(zhuǎn)化后的 JS 文件內(nèi)容,這相當(dāng)于局部編譯減輕 webpack 處理單文件時候的不必要消耗。
目錄結(jié)構(gòu)例如你在 webpack 的入口文件夾中有一個 .omi 的后綴文件,當(dāng)你新建并經(jīng)過編輯保存之后,Omi Snippets擴展會在同級目錄下新建一份同名但不同后綴的 .js 文件
src
Hello.omi
Hello.js
Hello.omi | 開發(fā)中你需要編寫的單文件組件 |
---|---|
Hello.js | 修改或者保存文件Hello.omi后經(jīng)過插件轉(zhuǎn)化的js文件 |
如下圖,左邊的代碼是我們編寫的 .omi 后綴的單文件組件,右邊是經(jīng)過 Omi Snippets 生成的 .js 后綴文件。
示例代碼上圖的示例代碼如下
標(biāo)簽負(fù)責(zé)放 JSX 的內(nèi)容,屬性name="my-test"為該組件的名字,后面可以在 JSX 中用
標(biāo)簽負(fù)責(zé)放入組件的邏輯文件,固定的結(jié)構(gòu)為 export default class { // 你的代碼 }或者為export default HOC(class { // 你的代碼 })兩種形式,第一種是定義類組件,第二種用來定義高階組件,你的代碼部分可以放入生命周期,函數(shù)等;
標(biāo)簽負(fù)責(zé)定義該組件的局部樣式
{ this.data.msg }
以下代碼就是經(jīng)過 Omi Snippets 生成的 .js 后綴文件,可以用于在你沒有 omil 模塊下,主邏輯文件或者其他組件引入調(diào)用。
import { WeElement, define, h } from "omi"; class MyTest extends WeElement { render() { return h( "div", { class: "example" }, this.data.msg ); } install() { this.data = { msg: "Hello world!" }; } } MyTest.css = ` .example { color: red; } `; define("my-test", MyTest);配合 React 開發(fā)
安裝 React 腳手架和一些必要模塊。
npm install create-react-app # 初始化項目 create-react-app my-project # 進入項目文件夾目錄 cd my-project # 安裝項目依賴 npm install # 安裝 styled-components 這個務(wù)必得安裝 用于處理 React 單文件組件局部樣式 npm install styled-components --save # 安裝 omil 處理React單文件組件,把 .omi 或者 .eno 后綴文件處理為 JS npm install omil --save-dev
在配置完 Omil 之后,我們可以在 VS Code 上同時安裝好 Omi Snippets 擴展,這個插件可以方便的讓你把 .omi 和 .eno 后綴文件在未經(jīng)過 webpack 處理前轉(zhuǎn)化為 .js 文件,讓你可以直觀了解到單文件組件經(jīng)過 omil 轉(zhuǎn)化后的 JS 文件內(nèi)容,這相當(dāng)于局部編譯減輕 webpack 處理單文件時候的不必要消耗。
編寫第一個組件現(xiàn)在你可以使用單文件組件來編寫 React 組件,默認(rèn)生成類組件。
name屬性值是組件名要滿足 React 框架的組件名字定義規(guī)范,首字母必須大寫字母;
模板中不能有和代碼片段。
{this.state.title}
以上文件經(jīng)過 Omil 處理后將會轉(zhuǎn)化為以下代碼:
import { Component as WeElement, createElement as h } from "react"; import styled from "styled-components"; const StyledComponents = styled.div` /* CSS */ p { color: #58bc58; } `; class ComponentName extends WeElement { render() { return h( StyledComponents, null, h("div", null, h("p", null, this.state.title)) ); } constructor(props) { super(props); this.state = { title: "react" }; } componentDidMount() { console.log("生命周期"); } } ComponentName.css = ` /* CSS */ p {color: #58bc58}; `; export default ComponentName;語言塊規(guī)范 簡介
.omi 文件是一個自定義的文件類型,用類 HTML 語法描述一個 Omi 組件。每個 .omi 文件包含三種類型的頂級語言塊 、 和 :
{ this.data.msg }
Omil 會解析文件,提取每個語言塊,如有必要會通過其它 loader 處理,最后將他們組裝成一個 ES Module,它的默認(rèn)導(dǎo)出是一個 Omi.js 組件定義好的自定義標(biāo)簽對象。
Omil 支持使用非默認(rèn)語言,比如 CSS 預(yù)處理器,預(yù)編譯的 HTML 模版語言,通過設(shè)置語言塊的 lang 屬性。例如,你可以像下面這樣使用 Sass 語法編寫樣式:
語言塊 模板每個 .omi 文件最多包含一個 塊。
內(nèi)容將被提取,如果是 JSX 會編譯為函數(shù)片段,如果為 html 會編譯為字符串,并最終注入到從導(dǎo)出的組件 render 函數(shù)中。
屬性name = "xxx-xxx"(Omi組件)定義name="xxx-xxx"可以給組件定義一個名字,這個名字會自動調(diào)用 omi 框架的 define("xxx-xxx", xxxXxx) 方法來注冊組件,你就可以在頁面中用這個屬性名
注意:
name屬性值是組件名要滿足 omi 框架的組件名字定義規(guī)范,首字母不能用大寫字母,并且中間必須有-字符;
模板中不能有和代碼片段。
{ this.data.msg }
在頁面容器中如此使用
屬性name = "XxxXxx"(React組件)
定義name="XxxXxx"可以給組件定義一個名字,這個名字會自動調(diào)用 React 框架的 React.Component 方法來定義類組件,你就可以在頁面中用這個屬性名
注意:
name屬性值是組件名要滿足 React 框架的組件名字定義規(guī)范,首字母必須大寫字母;
模板中不能有和代碼片段。
{ this.data.msg }
在頁面容器中如此使用
屬性lang = "html"(僅支持Omi)
默認(rèn)情況下,我們的模板是使用 JSX 語法,如果我們增加屬性lang = "html",就可以支持編寫html格式的字符串模板,你可以使用 ES6 的語法來編寫 html 模板 每個 .omi 文件最多包含一個 塊。 如果我們使用過 react 我們會了解到組件通常有兩種定義方式,一種是函數(shù)組件,一種是類組件,Omil 默認(rèn)是幫你創(chuàng)建類組件,我們在export default class { // 你的代碼 }或者module.exports = class { // 你的代碼 }片段中寫入你的組件邏輯代碼, 注意: 定義類組件必須是export default class { // 你的代碼 }這種寫法,class MyText {} ; export default MyText這種寫法不可以,因為 Omil 和 Omil Snippets 只識別連續(xù)的export default class這段字符串 有時候我們可以使用高階組件拓展組件本身的一些功能,高階組件跟類組件一樣,只支持下面規(guī)定的寫法。 下面是一個高階組件的詳細(xì)參考例子 {this.state.title} 或者你可以這樣寫 {this.state.title} 通常情況下,你可以在代碼中使用ES6的語法,甚至一些新特性,例如:static,某些情況下我們需要轉(zhuǎn)化為ES5做兼容,我們可以添加屬性type="text/babel" 一個 .omi 文件可以包含一個標(biāo)簽。 標(biāo)簽的樣式本身具有局部樣式的特性,這取決于 Omi 的設(shè)計是 Web Components,這有點類似于 Vue 的 scoped 屬性。 我們還可以使用lang = "scss"來書寫 scss 樣式,它會自動幫我們編譯為 css 格式內(nèi)容 建議使用 VS Code 配合 Omi Snippets (該擴展支持語法高亮)擴展開發(fā) Omi 項目,當(dāng)然你可以把 .omi 文件當(dāng)作 HTML 對待。 在語言塊中使用該語言塊對應(yīng)的注釋語法 (HTML、CSS、JavaScript 等)。 觀察下面這段代碼模板: 這個有趣的標(biāo)簽語法既不是字符串也不是 HTML。 它被稱為 JSX,是一個 JavaScript 的語法擴展。我們建議在 Omi 中配合使用 JSX,JSX 可以很好地描述 UI 應(yīng)該呈現(xiàn)出它應(yīng)有交互的本質(zhì)形式。JSX 可能會使人聯(lián)想到模版語言,但它具有 JavaScript 的全部功能。 上面的代碼事實上會自動編譯為下面這份 js 代碼 Omi 和 React 不強制要求使用 JSX,但是大多數(shù)人發(fā)現(xiàn),在 JavaScript 代碼中將 JSX 和 UI 放在一起時,會在視覺上有輔助作用。 Omil和Omi Snippets都支持編譯Omi和React,編譯的區(qū)別取決于的name屬性值,React的組件名必須首字母大寫,Omi的組件首字母不能大寫,并且名字中間必須有-符號連接。 在下面的例子中,我們聲明了一個名為 title 的變量,然后在 JSX 中使用它,并將它包裹在大括號中: 在 JSX 語法中,你可以在大括號內(nèi)放置任何有效的 JavaScript 表達(dá)式。例如,2 + 2,user.firstName 或 formatName(user) 都是有效的 JavaScript 表達(dá)式。 Name: {this.formatName(user)} Age: {9+9} 二元和三元表達(dá)式 假 數(shù)組渲染成列表 在編譯之后,JSX 表達(dá)式會被轉(zhuǎn)為普通 JavaScript 函數(shù)調(diào)用,并且對其取值后得到 JavaScript 對象。 也就是說,你可以在 if 語句和 for 循環(huán)的代碼塊中使用 JSX,將 JSX 賦值給變量,把 JSX 當(dāng)作參數(shù)傳入,以及從函數(shù)中返回 JSX: {this.getGreeting(user)} {this.getGreeting()} 你可以通過使用引號,來將屬性值指定為字符串字面量 也可以使用大括號,來在屬性值中插入一個 JavaScript 表達(dá)式: HTML 和 JSX 的一些區(qū)別 在屬性中嵌入 JavaScript 表達(dá)式時,不要在大括號外面加上引號。你應(yīng)該僅使用引號(對于字符串值)或大括號(對于表達(dá)式)中的一個,對于同一屬性不能同時使用這兩種符號。 因為 JSX 語法上更接近 JavaScript 而不是 HTML,所以 React DOM 使用 camelCase(小駝峰命名)來定義屬性的名稱,而不使用 HTML 屬性名稱的命名約定。 例如,JSX 里的 class 變成了 className,而 tabindex 則變?yōu)?tabIndex。 假如一個標(biāo)簽里面沒有內(nèi)容,你可以使用 /> 來閉合標(biāo)簽,就像 XML 語法一樣: JSX 標(biāo)簽里能夠包含很多子元素: Babel 會把 JSX 轉(zhuǎn)譯成一個名為 h() 函數(shù)調(diào)用。 以下兩種示例代碼完全等效: h() 會預(yù)先執(zhí)行一些檢查,以幫助你編寫無錯代碼,但實際上它創(chuàng)建了一個這樣的對象: 這些對象它們描述了你希望在屏幕上看到的內(nèi)容。Omi 通過讀取這些對象,然后使用它們來構(gòu)建 DOM 以及保持隨時更新。 我們可以在組件的屬性上傳入屬性值,通過傳入屬性值讓組件接受外部的數(shù)據(jù)而更改自身的狀態(tài)。 組件內(nèi)部通過props接受即可: {props.myObj.name} 我們還可以通過static defaultProps設(shè)置默認(rèn)的props值和通過static propTypes設(shè)置默認(rèn)的props類型。 {props.name} {props.age} Omi 元素的事件處理和 React 一樣和 DOM 元素的很相似,但是有一點語法上的不同: Omi 事件的命名采用小駝峰式(camelCase),而不是純小寫。 使用 JSX 語法時你需要傳入一個函數(shù)作為事件處理函數(shù),而不是一個字符串。 你必須謹(jǐn)慎對待 JSX 回調(diào)函數(shù)中的 this,在 JavaScript 中,class 的方法默認(rèn)不會綁定 this。如果你忘記綁定 this.handleClick 并把它傳入了 onClick,當(dāng)你調(diào)用這個函數(shù)的時候 this 的值為 undefined。 這并不是 React 特有的行為;這其實與 JavaScript 函數(shù)工作原理有關(guān)。通常情況下,如果你沒有在方法后面添加 (),例如 onClick={this.handleClick},你應(yīng)該為這個方法綁定 this。 在循環(huán)中,通常我們會為事件處理函數(shù)傳遞額外的參數(shù)。例如,若 id 是你要刪除那一行的 ID,以下兩種方式都可以向事件處理函數(shù)傳遞參數(shù): 上述兩種方式是等價的,分別通過箭頭函數(shù)和 Function.prototype.bind 來實現(xiàn)。 在這兩種情況下,React 的事件對象 e 會被作為第二個參數(shù)傳遞。如果通過箭頭函數(shù)的方式,事件對象必須顯式的進行傳遞,而通過 bind 的方式,事件對象以及更多的參數(shù)將會被隱式的進行傳遞。 以下表格是 Omi 的生命周期: 舉個例子: update 方法是內(nèi)置的重要核心方法,用于更新組件自身。比如: 也可以傳遞參數(shù),決定是否在 html 模式下忽略 attributes,強行更新: 當(dāng)我們組件的 data 值發(fā)生變化,我們可以使用this.update()更新視圖 顯示或者隱藏 在元素上添加 ref={e => { this.anyNameYouWant = e }} ,然后你就可以 JS 代碼里使用 this.anyNameYouWant 訪問該元素。你可以使用兩種方式來提高 update 的性能: 提前賦值 createRef 你也可以使用 createRef 來得到更高的性能,使用前需要引用 import { createRef } from "omi": Store 是 Omi 內(nèi)置的中心化數(shù)據(jù)倉庫,他解決和提供了下面問題和能力: 組件樹數(shù)據(jù)共享 path/elements/app/index.omi下的根組件
Clicked: {this.use.count} times
{" "}
{" "}
{" "}
{" "}
path/src/index.js全局的入口文件代碼 通過 static use 聲明依賴的 path store 通過 render 的第三個參數(shù)從根節(jié)點注入到所有組件。 Store 里的 data: 下面舉一個復(fù)雜的 use 例子: 下面看看 JSX 中使用: 如果不帶有 alias ,你也可以直接通過 this.store.data.xxx 訪問。 當(dāng) store.data 發(fā)生變化,依賴變更數(shù)據(jù)的組件會進行更新,舉例說明 Path 命中規(guī)則: 以上只要命中一個條件就可以進行更新! 總結(jié): 只要注入組件的 path 等于 use 里聲明 或者在 use 里聲明的其中 path 子節(jié)點下就會進行更新! 這里說的是 props 的 css,而不是 static css,它提供了修改 shadow dom 內(nèi)部 scoped style 的能力。 上面的 my-element 的 h1 標(biāo)簽顏色是紅色。有什么辦法修改嗎? 而且還可以通過下面的方式保證一定能夠修改: 如果您用過 React,相信對高階組件肯定不陌生,高階組件(HOC)是 React 中用于復(fù)用組件邏輯的一種高級技巧。HOC 自身不是 React API 的一部分,它是一種基于 React 的組合特性而形成的設(shè)計模式。 具體而言,高階組件是參數(shù)為組件,返回值為新組件的函數(shù)。 組件是將 props 轉(zhuǎn)換為 UI,而高階組件是將組件轉(zhuǎn)換為另一個組件。 HOC 在 React 的第三方庫中很常見,例如 Redux 的 connect。 下面這個例子是是在組件中使用 Redux 高階組件 {this.state.title} 文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。 轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/105703.html 摘要:用過的同學(xué)都知道,性能優(yōu)化的關(guān)鍵就是,最被詬病的也是這個,很多開發(fā)者也吐槽這個鉤子函數(shù),也可以配合不可變數(shù)據(jù)類型,直接進行引用地址比較,來決定組件是否需要更新。
大家好,這次給大家講下 Omi 框架 以及即將發(fā)布的 Omim 大家有沒有數(shù)左邊的圖片里有多少個 Omi?Omi 團隊很在意這里,特意數(shù)了下,有三個。Omi 團隊希望 Omi 以后在各大會議里能夠印刷得更加大一些。今天給大家?guī)淼闹?.. 摘要:經(jīng)過周末的連續(xù)通宵加班加點,版本終于問世。雖然組件通訊非常方便,但是各種數(shù)據(jù)傳遞組件實例互操作或者循環(huán)依賴,讓代碼非常難看且難以維護。所以是為了讓組件通訊幾乎絕跡。所以的插件不會有太多。完善的腳手架你可以安裝,用來初始化項目腳手架。
原文鏈接--https://github.com/AlloyTeam/omi
寫在前面
Omi框架經(jīng)過幾十個版本的迭代,越來越簡便易用和強大。經(jīng)過周末的連... 摘要:插件開發(fā)前端掘金作者原文地址譯者插件是為應(yīng)用添加全局功能的一種強大而且簡單的方式。提供了與使用掌控異步前端掘金教你使用在行代碼內(nèi)優(yōu)雅的實現(xiàn)文件分片斷點續(xù)傳。
Vue.js 插件開發(fā) - 前端 - 掘金作者:Joshua Bemenderfer原文地址: creating-custom-plugins譯者:jeneser Vue.js插件是為應(yīng)用添加全局功能的一種強大而且簡單的方式。插....
腳本
高階組件(僅支持React)
export default class { // 你的代碼 }
可以
建議使用
module.exports = class { // 你的代碼 }
可以
支持
class MyText { // 你的代碼 }
export default MyText
不可以
不支持
class MyText { // 你的代碼 }
module.export = MyText
不可以
不支持
export default HOC(class { // 你的代碼 })
可以
建議使用
module.exports = HOC(class { // 你的代碼 })
可以
支持
class MyText { // 你的代碼 }
export default HOC(MyText)
不可以
不支持
class MyText { // 你的代碼 }
module.export = HOC(MyText)
不可以
不支持
{HOC(
屬性type="text/babel"
JSX 簡介
JSX 注釋語法
{/* comment contents here */}
HTML 注釋語法
import { WeElement, define, h } from "omi";
class ComponentName extends WeElement {
render() {
return h(
"div",
{
onClick: this.testClick
},
this.data.title
);
}
}
define("component-name", ComponentName);
為什么使用 JSX?
在 JSX 中嵌入表達(dá)式
React
Omi
組件名必須首字母大寫
組件首字母不能大寫,并且名字中間必須有-符號連接
{ user.age > 18 &&
JSX 也是一個表達(dá)式
{
["a","b","c"].map((item,index) => {
return
JSX 特定屬性
HTML
JSX
警告:
使用 JSX 指定子元素
JSX 表示對象
const element =
Hello, world!
const element = h(
"div",
null,
h(
"h1",
{
className: "greeting"
},
"Hello, world!"
)
);
// 注意:這是簡化過的結(jié)構(gòu)
const element = {
children: [{
attributes: {className: "greeting"},
children: ["Hello, world!"],
nodeName: "h1",
}],
nodeName: "div"
}
事件處理
事件中的this
向事件處理程序傳遞參數(shù)
生命周期鉤子
描述
install
組件掛載到 DOM 前
installed
組件掛載到 DOM 后
uninstall
組件從 DOM 中移除前
beforeUpdate
update 更新前
updated
update 更新后
beforeRender
render() 之前
receiveProps
父元素重新渲染觸發(fā)
Update
this.update()
this.update(true)
Ref
{ this.h1 = e }} onClick={this.onClick}>Hello, world!
createRef
{ this.myRef = e }} onClick={this.onClick}>Hello, world!
Store 是什么?
Hello, world!
數(shù)據(jù)變更按需更新依賴的組件
import { render } from "omi"
import "./elements/app"
render(
{
count: 0,
arr: ["china", "tencent"],
motto: "I love omi.",
userInfo: {
firstName: "dnt",
lastName: "zhang",
age: 18
}
}
static use = [
"count", //直接字符串,JSX 里可通過 this.use[0] 訪問
"arr[0]", //也支持 path,JSX 里可通過 this.use[1] 訪問
//支持 json
{
//alias,JSX 里可通過 this.use.reverseMotto 訪問
reverseMotto: [
"motto", //path
target => target.split("").reverse().join("") //computed
]
},
{ name: "arr[1]" }, //{ alias: path },JSX 里可通過 this.use.name 訪問
{
//alias,JSX 里可通過 this.use.fullName 訪問
fullName: [
["userInfo.firstName", "userInfo.lastName"], //path array
(firstName, lastName) => firstName + lastName //computed
]
},
]
...
...
Proxy Path(由數(shù)據(jù)更改產(chǎn)生)
static use 中的 path
是否更新
abc
abc
更新
abc[1]
abc
更新
abc.a
abc
更新
abc
abc.a
不更新
abc
abc[1]
不更新
abc
abc[1].c
不更新
abc.b
abc.b
更新
Look at my color!
color: blue!important;
高階組件
const EnhancedComponent = higherOrderComponent(WrappedComponent);
相關(guān)文章
FDCon2019 第4屆中國前端開發(fā)者千人峰會 - 《Omi - Cross-Frameworks
Omi v1.0震撼發(fā)布 - 令人窒息的Web組件化框架
JavaScript - 收藏集 - 掘金
發(fā)表評論
0條評論
閱讀 3030·2021-11-22 09:34
閱讀 2506·2021-09-30 09:47
閱讀 1439·2021-09-03 10:32
閱讀 3703·2021-08-16 10:49
閱讀 1784·2019-08-30 15:55
閱讀 2451·2019-08-30 15:52
閱讀 3316·2019-08-30 15:44
閱讀 1344·2019-08-30 15:44