天天看點

一個vue小demo代碼介紹

上篇文章說道,前段時間忙裡偷閑,試了一下vue,搞了個小demo作為練習。原本以為很簡單,但實際上耗費時間超出我的想象。如果有客觀原因,是vue有自己的私貨,另外一個就是缺乏完整的示例,幫助文檔搞成手冊形式,例子很少,即使有也是支離破碎。再就是所謂免費開源的東西,内容和版本都有點随心所欲,很容易就不被支援,玩似的。

閑話休提。先給出demo的樣子。demo很簡單,就2個頁面,再加一個彈窗,但麻雀雖小,demo裡也包含了母版頁,部件,路由,以及使用了jquery和國産界面架構layUI。

一、成果

1、首頁

一個vue小demo代碼介紹

底部點選【Test】出次頁,點選【About】彈出關于。2、次頁

一個vue小demo代碼介紹

3、彈出視窗

一個vue小demo代碼介紹

二、代碼檔案結構

一個vue小demo代碼介紹

三、項目搭建

demo最初的基本結構和代碼,我是用vue ui指令來生成的。具體可看這個​​教學視訊​​

四、代碼介紹

  1. 首頁面

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
    })
  }
}      
  1. 主程式

/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
})      

裡面的代碼,主要與路由有關

  1. 路由

/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>      
  1. 模闆頁

/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>      
  1. 子頁

/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. 部件

    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>      
  1. assets

    圖檔是放在 /src/assets/images 下還是放在外面的 /public/images/ ?

這個要看情況。放在assets裡,webpack會處理,第一個是檔案名會加上哈希值,第二個據說如果圖檔比較小,内容就會直接被寫進頁面代碼中,這樣頁面打開時就不用請求了,速度可能會快一點。但如果圖檔比較大,就還是連結。這個說法我是聽别人說的,沒能證明。但對于第一點,如果檔案名加哈希值,好處是内容更新以後,浏覽器沒有緩存的問題;但壞處,如果哈希值每次釋出都是變的,圖檔内容又沒變的話,那麼優點就成為缺點。也許哈希值是不變的,我要了解下。

五、後記