zoukankan      html  css  js  c++  java
  • 一步一步学Vue(八)

    本篇完成如下场景:

    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
  • 相关阅读:
    Windows安装node.js
    02ARM体系结构
    01ARM介绍
    01软件过程模型
    创建一个JavaWeb工程
    python之面向对象01
    python学生管理系统
    python文件、文件夹的相关操作
    python文件的定位读写
    python文件的写入与备份
  • 原文地址:https://www.cnblogs.com/Johnzhang/p/7252747.html
Copyright © 2011-2022 走看看