上篇文章說道,前段時間忙裡偷閑,試了一下vue,搞了個小demo作為練習。原本以為很簡單,但實際上耗費時間超出我的想象。如果有客觀原因,是vue有自己的私貨,另外一個就是缺乏完整的示例,幫助文檔搞成手冊形式,例子很少,即使有也是支離破碎。再就是所謂免費開源的東西,内容和版本都有點随心所欲,很容易就不被支援,玩似的。
閑話休提。先給出demo的樣子。demo很簡單,就2個頁面,再加一個彈窗,但麻雀雖小,demo裡也包含了母版頁,部件,路由,以及使用了jquery和國産界面架構layUI。
一、成果
1、首頁
底部點選【Test】出次頁,點選【About】彈出關于。2、次頁
3、彈出視窗
二、代碼檔案結構
三、項目搭建
demo最初的基本結構和代碼,我是用vue ui指令來生成的。具體可看這個教學視訊
四、代碼介紹
- 首頁面
public/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
<!-- 加載jquery -->
<script type="text/javascript" src="./lib/jquery-1.11.1.min.js"></script>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app">
</div>
</body>
</html>
這個頁面是腳手架自動生成的。這裡面有些類似JSP,ASP的标記“
<% %>
”,似曾相識,再一次印證了前端開發後端(伺服器端)化的感覺。裡面的值,大概來自于 /vue.config.js。這個檔案也是腳手架生成的。裡面的值稍做修改。
// /vue.config.js
module.exports = {
publicPath: process.env.NODE_ENV === 'production' ? './' : '/',//直接給出一個路徑也可以,如:'/res'
chainWebpack: config => {
config
.plugin('html')
.tap(args => {
args[0].title= '資源索引'
return args
})
}
}
- 主程式
/src/main.js
import Vue from 'vue'
import router from './routes'
import notfound from './pages/404.vue'
const app = new Vue({
el: '#app',
data: {
currentRoute: window.location.pathname
},
computed: {
ViewComponent() {
const matchingView = router[this.currentRoute]
return matchingView ?
() => import('' + matchingView) :
notfound
}
},
render(h) {
return h(this.ViewComponent)
}
})
//浏覽器直接輸入位址處理
window.addEventListener('popstate', () => {
app.currentRoute = window.location.pathname
})
裡面的代碼,主要與路由有關
- 路由
/src/routes.js
export default {
'/': './pages/Home.vue',
'/test': './pages/Test.vue'
}
這路由代碼超簡單。但我在路由上花得時間最多。因為許多例子給的都是vue-router,但我試來試去,頁面總是出不來,懷疑是vue-router在我安裝的各種包裡不被支援。官方文檔裡好像也沒提到這個插件,最後隻能放棄了。
路由檔案雖然簡單,但主要由主檔案main.js(見上面的主程式)裡加載:
import router from './routes'
const app = new Vue({
。。。
data: {
currentRoute: window.location.pathname
},
computed: {
ViewComponent() {
const matchingView = router[this.currentRoute]
return matchingView ?
() => import('' + matchingView) : //最主要的一句
notfound
}
},
。。。
})
官方給出的例子中,使用
require("...")
來加載頁面,用下載下傳的例子運作的确可以,但移植到我這個項目裡,卻不行,一模一樣的代碼。猜測是包的問題。我是用腳手架生成的,代碼下來以後,就npm install了,官方這個例子,也許依賴的各種包不一樣,是以導緻require在我這裡就不行,非要import。
官方例子
路由應用,應用了自定義的VLink.vue
<template>
<div class="hlink" id="flink">
<span>
<v-link href="/">Home</v-link>
</span>
<span>
<v-link href="/test">Test</v-link>
</span>
<span id="about" @click="about"><u>About</u></span>
</div>
</template>
<script>import VLink from '../components/VLink.vue'
export default {
components: {
VLink
},
mounted() {},
methods: {
about() {
...
}
}
}</script>
<style>
。。。
</style>
- 模闆頁
/src/layouts/Main.vue,無非就是放置了一個頁頭、頁腳部件。
<template>
<div>
<div>
<Header></Header>
</div>
<div>
<slot></slot>
</div>
<div>
<Footer></Footer>
</div>
</div>
</template>
<script>import Header from '../components/Header.vue'
import Footer from '../components/Footer.vue'
export default {
components: {
Header,
Footer
}
}</script>
<style>
...
</style>
- 子頁
/src/pages/Home.vue
<template>
<main-layout>
<list></list>
</main-layout>
</template>
<script>import MainLayout from '../layouts/Main.vue'
import List from '../components/List.vue'
export default {
components: {
MainLayout,
List,
}
}</script>
<style>
</style>
簡單,應用了模闆頁,以及使用了部件List.vue
-
部件
1)清單
/src/components/List.vue,讀取/public/data/裡的json檔案資料,再顯示出來
<template>
<div class="box">
<div class="left">
<ALink v-for="item in projects" :key="item.id" :href="item.url" :title="item.title"
:note="item.note" :note2="item.note2"></ALink>
</div>
<div class="right">
<ALink v-for="item in apps" :key="item.id" :href="item.url" :title="item.title"
:note="item.note" :note2="item.note2"></ALink>
</div>
</div>
</template>
<script>
import ALink from './Link.vue';
import axios from "axios";
export default {
name: 'AppList',
components: {
ALink
},
data() {
return {
projects: [],
apps:[]
}
},
mounted() {
this.getProjects();
this.getApps();
},
methods: {
getProjects() {
axios.get('./data/projects.json').then(response => {
this.projects = response.data;
})
.catch(error => console.log(error));
},
getApps() {
axios.get('./data/apps.json').then(response => {
this.apps = response.data;
})
.catch(error => console.log(error));
}
}
};
</script>
<style>
...
</style>
json檔案沒什麼特别的
[
{"id":"1","url":"http://192.168.0.22:9999/","title":"共享文檔"},
{"id":"2","url":"http://192.168.0.60/","title":"禅道"},
{"id":"3","url":"http://192.168.0.205:6080/arcgis/rest/services/","title":"205地圖服務"},
{"id":"4","url":"http://192.168.0.22:6080/arcgis/rest/services/","title":"22地圖服務"}
]
2)與路由相關的連結部件
/src/components/VLink.vue
<template>
<a v-bind:href="href" v-bind:class="{ active: isActive }" v-on:click="go">
<slot></slot>
</a>
</template>
<script>import routes from '../routes'
export default {
props: {
href: {
type: String,
required: true
}
},
computed: {
isActive() {
return this.href === this.$root.currentRoute
}
},
methods: {
go(event) {
event.preventDefault()
this.$root.currentRoute = this.href
window.history.pushState(
null,
routes[this.href],
this.href
)
}
}
}</script>
<style scoped>.active {
...
}</style>
7、應用第三方架構layUI
layUI是個國産的UI架構,短小精悍,尤其是彈出視窗,可謂經典。怎麼與vue結合呢?有人弄了個layui-layer,可以用上layUI的彈窗功能。我開始時直接連接配接layUI.js,結果系統無法識别layui對象。
npm i -D layui-layer
/public/index.html裡引用jquery
<script type="text/javascript" src="./lib/jquery-1.11.1.min.js"></script>
vue裡使用
/src/components/Footer.vue
<template>
<div class="hlink" id="flink">
...
<span id="about" @click="about"><u>About</u></span>
</div>
</template>
<script>import layer from 'layui-layer'
import pack from '../../package.json'
export default {
data(){
return {
publicPath:process.env.BASE_URL
}
},
mounted() {},
methods: {
about() {
let version = pack.dependencies.vue;//vue版本号
let content = `<div style='text-align:center;'>
<div><img src='` + this.publicPath + `images/vue.png' /></div>
<div class='ver'><span>Vue version:</span><span>` + version + `</span></div>
</div>`;//路徑比較麻煩
layer.open({
type: 1,
skin:'layui-layer-molv',
title: '關于',
maxmin: false,
shade: 0.75,
id: 'lay_about',
moveType: 1,
area: ['450px', '350px'],
btn: ['确定'],
btnAlign: 'c',
content: content
});
}
}
}</script>
<style>
...
</style>
-
assets
圖檔是放在 /src/assets/images 下還是放在外面的 /public/images/ ?
這個要看情況。放在assets裡,webpack會處理,第一個是檔案名會加上哈希值,第二個據說如果圖檔比較小,内容就會直接被寫進頁面代碼中,這樣頁面打開時就不用請求了,速度可能會快一點。但如果圖檔比較大,就還是連結。這個說法我是聽别人說的,沒能證明。但對于第一點,如果檔案名加哈希值,好處是内容更新以後,浏覽器沒有緩存的問題;但壞處,如果哈希值每次釋出都是變的,圖檔内容又沒變的話,那麼優點就成為缺點。也許哈希值是不變的,我要了解下。