vue 判断两对象是否一致_你的.vue文件就已经是你的文档了
更新:文檔地址:http://vuese.org
昨天發(fā)布了vuese1.0,這是我的一個新的開源項目,用來解析Vue SFC并生成markdown文檔,如下:
HcySunYang/vuese?github.com這篇文章不會介紹如何使用,至于如何使用大家可以查看 readme,這里我們主要說一說實現(xiàn)的思路。
一、動機
你或者你的團隊也許會有一套自己的組件庫(或者是單純的一個組件),通常當你開發(fā)完一個組件之后,你需要手動的編寫markdown文檔,從而讓其他人了解組件是如何使用的。這里的問題在于:假若組件不停的在更新,你就必須要不停的手動維護對應的文檔,使其與組件的功能保持一致。實際上這個過程是有些惡心 的,那么有什么更好的辦法嗎?基于此我才開發(fā)了 vuese 。
二、想法
我們知道一個 vue 組件所暴露的接口無非是 props、events、slots(或scopedSlots) 以及部分 methods。那我們可不可以實現(xiàn)一個工具幫助我們分析一個vue組件并提取這些信息呢?然后自動生成文檔,這樣無論組件如何改動我們都不需要手動維護文檔了,只需要使用該工具重新生成即可。
三、基本思路
對于一個 vue 組件,如果我們拋開 style 和自定義塊,那么它由兩部分組成,即:模板 和 script 塊。甚至如果使用 render 函數(shù)代替模板的話,那么就只剩一下一個 script 了。
對于 props,methods 它們只能在 scirpt 塊內定義,如:
props: {name: String } methods: {clear () {/*...*/} }而對于 slots 則既可以在 script 塊內定義,也可以在模板中定義,如:
<!-- 在模板中定義 --> <div><slot name="header" /> </div>// 在 script 塊內定義了 slots render (h) {return h('div', this.$slots.header) }以上兩種寫法是等價的,所以在提取 slots 信息時即需要考慮模板中的slots,也要兼容 script 塊內的 slots。
而且在函數(shù)式組件中,以下內容都應該作為 slots 處理:
// ctx.slots() render (h, ctx) {return h('div', ctx.slots().xxx) }// ctx.children render (h, ctx) {return h('div', ctx.children) }這也是我們在提取slots信息時需要考慮在內的。
同樣的,對于 events 而言也是既可以出現(xiàn)在模板中,又可以出現(xiàn)在 script 塊中,如下:
<!-- 模板中的 events --> <div @click="$emit('onclear')"></div>// 定義在 script 中的事件 methods: {someMethod () {this.$meit('onclear')} }所以在提取 events 信息時也需要即考慮模板又考慮 script 塊。
對于模板我們默認是 html 語法,對于 script 塊我們默認為 js。我們要做的第一件事兒就是將 html 和 js 單獨提取出來并單獨分析,好在巨人的肩膀厚實,已經(jīng)有了 @vue/component-compiler-utils 模塊和 vue-template-compiler 模塊。其中我們使用 @vue/component-compiler-utils 模塊解析 vue SFC 并分別得到 html(模板) 和 JavaScript(script塊) 的源碼。對于 html 源碼我們可以再次使用 vue-template-compiler 模塊將其解析為模板對應的 AST,然后通過編寫一個 traverse 函數(shù)對其進行分析,讀取slots相關的內容。
而對于 JavaScript 源碼的處理,我選擇了使用 babel7,寫過 babel 插件的同學或許已經(jīng)猜到了實現(xiàn)的思路。我們將源碼交由 @babel/travers 模塊處理,然后通過編寫一些 helper 函數(shù)來輔助我們判斷出哪些是要真正處理的內容即可,如下源碼段所示:
const mainTraveres = {ObjectProperty(path: any) {// Processing nameif (isVueOption(path, 'name')) {if (onName) onName(path.node.value.value)}// Processing propsif (isVueOption(path, 'props')) {// 一些邏輯}// more...} }其中 isVueOption 函數(shù)是我們自己編寫的 helper 函數(shù),來輔助我們判斷一個對象的屬性是否是 Vue 選項對象中的特定屬性,如果是我們就進一步處理就可以了,對于 js 的處理基本都是這個思路,更多內容大家可以查看源碼:https://github.com/HcySunYang/vuese/blob/master/src/parser/parseJavascript.ts
四、生成目標
經(jīng)過上一步的處理,我們可以編寫出一個 parser 模塊,解析并組裝出我們需要的內容,有了需要的內容之后,我們就可以根據(jù)這些信息編寫一個 Render 模塊,本質就是一個代碼生成的過程,至于生成的內容是什么這取決于你想要的目標,vuese 內置的 Render 會根據(jù)這些信息為你生成 markdown 文件,或者生成一個集成 docute 的文檔。但實際上只要你腦洞夠大你可以生成任何東西,試想一下,如果我們的 parser 模塊編寫的更加完善,對一個 vue 組件的分析足夠細致,這樣我們就能拿到一個 vue 組件全部的信息,然后在代碼生成階段將其生成一個 ts compatible 的組件,這不就實現(xiàn)了一個將非js編寫的vue組件轉換為ts兼容的vue組件的插件了嗎?(備注:后來一哥們兒提供了一個更好的辦法來實現(xiàn)這件事兒,為了避免尷尬,我只能說這也是一個思路嘛......)
回到 vuese 內置的 Render 模塊,Render 的結果就是markdown資源,本質就是一個字符串拼接的過程,具體可以查看源碼 https://github.com/HcySunYang/vuese/blob/master/src/render/index.ts ,并不復雜。
實際上 vuese 提供了很多有用的信息和文檔中沒有體現(xiàn)出來的功能,這多會在后續(xù)逐漸補充。舉個例子,使用 vuese 生成的markdown文件大致如下:
你可能已經(jīng)注意到了,在上面的 markdown 文件中包含了很多諸如:
<!-- @vuese:CompName:props:start -->
<!-- @vuese:CompName:props:end -->
之類的注釋,它的作用是告訴 vuese 在生成文檔時要將生成的 markdown 代碼放置在什么位置,如果一個組件還沒有對應的markdown文檔,則新生成之,否則會在已有的文檔基礎上更新。這么做的目的是出于真正使用場景的考慮,因為一個組件的文檔不可能僅僅包含上圖中展示的內容,它還可能包含開發(fā)者自己編寫的demo,和其他描述內容。這樣我們生成文檔的時候就不會覆蓋掉開發(fā)者自己編寫的內容,而是將生成的內容插入到指定的位置。
五、規(guī)劃
目前 vuese 已經(jīng)實現(xiàn)的特性如下:
規(guī)劃中要實現(xiàn)的特性如下:
另外目前還不支持插件系統(tǒng),這也在未來的規(guī)劃當初。并且在我們團隊內部已經(jīng)將其應用在內部的組件庫的文檔維護,也計劃關注 vue3.0 并兼容之。最后 vuese 剛剛發(fā)布有諸多不足之處,但是隨著后續(xù)的更新迭代,它會變得越來越好,也歡迎感興趣的同學共建。
其他規(guī)劃:模板支持 pug、插件系統(tǒng)、還有啥??????
總結
以上是生活随笔為你收集整理的vue 判断两对象是否一致_你的.vue文件就已经是你的文档了的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 房价预测python_详解 Kaggle
- 下一篇: 鸿蒙系统暗黑2,暗黑破坏神2为什么被称为