Express、Vue、Vue-Router、Vue-Resource、Webpackcss
Vuehtml
vue 的組件化思想和 React 很像,一個 vue 組件將 html、css 和 js 都寫在一個文件裏面,組件管理和維護本身的數據和狀態,方便編寫也便於調試。vue
Vue-Resourcenode
做爲 vue 全家桶的一員,vue-resource 主要用在 HTTP 請求功能上,相似的工具還有 axios,雖然 vue2.0 推薦使用 axios,可是我的仍是習慣於用 vue-resource,使用起來也十分簡單,在實例中能夠使用如下格式的寫法:jquery
this.$http.post('/someUrl', [body], [options]).then(successCallback, errorCallback);
Vue-Routerwebpack
vue 經過配合 vue-router 來建立單頁應用,其思想是將 vue 組件映射到路由,並將路由掛載到 app 上,在頁面中經過 router-link 和 router-view 來定義頁面路由並切換到不一樣的組件。ios
<!-- html --> <router-link to="/home">Home</router-link> // js import Home from './components/home' const routes = [ { path: '/home', component: Home }, ] const router = new VueRouter({ routes }) const app = new Vue({ router }).$mount('#app')
Express + Vue + Webpackweb
爲何不用腳手架工具?vue-router
針對 React 能夠使用 dva-cli 快速生成項目結構,一樣,vue 也提供了 vue-cli 做爲腳手架工具,使用起來都很是方便,可是使用腳手架工具很明顯的一個問題就是,不一樣的框架經過腳手架生成的項目結構都是不一樣的,而針對一些實際項目,可能這樣的目錄結構並不能很好得符合項目須要,而爲了避免同的項目之間結構的一致性,我的更喜歡使用 express 生成 node 項目,並在 node 項目中手動得引入和使用框架,這樣一方面避免了項目結構的不一致性,同時也更有利於對框架的理解。vue-cli
經典的 node 項目結構配合手動建立的 src 目錄(用來放置全部的組件、入口和路由文件)。
// 安裝依賴 npm install // 項目打包 webpack -w // 啓動項目 npm start
由於項目自己並不複雜,因此這裏僅針對幾個難點和遇到的坑進行簡單的解釋和分析。
一、接口的封裝和數據的請求
應用相關的接口都在node中進行封裝,具體使用到了 request 模塊的 get 和 post 方法,以下:
// 獲取職位列表 router.post('/getJobs', function (req, res, next) { console.log(req.body.jobId); const jobsUrl = 'http://www.fabao.cn/api/FABAO_WEBSITE/job/getjobinfo?nonce=1494212786000§ionid=' + req.body.jobId +'&pageNumber=1&pageSize=20'; console.log(jobsUrl); request(jobsUrl, function (error, response, body) { if(!error && response.statusCode == '200') { res.send(body) } }) })
請求接口在組件中經過 vue-resource 來實現,以下:
getJoblist () { this.$http.post('/getJobs', { jobId }).then(data => { console.log(data); this.items = data.body.res; }, error => { console.log(error); }) }
二、路由地址變化的的監聽
在項目中的新聞詳情頁面有一個點擊按鈕查看上一篇或下一篇新聞的功能:
這裏經過直接在按鈕上定義路由中的新聞 id 的增減的方式來實現,以下:
<router-link :to="{name: 'news', params: {id: data.id - 1}}" replace>{{prevTxt}}</router-link> <router-link :to="{name: 'news', params: {id: data.id + 1}}">{{nextTxt}}</router-link>
可是發現,在點擊了按鈕以後,地址欄中的 url 確實變了,新聞 id 對應的加1或減1,可是頁面內容並無發生變化,針對這個問題,能夠經過監聽router 來解決,以下:
watch: { // 當路由發生變化時自動請求數據 "$route": "getNewsDetail" }
這樣,在 url 發生變化時,就獲取新的 url 地址,並主動請求一次數據,從而實現了內容的更新。
getNewsDetail 方法以下:
getNewsDetail () { // use vue-resource const curId = this.$route.params.id; this.$http.post('/getNewsDetail', {id: curId }).then(data => { if (data.body.res) { this.prevTxt = '上一篇'; this.nextTxt = '下一篇' this.data = data.body.res[0] }else { if (curId > this.initialId) { // 點擊了下一篇 this.nextTxt = '沒有啦'; this.prevTxt = '上一篇'; }else { // 點擊了上一篇 this.prevTxt = '沒有啦' this.nextTxt = '下一篇' } } }, error => { console.log(error); }) }
三、元素的切換和顯示隱藏
使用 jquery 來實現元素的切換和顯示隱藏十分簡單,只要控制元素的display屬性或者show()/hide()方法或者經過添加和移除類名的方式來實現,可是在 vue 中,由於不便於直接操做 dom 元素,因此在實現這樣的效果的時候須要轉換思路。以"加入咱們"頁面的效果爲例:
在實現上方標籤的切換和高亮,以及下方職位列表信息的現實隱藏,都涉及到元素屬性和樣式的變化,這裏主要是經過動態的類名和 v-show 的方式來實現。
首先,崗位標籤的結構以下:
<div class="job-type"> <span @click="getJoblist(6)" :class="{active: activeId == 6}">急招崗位</span> <span @click="getJoblist(7)" :class="{active: activeId == 7}">平常崗位</span> <span @click="getJoblist(8)" :class="{active: activeId == 8}">校園招聘</span> </div>
在這裏,點擊不一樣的標籤會傳入不一樣的參數,並請求不一樣的崗位信息來實現下方列表的更新,同時爲每個標籤都綁定了一個 active 的類名,並經過判斷當前點擊的標籤 id 來控制類名的有無。
getJoblist (jobId) { this.activeId = jobId; this.$http.post('/getJobs', { jobId }).then(data => { console.log(data); this.items = data.body.res; }, error => { console.log(error); }) }
能夠看到,在請求職位列表的方法中,首先便經過傳入的 jobId 來設置當前的標籤 id,由於標籤 id 是定義在 data 中的,因此全部的標籤都共享一個 activeId,所以當點擊了標籤時,傳入的 id 即是當前的標籤 id,對應的類名 active 也就爲真,同時其餘的標籤對應的 active 爲假,經過這種方式來實現類名的控制。
一樣,在下方職位列表信息的現實隱藏上也使用了相似的方式,不一樣的地方在於,在點擊了對應的職位時,不只須要顯示詳細信息,還需明確當前點擊的是哪一項,所以這裏須要用到兩個判斷:
<section class="job-info" @click="showDetail(item.id)"> <h3>{{item.name}}</h3> <div> <address>{{item.company_name}}</address> <span>{{item.type}}</span> <time>{{item.create_date}}</time> </div> </section> <transition name="fade"> <section class="job-detail" v-show="jobId === item.id && ifShow"> <h4>職位描述</h4> <p> <span>崗位職責</span> <pre>{{item.require}}</pre> <span>任職資格</span> <pre>{{item.description}}</pre> </p> </section> </transition>
ifShow 在 組件的 data 中定義,默認爲 false,當點擊列表,觸發showDetail(item.id)方法時,傳入當前列表項的id,並賦值給 jobId,同時修改 ifShow,這樣經過兩個布爾值的綜合判斷,能夠決定當前點擊項對應的詳情是否顯示。