<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          [email protected]正式發(fā)布與做open source的一些感受」從90%到100%...

          共 18946字,需瀏覽 38分鐘

           ·

          2022-02-20 09:27

          前言

          在介紹Strve.js新版本之前呢!我們先來看下尤雨溪同學(xué)近期的兩段分享。


          1. 當(dāng)時(shí)你還有day job時(shí)候,怎么保持做open source的, how you balance between them?

          可能我比較幸運(yùn)點(diǎn)吧!因?yàn)樵诿绹@邊大家對(duì)工作平衡比較注意,像谷歌的話就比較舒服的了。雖然我們剛進(jìn)去也年輕,偶爾也加加班,但是整體而言,在谷歌的話,你任務(wù)完成了想什么時(shí)候走都可以。所以在國內(nèi)確實(shí)會(huì)難一些,業(yè)務(wù)壓力會(huì)大的話。所以如果你真的覺得業(yè)務(wù)壓力就更大,工作就很忙。那我建議就可能不要逼自己,如果真覺得太累,就不要逼自己。 這個(gè)開源本身也其實(shí)就是說,這個(gè)大家做開源其實(shí)都有一個(gè)階段,就是你剛開始有一個(gè)想法想把它做出來,剛開始是一種快樂的一種狀態(tài),就是把一個(gè)想法從零到一那種快感,就是做技術(shù)人員都有這種創(chuàng)造一種東西的想法。但是開源在另一個(gè)過程完成之后立刻進(jìn)入一種,就是從90%到100%這個(gè)過程其實(shí)是很困難的,你就會(huì)發(fā)現(xiàn)把一個(gè)玩具做成真的能用的東西就需要投入很多,當(dāng)你把它做得真的能用,真的有人用的時(shí)候,這些人就會(huì)繼續(xù)給你提不停的要求。這就說,哎呀!我得去回應(yīng)這些人的期待,這又是一種心理壓力。 其實(shí)說就是很多時(shí)候,大家都是剛開始做開源的時(shí)候,這種創(chuàng)造一種東西的快感所吸引。沒有意識(shí)到你以后會(huì)有很多的commit。我對(duì)很多想要做開源的朋友的建議是,想清楚你做開源想要做什么,如果你就只是想寫一個(gè)庫覺得很爽,但是我后期不想去做讓它耗費(fèi)我很多精力去維護(hù)它,也沒有問題,其實(shí)就跟大家明確這個(gè)想法。但是如果說你想做一個(gè)項(xiàng)目想做大做好,想跟React競(jìng)爭(zhēng)的項(xiàng)目,那這個(gè)東西需要極大的投入的。如果你工作本質(zhì)就很煩忙,那么大概率你就沒有可能做這個(gè)。所以確實(shí)說,想好你的想要什么吧!如果你沒有真的條件,如果真的很拼很拼,我就是996,我也要做開源,那你要做好心理準(zhǔn)備。我有一段時(shí)間把自己搞成996這種狀態(tài),就是上完班回來搞Vue,其實(shí)這樣精神壓力是挺大的。我現(xiàn)在可能站著說話不腰疼,我現(xiàn)在還是覺得平衡一點(diǎn)的好。

          2 . 在設(shè)計(jì)vue這樣的框架時(shí),你會(huì)考慮哪些東西?

          其實(shí)考慮的問題就是說,首先,這個(gè)比較大了,當(dāng)然這個(gè)考慮問題也不是一開始就完全想好,Vue也是從一個(gè)小項(xiàng)目慢慢發(fā)展起來的。那我們就是說你對(duì)自己的框架有一個(gè)定位,Vue的定位就是說我們保證要對(duì)新手友好,容易上手。這個(gè)就是一個(gè)定位,有些框架就說了,我就不是設(shè)計(jì)給新手用的,我就不考慮這個(gè)問題。這也是合理的,這不是好或不好,這就是一個(gè)設(shè)計(jì)上的決定,我就是要對(duì)新手友好的框架,或者說我在其他情況付出一些代價(jià),比如說我的一個(gè)API設(shè)計(jì)的難以理解。但是就是有的時(shí)候你過度追求新手友好,你可能會(huì)被限制在高端或者追求性能的一些場(chǎng)景,那你就在這里面做權(quán)衡。那反過來有些框架我不考慮新手用戶,我就考慮理論上的優(yōu)美,就比如說小眾的函數(shù)式框架,它可能說是針對(duì)某些論文寫出的非常優(yōu)雅,非常完美的模式。但是,如果是一個(gè)新手,你可能看不懂我在干什么。其實(shí)這就是取舍,對(duì)吧。所以,最先要明確你的框架的定位。在這前提下,你還要考慮就是說其實(shí)你到后面你會(huì)發(fā)現(xiàn)一到具體工程問題。到處都是取舍。 就比如說你一個(gè)API,你可以選擇這樣設(shè)計(jì)變的更簡(jiǎn)潔優(yōu)美,但是這會(huì)導(dǎo)致某個(gè)地方很難優(yōu)化。那么反過來我為了追求極致性能,我可能API設(shè)計(jì)的稍微那么難受一點(diǎn)。還有就是社區(qū)的需求,你自己做出的決定未必是社區(qū)想要的。就需要去跟社區(qū)溝通吧,還要公開討論過程。Vue做一些大的改動(dòng)的話,更多的就是拋一個(gè)想法出來,社區(qū)進(jìn)行討論。變成了一個(gè)多少共同設(shè)計(jì)的過程,不再像初期,初期的話,你更多就是不需要考慮那么多用戶,你一拍腦袋,你就把它做出來。所以說,初期階段跟后期跟你設(shè)計(jì)的流程完全就不一樣了。



          大家可以看到對(duì)于開源框架,尤大也給出了很不錯(cuò)的建議。其實(shí)之前我打算寫Strve.js,就是想看自己也能不能開發(fā)出起碼不是很差的庫或者框架。結(jié)果也不錯(cuò),總算搞出來了。下面是之前自己獨(dú)立開發(fā)Strve.js的一些感想。

          從2021年9月份的時(shí)候,就想自己開發(fā)一個(gè)庫,從而提高一下自己的能力。慶幸的是在年前就開發(fā)出來了,并且生態(tài)也初步建成。這里提到的生態(tài)包括:Create Strve App、Strve Router以及其他輔助Strve.js開發(fā)的工具。

          說實(shí)話,這段時(shí)間是挺難熬的,這也算是今年給自己一個(gè)禮物吧!

          我開發(fā)Strve.js的初衷是之前接觸過JSX語法,一直覺的JSX語法非常酷,可以在JS中寫HTML標(biāo)簽,于是就想開發(fā)一款類似JSX語法的庫。剛開始也開發(fā)了一段時(shí)間,搭配Babel可以簡(jiǎn)單實(shí)現(xiàn)JSX語法。但是到后來覺得并不是那么完美,還要解決一些類似修改數(shù)據(jù)更新視圖的一些問題。熬了幾天夜,也沒有完美的解決。最后,還是放棄了這種方案。

          我當(dāng)時(shí)在想,如果我僅僅想在JS中寫HTML標(biāo)簽,那么使用JS中的模板字符串就已經(jīng)具備在字符串內(nèi)寫HTML標(biāo)簽的能力了,為什么不換一下思路,研究一下在模板字符串中寫HTML標(biāo)簽這種更加方便直接的方案呢?剛開始我就是從基礎(chǔ)著手,寫一串字符串,然后怎么想辦法將字符串掛載到頁面中。借鑒了React、Vue這些框架的思想,在頁面指定一個(gè)掛載元素。這就簡(jiǎn)單實(shí)現(xiàn)了在模板字符串內(nèi)開發(fā)HTML,但是隨之而來的是不能做到數(shù)據(jù)變頁面變,從更加專業(yè)的角度上講就是數(shù)據(jù)驅(qū)動(dòng)頁面。并且更新頁面后盡可能的少修改DOM元素,減少重排帶來的性能上的影響。這從最初的簡(jiǎn)單的在JS寫HTML又上升到一個(gè)層面上,怎么實(shí)現(xiàn)一個(gè)MVVM框架。

          市面上知名的MVVM框架有Vue、React、Angular,既然自己想設(shè)計(jì)一個(gè)MVVM框架,那么可以借鑒一下它們的思想。首先,非常喜歡Vue的漸進(jìn)式設(shè)計(jì)思想,只要你是一個(gè)前端小白就可以立馬上手,這是非常值得借鑒的。另外又借鑒了React框架中的“All in JS”以及異步更新數(shù)據(jù)的思想。最后,它們兩個(gè)框架都使用了虛擬DOM來提升性能,那么我們也可以引入虛擬DOM機(jī)制。

          之前,聽過尤老師的幾期中文分享,談到框架的話題說,框架的設(shè)計(jì)就是不斷的取舍。這其中肯定還會(huì)復(fù)雜很多,我上面也就是簡(jiǎn)單的概括了一下。能不能實(shí)現(xiàn)我所預(yù)期的那樣,當(dāng)時(shí)我也不知道,當(dāng)時(shí)就想把東西做出來。前面一個(gè)多月是非常痛苦的,幾乎是閉門造車。主要的難點(diǎn)是怎么將模板字符串轉(zhuǎn)化成虛擬DOM結(jié)構(gòu),并且代碼量控制在最小。然后將轉(zhuǎn)化的虛擬DOM進(jìn)行Diff算法,更有效的更新DOM。

          最終,功夫不負(fù)有心人,我終于如愿以償?shù)耐瓿闪薙trve.js的開發(fā)。這個(gè)小型庫,也算不上是框架吧!設(shè)計(jì)的初衷上面也說了就是自己想練練手,看自己也能不能開發(fā)出起碼不是很差的庫或者框架。

          在2021年12月的時(shí)候,我發(fā)布了第一個(gè)版本1.2.2,這個(gè)版本相對(duì)比較簡(jiǎn)陋。但是,周圍生態(tài)也已經(jīng)初步建成。發(fā)布之后,我自己試用了一下,自己試著敲了幾個(gè)小項(xiàng)目。比如大家都會(huì)做得TodoList。怎么說呢!對(duì)于我自己來說,只能說還可以。很容易上手,大多都是利用原生JavaScript的能力,所以只要熟悉JavaScript的朋友都可以上手,并且利用聲明式API對(duì)一些DOM進(jìn)行操作,沒有了JQuery那種命令式API對(duì)DOM拿來就是干。并且符合了MVVM框架的思想,更容易開發(fā)項(xiàng)目。

          我很認(rèn)同尤大說的一句話,就是從90%到100%這個(gè)過程其實(shí)是很困難的,你就會(huì)發(fā)現(xiàn)把一個(gè)玩具做成真的能用的東西就需要投入很多。我在想既然我已經(jīng)決定了開發(fā)一個(gè)庫,雖然比不上Vue、React這些大框架,但是為什么不想簡(jiǎn)單一點(diǎn),就單純地自己開發(fā)維護(hù)一個(gè)項(xiàng)目呢!所以,我必須繼續(xù)優(yōu)化維護(hù)下去。在2022年1月份,我決定要優(yōu)化一些代碼,使Strve.js變得更好。框架設(shè)計(jì)正如尤大所說的到后面你會(huì)發(fā)現(xiàn)一到具體工程問題。到處都是取舍。在這段時(shí)間我覺得比剛開發(fā)Strve.js的時(shí)候更難受,因?yàn)槟阆氚岩粋€(gè)做出來的東西再做到更完美實(shí)在是難。終于體會(huì)到了尤大說的那些話,我覺得這也是成長,起碼我在用Vue的時(shí)候,不會(huì)只會(huì)簡(jiǎn)單用它的API。經(jīng)過1個(gè)月的調(diào)研與各種測(cè)試,終于可以發(fā)布第二個(gè)版本2.1.0,之前還有一個(gè)版本2.0.0。我覺得這就是突破,我也完成了。

          所以,最后,我想告訴有一些做開源的朋友們,其實(shí)不要想的那么復(fù)雜,做好每一步就可以了。

          [email protected]發(fā)布

          源代碼地址:

          https://github.com/maomincoding/strve/

          2.0.0 (2022-01-23)

          • 向鏈表頭部插入數(shù)據(jù)需要綁定useFkey字段,避免DOM節(jié)點(diǎn)重復(fù)渲染;

          • 渲染后隱藏“DOM”節(jié)點(diǎn)事件方法;

          • 綁定Style樣式(對(duì)象);

          • 綁定屬性統(tǒng)一使用${}符號(hào)綁定;

          • 支持 HTML 模板字符串高亮(VSCode 編輯器需要安裝 comment-tagged-templates 插件);

          • 支持父子組件互相傳值;

          • 適配Bootstrap5、Tailwindcss UI框架;

          2.1.0 (2022-01-25)

          • 修復(fù)DOM屬性property無法賦值的問題;
          • 完善字符串轉(zhuǎn)換為虛擬DOM邏輯問題;

          新文檔更新

          中文文檔地址:

          https://maomincoding.github.io/strvejs-doc/zh/

          更新內(nèi)容

          • 整體UI優(yōu)化;
          • 側(cè)邊欄默認(rèn)收起;
          • 代碼主題優(yōu)化;
          • 搜索功能優(yōu)化;
          • 加入主題切換(白天/黑夜);
          • 加入支持UI框架菜單項(xiàng);
          • 加入更新日志菜單項(xiàng);
          • 更新API的使用細(xì)節(jié)說明;

          效果圖預(yù)覽


          aa37d29c6da03e2c3ce69527529309c0.webp

          圖1

          2b4975a5832e4aae5cf36f3c908a46bd.webp

          圖2


          661e1b359974db8e7c7ab13058848d68.webp

          圖3


          實(shí)戰(zhàn)第一個(gè)Strve項(xiàng)目

          我們下面要做的項(xiàng)目是TodoList,相信大家都做過,也挺實(shí)用。我們這里先不注重樣式,主要是實(shí)現(xiàn)簡(jiǎn)單的增刪改的功能。

          下面是全部代碼,大約51行。

          5e701d0ab22adc50a9ae77a4755a2a90.webp

          圖4

          下面是頁面效果。

          fdf30514d0ebeb5ba9f587790d49b8d5.webp

          圖5

          我們來跑下分吧!

          3575d179a3c73dfe7755ed4794d1a12f.webp


          文檔一覽

          介紹

          Strve.js的讀音/str'vi/,是字符串(String)與視圖(View)的拼接。Strve.js是一個(gè)可以將字符串轉(zhuǎn)換為視圖的JS庫。這里的字符串指的是模板字符串,所以你僅需要在JavaScript中開發(fā)視圖。這里的視圖指的就是我們平時(shí)寫的HTML頁面,也就是視圖層。

          Strve.js不僅易于上手,還便于靈活拆裝不同的代碼塊。使用模板字符串開發(fā)視圖主要是利用了原生JavaScript的能力,可以更加靈活地分離代碼塊,你僅僅只關(guān)注JavaScript文件。

          Strve.js又是一款輕量級(jí)的MVVM框架,你只需要關(guān)心數(shù)據(jù)以及如何操作它,其他工作交給Strve.js內(nèi)部處理。Strve.js首先會(huì)將模板字符串轉(zhuǎn)化為虛擬DOM,然后進(jìn)行Diff算法通過比較前后兩次的狀態(tài)差異更新真實(shí)DOM。這也是很多框架為了提升瀏覽器性能采用的方案,但是Strve.js更加輕量。

          如果你想上手項(xiàng)目,那么請(qǐng)看下面怎么安裝它吧!

          安裝

          CDN

          如果你使用原生 ES Modules。

          <script?type="module">
          ??import?{?Strve,?render}?from?'https://cdn.jsdelivr.net/npm/strvejs/dist/strve.esm.min.js';
          script>

          NPM

          npm?i?strvejs

          命令行工具

          create-strve-app

          一套快速搭建Strve.js項(xiàng)目的命令行工具。與早期的腳手架 Create Strve 相比,Create Strve App 更勝一籌,可直接輸入命令快速創(chuàng)建Strve項(xiàng)目。Create Strve App是用Vite來構(gòu)建的,它是一種新型前端構(gòu)建工具,能夠顯著提升前端開發(fā)體驗(yàn)。

          npm

          npm?init?strve-app@latest

          yarn

          yarn?create?strve-app

          pnpm

          pnpm?create?strve-app
          create-strve

          Create Strve 是基于Strve.js的項(xiàng)目構(gòu)建工具,您可以使用它更方便靈活地搭建頁面。

          全局安裝

          npm?install?create-strve?-g

          查看版本

          create-strve?-v

          初始化項(xiàng)目

          create-strve?init?

          快速上手

          嘗試 Strve.js 最簡(jiǎn)單的方法是使用直接引入CDN鏈接。你可以在瀏覽器打開它,跟著例子學(xué)習(xí)一些基礎(chǔ)用法。

          html>
          <html?lang="en">

          <head>
          ????<meta?charset="UTF-8">
          ????<title>Strve.jstitle>
          ????<style>
          ????????.inner?{
          ????????????width:?900px;
          ????????????margin:?40px?auto;
          ????????????text-align:?center;
          ????????????padding:?40px;
          ????????????box-shadow:?0?0?20px?#ccc;
          ????????}

          ????????button?{
          ????????????margin:?10px;
          ????????}
          ????
          style>
          head>

          <body>
          ????<div?id="app">div>
          ????<script?type="module">
          ????????import?{?Strve,?updateView,?render,?emitEvent?}?from?'https://cdn.jsdelivr.net/npm/strvejs/dist/strve.esm.js';
          ????????const?state?=?{
          ????????????arr:?[{
          ????????????????id:?'1',
          ????????????????txt:?'1'
          ????????????},?{
          ????????????????id:?'2',
          ????????????????txt:?'2'
          ????????????},?{
          ????????????????id:?'3',
          ????????????????txt:?'3'
          ????????????},?{
          ????????????????id:?'4',
          ????????????????txt:?'4'
          ????????????}],
          ????????????msg:?'hello',
          ????????????a:?2,
          ????????????style:?{
          ????????????????color:?'red',
          ????????????????fontSize:?"40px"
          ????????????},
          ????????????obj:?{
          ????????????????a:?{
          ????????????????????b:?{
          ????????????????????????c:?1
          ????????????????????}
          ????????????????}
          ????????????}
          ????????};

          ????????function?Component1(v)?{
          ????????????return?render/*?html?*/`
          ????????????????????${emitData}
          >${v}
          ????????????????????
          ????????????????????????${state.arr.map((todo)?=>?render/*?html?*/`${todo.txt}`)}
          ????????????????????
          ????????????`

          ????????}

          ????????function?emitData()?{
          ????????????emitEvent('getTit',?{
          ????????????????detail:?{?title:?'This?is?title!'?},
          ????????????},?'.component1')
          ????????}

          ????????function?App()?{
          ????????????return?render/*?html?*/`
          ??????????????
          ??????????????????${state.style}
          ">{state.obj.a.b.c}


          ??????????????????${state.obj.a.b.c}/>
          ??????????????????

          ${state.msg}


          ??????????????????

          ${state.a?+?state.a}


          ??????????????????${useChange}>Change
          ??????????????????${usePush}>Push
          ??????????????????${getTit}?class="component1">
          ????????????????????${Component1(state.msg)}
          ??????????????????

          ??????????????
          ??????????`;
          ????????}

          ????????function?getTit(event)?{
          ????????????updateView(()?=>?{
          ????????????????state.msg?=?event.detail.title;
          ????????????})
          ????????}

          ????????function?useChange()?{
          ????????????updateView(()?=>?{
          ????????????????state.arr.splice(1,?1,?{
          ????????????????????id:?'0',
          ????????????????????txt:?'0'
          ????????????????});
          ????????????})
          ????????}

          ????????let?count?=?5;
          ????????function?usePush()?{
          ????????????updateView(()?=>?{
          ????????????????//?state.obj.a.b.c?=?3;
          ????????????????//?state.style.color?=?'blue';
          ????????????????//?state.arr.length?=?2;
          ????????????????//?state.arr[1]?=?{
          ????????????????//?????id:?'4',
          ????????????????//?????txt:?'4'
          ????????????????//?}
          ????????????????//?state.msg?=?'world';
          ????????????????let?a?=?count++;
          ????????????????state.arr.push({
          ????????????????????id:?a,
          ????????????????????txt:?a
          ????????????????})
          ????????????????//?state.arr.pop();
          ????????????????//?state.arr.unshift({
          ????????????????//?????id:?a,
          ????????????????//?????txt:?a
          ????????????????//?});
          ????????????????//?state.arr.shift();
          ????????????});
          ????????????//?'useFkey'
          ????????}

          ????????Strve('#app',?{
          ????????????data:?{?state?},
          ????????????template:?App
          ????????});
          ????script>
          body>

          html>

          如果你還想深入學(xué)習(xí)其他關(guān)于 Strve.js 的內(nèi)容,你可以繼續(xù)往下閱讀。

          使用

          API

          Strve
          • 參數(shù):

            • string
            • object
          • 詳細(xì):

          初始化Strve.js。第一個(gè)參數(shù)傳入需要掛載到HTML頁面的節(jié)點(diǎn)選擇器名稱。第二個(gè)參數(shù)傳入一個(gè)對(duì)象,第一個(gè)屬性data表示的意思是狀態(tài)對(duì)象,第二個(gè)屬性template表示模板函數(shù)。

          Strve('#app',?{
          ????data:?{?state?},
          ????template:?App
          });
          render
          • 類型:function
          • 詳細(xì):

          render`` 是一個(gè)標(biāo)簽函數(shù),標(biāo)簽函數(shù)的語法是函數(shù)名后面直接帶一個(gè)模板字符串,并從模板字符串中的插值表達(dá)式中獲取參數(shù)。比如說,你可以在模板字符串中直接可以寫HTML標(biāo)簽。

          function?App()?{
          ????return?render`
          ????????
          ????????????

          Hello


          ????????
          ????`
          ;
          }

          如果你使用的是VSCode編輯器,你可以去商店里下載comment-tagged-templates插件,然后,在render`` 中間加上/*html*/

          就像這樣,它可以使HTML標(biāo)簽字符高亮顯示。

          function?App()?{
          ????return?render/*html*/`
          ????????
          ????????????

          Hello


          ????????
          ????`
          ;
          }
          updateView
          • 參數(shù):
            • function
            • string(可選)
          • 詳細(xì):

          第一個(gè)參數(shù)是一個(gè)函數(shù)。函數(shù)體中需要執(zhí)行將改變頁面狀態(tài)的值,例如以下示例中的state.msg

          const?state?=?{
          ????msg:'1'
          };

          function?App()?{
          ????return?render`
          ????????
          ????????????${useChange}
          >change
          ????????????

          {state.msg}


          ????????
          ????`;
          }

          function?useChange()?{
          ????updateView(()?=>?{
          ????????state.msg?=?'2';
          ????});
          }

          第二個(gè)參數(shù)是字符串類型,在當(dāng)你使用列表渲染頁面時(shí),在列表頭部插入數(shù)據(jù)需要綁定useFkey字段,以避免DOM節(jié)點(diǎn)重復(fù)渲染。

          const?state?=?{
          ????arr:?[1,?2]
          };

          function?Home()?{
          ????return?render`
          ????????
          ????????????${useUnshift}
          >unshift
          ????????????

            ????????????????${state.arr.map((item)?=>?render`
          • ${item}
          • `
            )}

            ????????????

          ????????

          ????`
          }

          function?useUnshift()?{
          ????updateView(()?=>?{
          ????????state.arr.unshift('2');
          ????},?'useFkey')
          }
          emitEvent
          • 參數(shù):

            • string
            • dictionary
            • string
          • 詳細(xì):

          自定義事件,一般是用于子組件數(shù)據(jù)傳入父組件。第一個(gè)參數(shù)是表示 event 名字的字符串。第二個(gè)參數(shù)一個(gè)字典類型參數(shù)。

          • "detail",可選的默認(rèn)值是 null 的任意類型數(shù)據(jù),是一個(gè)與 event 相關(guān)的值。
          • bubbles 一個(gè)布爾值,表示該事件能否冒泡。來自 EventInit。注意:測(cè)試chrome默認(rèn)為不冒泡。
          • cancelable 一個(gè)布爾值,表示該事件是否可以取消。

          第三個(gè)參數(shù)是一個(gè)字符串類型,主要是節(jié)點(diǎn)選擇器的名稱,這里的節(jié)點(diǎn)指的是子組件在父組件中外層包裹的DOM節(jié)點(diǎn)。

          例如:

          function?Component1(v)?{
          ????return?render`
          ????????${emitData}
          >${v}
          ????`
          }

          function?emitData()?{
          ????emitEvent('getTit',?{
          ????????detail:?{?title:?'This?is?title!'?},
          ????},?'.component1')
          }

          function?App()?{
          ????return?render`
          ????????
          ????????????${getTit}
          ?class="component1">
          ????????????${Component1(state.msg)}
          ????????????

          ????????
          ????`;
          }

          function?getTit(event)?{
          ????updateView(()?=>?{
          ????????console.log(event.detail.title);
          ????????state.msg?=?event.detail.title;
          ????})
          }

          插值

          Strve.js 使用了基于 JavaScript 的模板字符串語法,允許開發(fā)者聲明式地將 DOM 綁定至底層實(shí)例的數(shù)據(jù)。所有 Strve.js 的模板字符串都是合法的 HTML,所以能被遵循規(guī)范的瀏覽器和 HTML 解析器解析。

          在底層的實(shí)現(xiàn)上,Strve.js 將模板字符串編譯成虛擬 DOM 渲染函數(shù),并把 DOM 操作次數(shù)減到最少。

          在Strve.js中,你可以盡情的使用JavaScript 的模板字符串,感受它獨(dú)特的魅力吧!

          文本

          數(shù)據(jù)綁定最常見的形式就是使用符號(hào)${}的文本插值:

          const?state?=?{
          ????msg:?'hello'
          };

          function?App()?{
          ????return?render`
          ????????
          ????????????

          ${state.msg}


          ????????
          ????`
          ;
          }

          另外你還可以使用更簡(jiǎn)便的方法符號(hào){},同樣可以達(dá)到預(yù)想的效果。

          const?state?=?{
          ????msg:?'hello'
          };

          function?App()?{
          ????return?render`
          ????????
          ????????????

          {state.msg}world


          ????????
          ????`
          ;
          }

          但是,使用這種符號(hào){}需要注意的是,它只適用于標(biāo)簽內(nèi)的文本插值。例如如下這種情況,它是不起作用的,不過你可以使用強(qiáng)大的符號(hào)${}

          //?Bad
          function?App()?{
          ????return?render`
          ????????
          ????????????
          ????????
          ????`
          ;
          }

          //?Good
          function?App()?{
          ????return?render`
          ????????
          ????????????${state.msg}
          />
          ????????
          ????`;
          }
          表達(dá)式

          目前僅支持在符號(hào)${}中使用表達(dá)式。

          例如:

          const?state?=?{
          ????a:?1,
          ????b:?2
          };

          function?App()?{
          ????return?render`
          ????????
          ????????????

          ${state.a?+?state.b}


          ????????
          ????`
          ;
          }

          屬性綁定

          前面,我們可以看到使用符號(hào)${}可以與屬性value綁定值。

          function?App()?{
          ????return?render`
          ????????
          ????????????${state.msg}
          />
          ????????
          ????`;
          }

          另外,你還可以綁定其他屬性,例如class

          const?state?=?{
          ????isRed:?true
          };

          function?App()?{
          ????return?render`
          ????
          ????????${state.isRed???'red'?:?''}
          >Strve.js


          ????
          `;
          }

          如果你想綁定style屬性,同樣也可以。

          const?state?=?{
          ????msg:?'hello',
          ????style:?{
          ????????color:?'red',
          ????????fontSize:?"40px"
          ????}
          };
          function?App()?{
          ????return?render`
          ????????
          ????????????${state.style}
          ">{state.msg}


          ????????
          ????`;
          }

          條件渲染

          我們也可以使用符號(hào)${},這塊內(nèi)容只會(huì)在指令的表達(dá)式返回 true 值的時(shí)候被渲染。

          const?state?=?{
          ????isShow:?false
          };

          function?App()?{
          ????return?render`
          ????????
          ????????????${useShow}
          >show
          ????????????${state.isShow???render`

          Strve.js

          `
          ?:?''
          ????????}

          ????????
          ????`;
          }

          function?useShow()?{
          ????updateView(()?=>?{
          ????????state.isShow?=?!state.isShow;
          ????});
          }

          列表渲染

          我們可以用符號(hào)${}基于一個(gè)數(shù)組來渲染一個(gè)列表。比如我們使用數(shù)組的map方法來渲染列表,并且可以動(dòng)態(tài)添加數(shù)組項(xiàng)。

          const?state?=?{
          ????arr:?['1',?'2']
          };

          function?App()?{
          ????return?render`
          ????????
          ????????????${usePush}
          >push
          ????????????

            ????????????${state.arr.map((todo)?=>?render`
          • ${todo}
          • `
            )}

            ????????????

          ????????}
          ????????
          ????`;
          }

          function?usePush()?{
          ????updateView(()?=>?{
          ????????state.arr.push('3');
          ????});
          }

          上面我們提到updateView()可以傳入第二個(gè)參數(shù),它是字符串類型,在使用列表渲染頁面時(shí),如果在列表頭部插入數(shù)據(jù)則需要綁定useFkey字段,以避免DOM節(jié)點(diǎn)重復(fù)渲染,這是必須要做的。任何在列表頭部操作的動(dòng)作,如unshiftpop數(shù)組方法都需要加上這個(gè)useFkey字段。其他操作則不需要這樣,內(nèi)部已經(jīng)進(jìn)行了優(yōu)化。

          const?state?=?{
          ????arr:?[1,?2]
          };

          function?Home()?{
          ????return?render`
          ????????
          ????????????${useUnshift}
          >unshift
          ????????????

            ????????????????${state.arr.map((item)?=>?render`
          • ${item}
          • `
            )}

            ????????????

          ????????

          ????`
          }

          function?useUnshift()?{
          ????updateView(()?=>?{
          ????????state.arr.unshift('2');
          ????},?'useFkey')
          }

          事件處理

          我們可以使用on指令來監(jiān)聽 DOM 事件,并在觸發(fā)事件時(shí)執(zhí)行一些 JavaScript。我們推薦使用這種onClick駝峰式命名方法,當(dāng)然,直接使用onclick這種全小寫方式也可以。

          需要使用符號(hào)${}來綁定事件。

          function?App()?{
          ????return?render`
          ????????
          ????????????${useClick}
          >sayHello
          ????????}
          ????????
          ????`;
          }

          function?useClick()?{
          ????console.log('hello');
          }

          與Vue.js搭配

          Strve.js不僅可以單獨(dú)使用,也可以與Vue.js搭配使用。你需要在Vue實(shí)例掛載完成后被調(diào)用Strve()注冊(cè)方法,并且第一個(gè)參數(shù)已經(jīng)在template標(biāo)簽中存在。

          App.vue

          <template>
          ??<div?id="container">
          ????<HelloWorld/>
          ??div>
          template>

          <script>
          import?HelloWorld?,{hello}?from?'./components/HelloWorld.vue';
          import?{?about,state?}?from?'./components/About.vue';
          import?{?render,?Strve?}?from?"strvejs";
          const?AppTm?=?()?=>?render`
          ??????

          ????????${hello()}
          ????????${about()}
          ??????

          `
          ;
          export?default?{
          ??name:?"App",
          ??components:{
          ????HelloWorld
          ??},
          ??mounted()?{
          ????Strve("#container",?{
          ??????data:?{state},
          ??????template:?AppTm,
          ????});
          ??},
          };
          script>

          如果需要與Vue共享一個(gè)方法,推薦在setup方法中使用。

          HelloWorld.vue

          <template>
          ??<div>
          ????<img?src="../assets/logo.png"?alt=""?@click="useCliimg">
          ??div>
          template>
          <script>
          import?{?render?}?from?"strvejs";
          import?styles?from?'../assets/hello/hello.module.css';

          export?const?hello?=?()=>render`
          ${styles.color}
          "?onClick=${useCliimg}>hello
          `

          function?useCliimg(){
          ????console.log(1);
          }

          export?default?{
          ??name:'HelloWorld',
          ??setup(){
          ????return?{
          ??????useCliimg
          ????}
          ??}
          }
          script>

          如果,你想在Vue組件中完全使用Strve.js,當(dāng)然也可以。不過最后,推薦使用export default導(dǎo)出組件名。

          About.vue

          <script>
          import?{?render,?updateView?}?from?"strvejs";
          import?styles?from?'../assets/about/about.module.css';

          export?const?about?=?()=>render`

          ????

          {state.msg}


          ???${styles.color}"?onClick=${useClick}>about

          `

          export?const?state?=?{
          ????msg:"hello"
          }

          function?useClick()?{
          ????updateView(()=>{
          ????????state.msg?=?'world';
          ????})
          }
          export?default?{
          ????name:"About"
          }
          script>

          與React.js搭配

          Strve.js與Vue.js搭配相比,與React.js搭配使用更為靈活。同樣需要在組件第一次渲染完成后調(diào)用Strve()方法注冊(cè)方法。

          App.js

          import?{useEffect}?from?'react'
          import?{Strve,render,updateView}?from?'strvejs';
          import?'./App.css';

          const?state?=?{
          ??msg:"Hello"
          }

          function?Home(){
          ??return?render`${useClick}>{state.msg}`
          }

          function?useClick(){
          ??updateView(()=>{
          ????state.msg?=?"World";
          ??})
          }

          function?App()?{
          ??useEffect(()=>{
          ????Strve(".App",{
          ??????data:{state},
          ??????template:?Home
          ????})
          ??})
          ??return?(<div?className="App">div>);
          }

          export?default?App;

          工具

          create-strve-app

          一套快速搭建Strve.js項(xiàng)目的命令行工具。與早期的腳手架 Create Strve 相比,Create Strve App 更勝一籌,可直接輸入命令快速創(chuàng)建Strve項(xiàng)目。Create Strve App是用Vite來構(gòu)建的,它是一種新型前端構(gòu)建工具,能夠顯著提升前端開發(fā)體驗(yàn)。

          搭建你的第一個(gè) Strve 項(xiàng)目
          npm
          npm?init?strve-app@latest
          yarn
          yarn?create?strve-app
          pnpm
          pnpm?create?strve-app
          選擇模板

          你可以根據(jù)自己的需要選擇對(duì)應(yīng)的模板。

          只包含Strve.js基本使用的功能。此模板適用于項(xiàng)目中僅僅單頁面,沒有跳轉(zhuǎn)其他頁面的應(yīng)用。

          不僅包含了Strve.js的基本使用的功能,而且還包含了Strve Router,適用于跳轉(zhuǎn)多頁面以及稍微復(fù)雜的應(yīng)用。

          create-strve

          在前面我們也簡(jiǎn)單介紹過,Create Strve是基于Strve.js的項(xiàng)目構(gòu)建工具,您可以使用它更方便靈活地搭建頁面。Create Strve同樣是用Vite來構(gòu)建的。

          不過,在這里推薦使用Create Strve App,它相對(duì)安裝更加靈活以及快速。

          安裝

          全局安裝

          npm?install?create-strve?-g

          查看版本

          create-strve?-v

          初始化項(xiàng)目

          create-strve?init?

          strve-router

          Strve Router 是 Strve.js 的官方路由管理器。它與 Strve.js 的核心深度集成,可以輕松構(gòu)建單頁應(yīng)用程序。

          目前只支持Hash模式。

          開始

          嘗試 Strve Router 最簡(jiǎn)單的方法是使用直接導(dǎo)入 CDN 鏈接。您可以在瀏覽器中打開它并按照示例學(xué)習(xí)一些基本用法。

          html>
          <html?lang="en">

          <head>
          ????<meta?charset="UTF-8">
          ????<title>StrveRoutertitle>
          head>

          <body>
          ????<div?id="app">div>
          ????<script?type="module">
          ????????import?{?Strve,?render,?updateView?}?from?'https://cdn.jsdelivr.net/npm/strvejs/dist/strve.esm.js';
          ????????import?StrveRouter?from?'https://cdn.jsdelivr.net/npm/strve-router/dist/strve-router.esm.js';

          ????????const?state?=?{
          ????????????msg:?'Hello!'
          ????????};

          ????????const?strveRouter?=?new?StrveRouter([{
          ????????????path:?'/',
          ????????????template:?Home
          ????????},?{
          ????????????path:?'/about',
          ????????????template:?About
          ????????}]);

          ????????strveRouter.routerHashUpdate(updateView,?()?=>?{
          ????????????console.log(strveRouter.param2Obj());
          ????????});

          ????????function?Home()?{
          ????????????return?render`
          ????????????????
          ????????????????????${goAbout}
          ">goAbout
          ????????????????????

          Home


          ????????????????
          ????????????`

          ????????}

          ????????function?About()?{
          ????????????return?render`
          ????????????????
          ????????????????????${goback}
          ">goback
          ????????????????????${goHome}">goHome
          ????????????????????

          About


          ????????????????
          ????????????`
          ????????}

          ????????function?App()?{
          ????????????return?render`
          ??????????????
          ????????????????

          {state.msg}


          ????????????????${strveRouter.routerView()}
          ??????????????
          ??????????`
          ;
          ????????}

          ????????function?goback()?{
          ????????????strveRouter.back();
          ????????}

          ????????function?goAbout()?{
          ????????????console.log('goAbout');
          ????????????strveRouter.routerLink({
          ????????????????path:?'/about',
          ????????????????query:?{
          ????????????????????id:?1,
          ????????????????????name:?"maomin"
          ????????????????}
          ????????????});
          ????????}

          ????????function?goHome()?{
          ????????????console.log('goHome');
          ????????????strveRouter.routerLink('/');
          ????????}

          ????????Strve('#app',?{
          ????????????data:?{?state?},
          ????????????template:?App
          ????????});
          ????script>
          body>

          html>
          安裝
          npm
          npm?install?strve-router
          yarn
          yarn?add?strve-router
          pnpm
          pnpm?add?strve-router
          使用

          如果在一個(gè)模塊化工程中使用它,可以引入StrveRouter對(duì)象,然后實(shí)例化。參數(shù)是需要注冊(cè)的路由組件,path屬性代表路徑,template屬性代表引入的組件。

          匹配到相應(yīng)的路徑頁面會(huì)相應(yīng)的更新,所以這里必須注冊(cè)一個(gè)routerHashUpdate()方法,然后第一個(gè)參數(shù)傳入updateViewAPI,第二個(gè)參數(shù)則是一個(gè)自定義方法。最后導(dǎo)出strveRouter實(shí)例。

          比如這里在一個(gè)router文件夾下創(chuàng)建一個(gè)index.js文件。

          import?StrveRouter?from?'strve-router';
          import?{updateView}?from?'strvejs';

          import?Home?from?'../template/homepage.js';
          import?About?from?'../template/aboutpage.js';

          const?strveRouter?=?new?StrveRouter([{
          ????path:?'/',
          ????template:?Home
          },?{
          ????path:?'/about',
          ????template:?About
          }]);

          strveRouter.routerHashUpdate(updateView,()=>{
          ????console.log('router');
          });

          export?default?strveRouter

          路由匹配到的組件將渲染到routerView()方法所在的地方,一般會(huì)放在主頁面入口文件下(例如App.js)。

          import?{?render?}?from?'strvejs';
          import?strveRouter?from?'./router/index';
          function?template()?{
          ??return?render`
          ????????
          ????????${strveRouter.routerView()}
          ????????
          ????`
          ;
          }

          export?default?template;

          如果需要跳轉(zhuǎn)到對(duì)應(yīng)頁面,使用strveRouter.routerLink()方法,可以傳對(duì)應(yīng)的路徑和需要傳的參數(shù),也可以直接傳一個(gè)路徑字符串。

          import?{?render?}?from?'strvejs'
          import?strveRouter?from?'../router/index.js'

          function?Home(){
          ????return?render`
          ????????

          ????????????${goAbout}">goAbout
          ????????????

          Home


          ????????

          ????`

          }

          function?goAbout(){
          ????strveRouter.routerLink({
          ????????path:?'/about',
          ????????query:?{
          ????????????id:?1,
          ????????????name:?"maomin"
          ????????}
          ????});
          }

          export?default?Home

          如果你需要實(shí)現(xiàn)后退、前進(jìn)跳轉(zhuǎn)頁面這樣操作時(shí),同樣提供了幾個(gè)方法。

          另外,如果你執(zhí)行了路由傳參的操作,想獲取參數(shù)對(duì)象。直接執(zhí)行strveRouter.param2Obj()方法就可以獲取對(duì)象信息。

          最后,我們已經(jīng)給你預(yù)裝了項(xiàng)目配置,你可以使用Create Strve App選擇strve-apps模板即可。

          其它

          IDE支持

          Visual Studio Code

          打開設(shè)置下的settings.json,加入如下代碼:

          "emmet.triggerExpansionOnTab":?true,
          "emmet.showAbbreviationSuggestions":?true,
          "emmet.showExpandedAbbreviation":?"always",
          "emmet.includeLanguages":?{
          ????"javascript":?"html"
          }

          下載comment-tagged-templates插件。在render``方法中間加上/* html */

          function?App()?{
          ????return?render/*?html?*/`
          ????????
          ????????????

          ${state.msg}


          ????????
          ????`
          ;
          }

          UI框架

          https://v5.bootcss.com/

          https://www.tailwindcss.cn/

          更新日志

          v2.1.0
          v2.0.0

          關(guān)于作者

          結(jié)語

          因?yàn)槠脑颍疫@里先介紹這么多吧!有感興趣的朋友可以打開官方文檔去了解一下Strve.js,做幾個(gè)小項(xiàng)目玩一下。

          https://github.com/maomincoding/strve/

          https://maomincoding.github.io/strvejs-doc/zh/

          還有如果有交流學(xué)習(xí)的朋友可以在下面留言或者關(guān)注我,我們一起加油!

          這一篇也是2021年最后一篇了,感謝大家對(duì)我的支持,祝大家在新的一年里身體健康,萬事如意。




          點(diǎn)此卡片,即可關(guān)注我
          瀏覽 34
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  豆花淫荡视频 | 特色一及片免费看 | 女人高潮av | 亚洲欧洲免费在线观看 | 91视频强奸乱伦家庭国产 |