容我思考思考文章結構,可以更容易讓新手入門,思考的過程當中被小編拒了一次,囧。本文將會從項目開發角度出發,由外向內拆解,自頂而下設計javascript
項目地址css
效果圖html
暗黑風是否是很炫~Step by step,follow me~前端
vue.js 官網教程vue
vuex 官方教程
核心思想java
vue-router 官方教程node
webpack 官方教程webpack
node.js 官方git
對於知識儲備這類事,無需多言,尤爲是node橫空出世以後,前端技能棧突飛猛進,學海無涯!一開始看不懂沒關係,書讀百遍,其義自現!做爲一名「碼農」, 更要增強閱讀能力+實操能力結合。
安裝nodejs,這個不贅述了
安裝vue-cli,這是vue.js官方推薦的大中型項目構建工具腳手架
npm install -g vue-cli
初始化項目,選擇webpack做爲資源打包工具
vue init webpack workbook(eslint,karma,e2e test等都選擇n) cd workbook npm install npm run dev // 打開 http://localhost:8080,應該能看到頁面
安裝相關依賴,我們把本次能用到的依賴安裝一下
npm install -D vue-router vuex marked highlight.js // -D 和 --save-dev 等效,marked是markdown 語法轉換工具庫
ok,項目初始化工做結束,我們來思考用vue+vuex+vue-router來構建頁面吧。
Oh Yeah! 組件化設計!
因爲我們後面幾乎全部的工做都在src文件夾下完成,因此咱們先來看看咱們將來的結構吧
├── App.vue //初始化工做,以及掛載路由的router-view組件 ├── assets //靜態資源文件 │ └── darkness.css //暗黑風stylesheet ├── components //組件放在這兒 │ ├── rawEditor.vue //markdown 文本編輯器組件 │ └── renderEditor.vue //渲染後的展現組件 ├── main.js //入口程序 ├── router.js //SPA 路由配置文件 ├── views //頁面 │ ├── 404.vue // 除'/'之外的非法路由,一概指向404 │ └── index.vue // '/'路由指向頁面,內含 rawEditor.vue & renderEditor.vue └── vuex ├── actions.js //vuex理念中 actions -> dispatch ├── getters.js //vuex 理念中 Getters Can Return Derived State,簡言之,組建裏面的狀態都經過getters來獲取 └── store.js //vuex 理念中 initial state,mutations,相應dispatch-》mutations-》從而完成對state的更新
1. 在 src 根目錄下建立 router.js
//router.js export default (router)=>router.map({ '/':{ name:'index',//應用首頁 component:require('./views/index') //加載index頁面 }, '*':{//除'/'之外的全部路由,均跳轉到404頁面 name:'404', component:require('./views/404')// 加載404頁面 } })
2. 修改 main.js 入口文件,咱們要加上 vue-router
//main.js import Vue from 'vue' import App from './App' import VueRouter from 'vue-router' import configRouter from './router' require('./assets/darkness.css') Vue.use(VueRouter) const router = new VueRouter() configRouter(router)//注入路由規則 router.start(Vue.extend(App),'#app')//#app是what 鬼,哪裏來的? /* 細心或者有經驗的同窗可能已經發現,在整個項目的根目錄有個index.html 文件,這個其實才是咱們整個應用的第一入口,SPA(Single Page App)完美的解釋,咱們來修改一下它吧。 */ //index.html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>workbook</title> <style type="text/css"> html,#app { height:100%; } body{ width: 100%; height: 100%; margin:0; padding:0; } </style> </head> <body> <div id="app"></div> <!-- built files will be auto injected --> </body> </html>
3. 修改 App.vue
//app.vue 瞧好了,vue 組件大法來了 <template> <div id="main"> <router-view></router-view> //路由組件 </div> </template> <script> import store from './vuex/store' //後面講vuex 配置會提到 export default { store } </script> <style> #main { width:100%; height:100%; } </style>
4. 開始寫咱們的兩個頁面吧
在src目錄下,新建views文件夾,存放咱們的頁面,index.vue & 404.vue
//index.vue <template>//對照頁面佈局草稿圖,分別把兩個組件加載進來 <raw-editor></raw-editor> <render-editor></render-editor> </template> <script> import rawEditor from '../components/rawEditor' import renderEditor from '../components/renderEditor' export default { components:{ rawEditor, renderEditor } } </script> //404.vue 簡單到使人髮指,不過我只是爲了實現router功能,請開恩。 <template> <h1>404</h1> </template> <script> export default { } </script>
5. 開始寫具體組件
在寫組件以前,咱們先靜靜地思考一下
代碼都寫了快一大半了,怎麼還不見飽守吹捧的vuex登場。OK!如你所願,不過在vuex登場以前,我們能否拿出紙和筆 或者 頭腦風暴一下,想一想我們的應用的state應該是什麼!!!
BingGo! rawHtml
和renderHtml
,簡簡單單的兩個state,就可以知足咱們的應用需求。
rawHtml
和renderHtml
之間又有什麼關係呢?
rawHtml
通過轉換以後給renderHtml
賦值
Jack:我以爲是時候引入 Vuex 了
在src 文件夾下 新建vuex文件夾,建立store.js ,getters.js,actions.js
//store.js import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex); const state = { rawHtml:'', renderHtml:'' } //這塊是重點,可以改變state的只可以在 mutations完成!!! const mutations = { MARKDOWN_SUCCESS(state,_rawHtml,content){ console.log(_rawHtml,content) state.rawHtml = _rawHtml state.renderHtml = content } } //最後別忘了,這塊要export 出去,還記得咱們在編寫app.vue 的時候 引入的store,就是這個,SPA只須要在最頂層的app.vue 引用一次便可。 export default new Vuex.Store({ state, mutations }) //getters.js 簡單到不像,getters存在的意義就是 純粹!! export const getRawHtml = (state)=>state.rawHtml; export const getRenderHtml = (state)=>state.renderHtml; //actions.js 還記得vuex核心思想的那張數據流圖,還有上面我描述src的完成狀態的關於 vuex裏面各文件的意義所在,actions.js 說白了,就是處理玩rawHtml以後,dispatch 結果到 mutations,剩下更新state的工做交給mutations import Vue from 'vue' import marked from 'marked'; //marked配置文件 marked.setOptions({ renderer: new marked.Renderer(), gfm: true, tables: true, breaks: false, pedantic: false, sanitize: true, smartLists: true, smartypants: false, highlight: function (code) { return require('highlight.js').highlightAuto(code).value; } }); export const renderHtml = ({dispatch},e)=>{ var _renderHtml = marked(e.target.value) return dispatch('MARKDOWN_SUCCESS',e.target.value,_renderHtml) }
繼續咱們的組件工做:
這個項目很簡單,兩個組件,一個是rawEditor 還有一個是 renderEditor,至於爲何要起這個名字,who knows!在components 文件夾下建立rawEditor.vue 和renderEditor.vue文件。
往下走,可能有點複雜,千萬別退縮,多是我表述不夠清楚,可是move on,你就能收穫整片天空。
//rawEditor.vue <template> <div id="raw-editor"> <textarea :value="rawHtml" @input="renderHtml" class="form-control"> </textarea> </div> </template> <script> //設計思想就是rawHtml內容已改變,就會觸發renderHtml方法 import {renderHtml} from '../vuex/actions' import {getRawHtml} from '../vuex/getters' export default { vuex:{//看到沒,裏面有個 vuex 對象,actions和getters二者相得益彰 actions:{ renderHtml //內容改變觸發 }, getters:{ rawHtml:getRawHtml//得到rawHtml } }, } </script> <style> #raw-editor { float:left; width:45%; height:100%; } textarea{ width: 100%; height:100%; border: 0; border-radius: 0; } </style> //renderEditor.vue <template> <div id="render-editor"> {{{renderHtml}}} </div> </template> <script> import {getRenderHtml} from '../vuex/getters' export default { vuex:{ //看到沒,裏面有個 vuex 對象 getters:{ renderHtml:getRenderHtml } } } </script> <style> #render-editor { float:right; width:50%; height:100%; overflow: scroll; } </style>
//打開命令行or terminal 工具,運行一下吧 npm run dev
等待一會編譯完成後,打開 http://localhost:8080,查看效果,怎麼樣,是否是很酷!
好吧!你們發現了,咱們的樣式不夠酷炫,也不是 暗黑風。退貨、老闆給差評!在src/assets文件夾中新建 darkness.css
pre, code { font-family: Menlo, Monaco, "Courier New", monospace; } pre { padding: .5rem; line-height: 1.25; overflow-x: scroll; } @media print { *, *:before, *:after { background: transparent !important; color: #000 !important; box-shadow: none !important; text-shadow: none !important; } a, a:visited { text-decoration: underline; } a[href]:after { content: " (" attr(href) ")"; } abbr[title]:after { content: " (" attr(title) ")"; } a[href^="#"]:after, a[href^="javascript:"]:after { content: ""; } pre, blockquote { border: 1px solid #999; page-break-inside: avoid; } thead { display: table-header-group; } tr, img { page-break-inside: avoid; } img { max-width: 100% !important; } p, h2, h3 { orphans: 3; widows: 3; } h2, h3 { page-break-after: avoid; } } a, a:visited { color: #01ff70; } a:hover, a:focus, a:active { color: #2ecc40; } .retro-no-decoration { text-decoration: none; } html { font-size: 12px; } @media screen and (min-width: 32rem) and (max-width: 48rem) { html { font-size: 15px; } } @media screen and (min-width: 48rem) { html { font-size: 16px; } } body { line-height: 1.85; } p, .retro-p { font-size: 1rem; margin-bottom: 1.3rem; } h1, .retro-h1, h2, .retro-h2, h3, .retro-h3, h4, .retro-h4 { margin: 1.414rem 0 .5rem; font-weight: inherit; line-height: 1.42; } h1, .retro-h1 { margin-top: 0; font-size: 3.998rem; } h2, .retro-h2 { font-size: 2.827rem; } h3, .retro-h3 { font-size: 1.999rem; } h4, .retro-h4 { font-size: 1.414rem; } h5, .retro-h5 { font-size: 1.121rem; } h6, .retro-h6 { font-size: .88rem; } small, .retro-small { font-size: .707em; } /* https://github.com/mrmrs/fluidity */ img, canvas, iframe, video, svg, select, textarea { max-width: 100%; } html, body { background-color: #222; min-height: 100%; } html { font-size: 18px; } body { width: 100%; color: #fafafa; font-family: "Courier New"; line-height: 1.45; padding: .25rem; } pre { background-color: #333; } blockquote { border-left: 3px solid #01ff70; padding-left: 1rem; }
不行,代碼部分然而並無高亮,老闆,我要退貨!
//在 index.html的head 裏面加上 <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.4.0/styles/default.min.css">
這樣我們的暗黑風的在線markdown日記應用就暫告一段落了,文中表述若是有不清不楚的,歡迎留言。同時我也是一命 new vuer,但願老鳥們可以指點!