1. 程式人生 > >一步一步學Vue(八)

一步一步學Vue(八)

nod png 路由配置 ring 圖片 sca -a 基本 routes

本篇完成如下場景:

1、系統包含首頁、客戶信息查詢、登錄三個模塊

2、默認進入系統首頁,如果要進行用戶查詢,則需要進行登錄授權

3、查詢用戶後點擊列表項,則進入詳情頁面

基於上述場景需求描述,在客戶端我們考慮,需要設計如下組件:Home組件、客戶列表組件、客戶詳情組件、登錄組件

在服務器端考慮需要:用戶認證服務;客戶列表查詢服務、客戶詳情查詢服務。

ok,現在我們從上往下,先創建我們的基本目錄結構,

當前目錄結構如下:

app.js node web 啟動文件

node_modules node模塊文件(關於node模塊安裝這裏不再介紹)

public 存放靜態文件比如index.html 瀏覽器端執行的css或者js文件、圖片、文字等等。當前包含兩個文件 index.html,app.js (組件定義等文件)

router 後端路由文件,比如可以把portal部分進行抽象到路由文件夾

middleware 中間件 文件夾,我們會定義鑒權中間件

package.json npm包配置文件

由我們的客戶端開始設計,構建我們的組件:

首先Home組件,Home組件,簡單的potal信息展示,這裏為了演示,就直接顯示一串基本信息,在public/app.js中添加如下代碼:

var HomeComponent = {
    template: `<div>
        <h1>Home 頁面,portal頁</h1>
        <h2>以下數據來自服務端</h2>
        {{stat}}
    
</div>`, data:function(){ return { stat:‘‘//代表相關統計信息等 } }, methods:{ getStat:function(){ return axios.get(‘/portal‘); } }, created:function(){ this.getStat().then(res=>{ this.stat=JSON.stringify(res.data); }).
catch(err=>{ console.log(err); }) } }

這裏一個新的知識axios,這是一個vue的Ajax庫,由於vue-resource已不再更新,官方推薦使用axios;上述代碼邏輯很簡單,在組件初始化時,請求後端數據,返回後進行簡單的數據綁定;對應的後端接口(數據只是模擬),在/app.js下添加如下代碼:

var express = require("express");


var app = express();

app.use(express.static(‘public‘));
app.get(‘/portal‘,function(req,res){
    res.json({
        data:[
            {
                visits:12,
                clicks:100
            },
            {
                location:‘BeiJing‘,
                total:17
            }
        ]
    })
})


app.listen(8110,function(){
    console.log("port 8110 is listenning!!!");
});

這裏就是最基礎的express代碼了,只是做了兩件事情,第一,設置靜態目錄為public,設置路由/portal,對應前端請求。

為了讓程序運行起來,我們修改我們的/public/index.html代碼如下:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>demo3</title>
    <script src="https://cdn.bootcss.com/vue/2.4.1/vue.js"></script>
    <script src="https://cdn.bootcss.com/vue-router/2.7.0/vue-router.js"></script>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>


</head>

<body>
    <div id="app">
      
    </div>
    <script src="./app.js"></script>
</body>

</html>

在public/app.js中為組件Home設置路由,並啟用路由配置:

var router = new VueRouter({
    //TODO:各種路由定義;
    routes: [{
        name: ‘home‘, path: ‘/home‘, component: HomeComponent
    }
    
    ]
});
var app = new Vue({
    router: router,
    template: `
    <div>
          <router-view></router-view>
    </div>
    `,
    el: ‘#app‘
});

打開控制臺,進入到項目根目錄,執行node app.js 啟動後臺服務,在瀏覽器打開http://localhost:8110/#/home ,可以看到如下效果:

技術分享

接下來,在public/app.js文件中添加我們的另外三個組件:客戶列表組件,詳情組件和登錄組件,並配置路由,最終代碼如下:

var LoginComponent = {
    template: `
    
     <div class="login" >
        username:<input type="text" v-model="user.username" />
        password:<input type="password" v-model="user.password" />
        <input type="button" @click="login()" value="login" />
     </div>
    `,
    data: function () {
        return {
            user: {
                username: ‘‘,
                password: ‘‘
            }
        }
    },
    methods: {

        login: function () {
            axios.post(‘/login‘,{params: this.user})
                .then(function (res) {
                    if (res.success) {
                        localStorage.setItem(‘token‘, res.token);
                    }
                })
                .catch(function (error) {
                    console.log(error);
                });

        }
    }
}

var CustomerListComponent = {
    template: `
<div>
    <div>
        <input type="text" v-model="keyword" /> <input type="button" @click="getCustomers()" value="search" />
    </div>
    <ul>
        <router-link v-for="c in customers"  tag="li" :to="{name:‘detail‘,params:{id:c.id}}" :key="c.id">{{c.name}}</router-link>
    </ul>
</div>
    `,
    data: function () {
        return {
            customers: [],
            keyword: ‘‘
        }
    },
    created: function () {
        this.getCustomers();
    },
    methods: {
        getCustomers: function () {
            axios.get(‘/api/getCustomers‘, { params: { keyword: this.keyword } })
                .then(res => { this.customers = res.data; console.log(res) })
                .catch(err => console.log(err));
        },

    }
}


var CustomerComponent = {
    template: `
        <div>
            {{customer}}
        </div>
    `,
    data: function () {
        return {
            customer: {}
        }
    },
    created: function () {
        var id = this.$route.params.id;
        this.getCustomerById(id);
    },
    watch: {
        ‘$route‘: function () {
            console.log(this.$route.params.id);
        }
    },
    methods: {
        getCustomerById: function (id) {
            axios.get(‘/api/customer/‘+id)
                .then(res => this.customer = res.data)
                .catch(err => console.log(err));
        }
    }
}



var HomeComponent = {
    template: `<div>
        <h1>Home 頁面,portal頁</h1>
        <h2>以下數據來自服務端</h2>
        {{stat}}
    </div>`,
    data: function () {
        return {
            stat: ‘‘//代表相關統計信息等
        }
    },
    methods: {
        getStat: function () {
            return axios.get(‘/portal‘);
        }
    },
    created: function () {
        this.getStat().then(res => {
            this.stat = JSON.stringify(res.data);
        }).catch(err => {
            console.log(err);
        })
    }
}

var router = new VueRouter({
    //TODO:各種路由定義;
    routes: [{
        name: ‘home‘, path: ‘/home‘, component: HomeComponent
    },
    {
        name: ‘customers‘, path: ‘/customers‘, component: CustomerListComponent,

    },
    {
        name: ‘detail‘, path: ‘/detail/:id‘, component: CustomerComponent,

    },
    {
        name: ‘login‘, path: ‘/login‘, component: LoginComponent
    }
    ]
});

//註冊全局事件鉤子
//TODO:會在下一篇中詳細分析
// router.beforeEach(function (to, from, next) {
//     if (to.matched.some(r => r.meta.auth)) {
//         if (!localStorage.getItem(‘token‘)) {
//             console.log("需要登錄");
//             next({
//                 path: ‘/login‘,
//                 query: { to: to.fullPath }
//             })
//         } else {
//             next();
//         }
//     } else {
//         next()
//     }
// });


var app = new Vue({
    router: router,
    template: `
    <div>
          <router-link :to="{name:‘home‘}" >Home</router-link>
          <router-link :to="{name:‘customers‘}" >Customers</router-link>
          <router-view></router-view>
    </div>
    `,
    el: ‘#app‘
});

後臺根據接口添加如下路由,在router文件夾中,添加customers.js文件,加入如下代碼:

var router = require("express").Router();
var db = require(‘./fakeData‘);

router.get(‘/getCustomers‘, function (req, res) {
    var list = db.data;

    list = list.filter(v => v.name.indexOf(req.query.keyword) !== -1);

    res.json(list);
});

router.get(‘/customer/:id‘,function(req,res){
    var list=db.data;


    var obj=list.filter(v=>v.id==req.params.id)[0];

    res.json(obj);
})

module.exports = router;

同時在/app.js中修改代碼如下:

var express = require("express");

var authMiddleware=require(‘./middleware/authMiddleware‘);
var customerRouter=require(‘./router/customers‘);

var app = express();

app.use(express.static(‘public‘));
app.get(‘/portal‘,function(req,res){
    res.json({
        data:[
            {
                visits:12,
                clicks:100
            },
            {
                location:‘BeiJing‘,
                total:17
            }
        ]
    })
})
//TOOD:下一篇會詳細講,先忽略
// app.use(authMiddleware);

app.use(‘/api‘,customerRouter);



app.listen(8110,function(){
    console.log("port 8110 is listenning!!!");
});

重新執行node app.js,刷新瀏覽器,看到最終效果如下:

技術分享

上述vue的代碼,我們在前面幾篇都有所提及,沒有陌生格式的代碼,大家有疑問的可以提comment。下一篇中會加入授權,包括前端路由控制以及後端接口訪問控制,今天就到這裏吧,最近比較忙,更新進度有點慢,下一篇完善權限,在本部分代碼中已加入todo標示,有興趣的可以考慮一下()。

本篇完整代碼如下:

public/index.html

技術分享
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>demo3</title>
    <script src="https://cdn.bootcss.com/vue/2.4.1/vue.js"></script>
    <script src="https://cdn.bootcss.com/vue-router/2.7.0/vue-router.js"></script>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>


</head>

<body>
    <div id="app">
      
    </div>
    <script src="./app.js"></script>
</body>

</html>
View Code

public/app.js

技術分享
var LoginComponent = {
    template: `
    
     <div class="login" >
        username:<input type="text" v-model="user.username" />
        password:<input type="password" v-model="user.password" />
        <input type="button" @click="login()" value="login" />
     </div>
    `,
    data: function () {
        return {
            user: {
                username: ‘‘,
                password: ‘‘
            }
        }
    },
    methods: {

        login: function () {
            axios.post(‘/login‘, this.user)
                .then(function (res) {
                    if (res.success) {
                        localStorage.setItem(‘token‘, res.token);
                    }
                })
                .catch(function (error) {
                    console.log(error);
                });

        }
    }
}

var CustomerListComponent = {
    template: `
<div>
    <div>
        <input type="text" v-model="keyword" /> <input type="button" @click="getCustomers()" value="search" />
    </div>
    <ul>
        <router-link v-for="c in customers"  tag="li" :to="{name:‘detail‘,params:{id:c.id}}" :key="c.id">{{c.name}}</router-link>
    </ul>
</div>
    `,
    data: function () {
        return {
            customers: [],
            keyword: ‘‘
        }
    },
    created: function () {
        this.getCustomers();
    },
    methods: {
        getCustomers: function () {
            axios.get(‘/api/getCustomers‘, { params: { keyword: this.keyword } })
                .then(res => { this.customers = res.data; console.log(res) })
                .catch(err => console.log(err));
        },

    }
}


var CustomerComponent = {
    template: `
        <div>
            {{customer}}
        </div>
    `,
    data: function () {
        return {
            customer: {}
        }
    },
    created: function () {
        var id = this.$route.params.id;
        this.getCustomerById(id);
    },
    watch: {
        ‘$route‘: function () {
            console.log(this.$route.params.id);
        }
    },
    methods: {
        getCustomerById: function (id) {
            axios.get(‘/api/customer/‘+id)
                .then(res => this.customer = res.data)
                .catch(err => console.log(err));
        }
    }
}



var HomeComponent = {
    template: `<div>
        <h1>Home 頁面,portal頁</h1>
        <h2>以下數據來自服務端</h2>
        {{stat}}
    </div>`,
    data: function () {
        return {
            stat: ‘‘//代表相關統計信息等
        }
    },
    methods: {
        getStat: function () {
            return axios.get(‘/portal‘);
        }
    },
    created: function () {
        this.getStat().then(res => {
            this.stat = JSON.stringify(res.data);
        }).catch(err => {
            console.log(err);
        })
    }
}

var router = new VueRouter({
    //TODO:各種路由定義;
    routes: [{
        name: ‘home‘, path: ‘/home‘, component: HomeComponent
    },
    {
        name: ‘customers‘, path: ‘/customers‘, component: CustomerListComponent,

    },
    {
        name: ‘detail‘, path: ‘/detail/:id‘, component: CustomerComponent,

    },
    {
        name: ‘login‘, path: ‘/login‘, component: LoginComponent
    }
    ]
});

//註冊全局事件鉤子
//TODO:會在下一篇中詳細分析
// router.beforeEach(function (to, from, next) {
//     if (to.matched.some(r => r.meta.auth)) {
//         if (!localStorage.getItem(‘token‘)) {
//             console.log("需要登錄");
//             next({
//                 path: ‘/login‘,
//                 query: { to: to.fullPath }
//             })
//         } else {
//             next();
//         }
//     } else {
//         next()
//     }
// });


var app = new Vue({
    router: router,
    template: `
    <div>
          <router-link :to="{name:‘home‘}" >Home</router-link>
          <router-link :to="{name:‘customers‘}" >Customers</router-link>
          <router-view></router-view>
    </div>
    `,
    el: ‘#app‘
});
View Code

router/customers.js

技術分享
var router = require("express").Router();
var db = require(‘./fakeData‘);

router.get(‘/getCustomers‘, function (req, res) {
    var list = db.data;

    list = list.filter(v => v.name.indexOf(req.query.keyword) !== -1);

    res.json(list);
});

router.get(‘/customer/:id‘,function(req,res){
    var list=db.data;


    var obj=list.filter(v=>v.id==req.params.id)[0];

    res.json(obj);
})

module.exports = router;
View Code

middleware/authMiddleware.js

技術分享
module.exports=function(req,res,next){
    if(req.path="/login"){
        res.json({
            success:true
        })
    }
    next();
}
View Code

app.js

技術分享
var express = require("express");

var authMiddleware=require(‘./middleware/authMiddleware‘);
var customerRouter=require(‘./router/customers‘);

var app = express();

app.use(express.static(‘public‘));
app.get(‘/portal‘,function(req,res){
    res.json({
        data:[
            {
                visits:12,
                clicks:100
            },
            {
                location:‘BeiJing‘,
                total:17
            }
        ]
    })
})
//TOOD:下一篇會詳細講,先忽略
// app.use(authMiddleware);

app.use(‘/api‘,customerRouter);



app.listen(8110,function(){
    console.log("port 8110 is listenning!!!");
});
View Code

一步一步學Vue(八)