• 利用vue-router和compoment重构代码--踩坑(一)


    业务主要功能

    • 获取所有的数据库列表

    • 点击某一个数据库列表的时候,右侧分页展示数据

    • 点击右侧某一条数据的时候,现实数据详情


    以下是之前的页面,存在以下问题:

    • 前段开发没有工程化(webpack)

    • 主要功能耦合,列表,详情,(检索,重构的是为了加功能方便)

    • 左侧的数据库链接是直接跳页的,分页的链接是跳页的,右侧点击的详情页却是vue-resource加载的

    • 代码结构混乱,之前为了快速实现功能。所有代码写在一个文件上。难读。

    功能效果图

    数据列表页效果



    数据详情效果



    代码重构思路

    • 前段模块化开发,用webpack,参考我

    • 利用compoment组件化,组件化原则:组件只需要告诉别自己什么状态,状态自治。组件不要去要求别的组件做什么

    • 因为用vue就要体验spa,根据页面功能,利用vue-router配置页面路由


    重构开始

    1. 因为功能少,所以就略过了 前段模块化开发,用webpack,参考我这篇

    2. 因为之前所有代码都是写在一个文件的,现在为了代码清晰易读易扩展,将前段js代码拆分为三个文件

      compoments.js对应抽离的组件

    router.js配置路由文件

    show_database.js vue实例

    1. 分别将页面抽成6个组件

    itemsNumber--显示数据条数

    databaseLists--左侧数据库列表

    itemsLists--右侧数据列表

    pagination --底部的分页

    itemDetail --详情页

    listCompoment --vue-router用到的组件包含itemsListspagination

    1. 页面路由暂时分成列表/core/:core和详情/detail/:id两个路由,以后还有个检索页的路由

    因为数据列表和详情的数据是独立接口获取的,这样分符合功能
    (想了很久,没想到更好地想法,第一次接触vue-router,一边文档,一边coding)


    重构中---踩坑--填坑

    一、填坑工具

    二、遇到的那些坑

    • vue-router文档中的一些功能只有在新版本中才有效,一开始怕3.0太冒进了,就选了个2.0,一段时间后发现一些功能死活不成功如:router.push等。细看文档。原来是新版本特有的。所以以后看选版本要对着文档选,实在不行就选择最新的大版本,如3.0

    • vue-router中如何给组件传props?细看文档向路由组件传递 props搞定

    • vue-router中如何监听路由组件中的事件?因为路由组件listCompoment获取到数据库列表中需要向外发送找到的数据

                //发送找到的数据
                this.$emit('num-found',this.numFound);
      

    我记得在官方文档通过事件向父级组件发送消息
    v-on:num-found在组件上监听是官方文档的做法。但是路由组件怎么绑定事件呢?$emit的事件是可以用$on来接受的?;然而试了不可以;

    折腾了很久,直接电话老同学,得知可以直接在router-view中绑定事件监听

    router-view(v-on:num-found='getnumFound')
    
    • 如果是触发事件是包含大写的却不能成功

      this.$emit(:'numFound',this.numFound);
      v-on:numFound

    • 。。。。。。未完待续

    贴代码

    • templates/views/show_database/show_database.pug

        extends ../../layouts/default
        include ../../mixins/footer-js
        include ../../mixins/search_components
        block css
            link(rel="stylesheet", href="/styles/document/document_search.css")    
            style.
                .result_static {
                    padding: 15px 0;
                    margin-bottom: 20px;
                    border: #BDE8F2 1px solid;
                    background-color: #EFF6FA;
                    text-align: center;
                    font-size: 14px;
                }
                .result_static strong {
                    color: #F30;
                    font-size: 18px;
                    font-weight: normal;
                    padding: 0 5px;
                }
                .show_database_item{
                    border-bottom: 1px solid #e5e6e7;
                    margin-top: 15px;
                    padding-bottom: 5px;
                }
                .show_database_item h4{
                    color: #259;
                    box-sizing: border-box;
                    font-size: 14px;
                    font-weight: bold;
                    letter-spacing: 1px;
                    line-height: 16px;
                    text-align: left;
                }
                .show_database_item p{
                    font-weight: normal;
                    text-align: left;
                    word-break: break-all;
                    color: #222;
                    letter-spacing: 1px;
                    font-size: 13px;
                }
        block content
            script(type='text/x-template',id='items_number')
                div.result_static 找到相关数据
                    strong(v-text='number || 0')
                    | 条
            script(type='text/x-template',id='database_lists')
                .list-group
                    a.list-group-item(v-on:click='jumpNew(core.core._id,50,0)',href='javascript:void(0);',v-for="(core,index) in cores",v-bind:key="index", v-bind:class="{'active':core.core._id==currentId}",v-text="core.core.alias || core.core.name")
            script(type='text/x-template',id='items_lists')
                div
                    .col-xs-12(v-for="(item,index) in data",v-bind:key="index")
                        div.show_database_item
                            h4 {{ parseInt(start)+(index+1)}}、
                                a(href='javascript:void(0);',v-on:click.prevent="showDetail(item.id)",v-text="item.name || item.Title || item.title || item.productname")
                            p {{item | content}}
            script(type='text/x-template',id='item_detail')
                .col-xs-12.col-sm-8.col-md-9(v-if="isShowDetail")
                    .row
                        .col-xs-12
                            h5(v-on:click="backFn") 
                                a(href='javascript:void(0);') <<返回
                        .col-xs-12
                            table.table.table-bordered.table-striped(v-if="tableData.length")
                                tbody
                                    tr(v-for="(item,index) in tableData",v-bind:key="index")
                                        td.text-center(v-text="item.name")
                                        td(v-text="item.value")
            script(type='text/x-template',id='pagination')
                div.text-center
                    nav(aria-label="Page navigation")
                        ul.pagination
                            li(v-for="item in pagesList",v-bind:class="{'active':item.show}")
                                a(v-bind:href="''+item.link")
                                    span(v-text="item.label")
            script(type='text/x-template',id='items_search')
            script(type='text/x-template',id='list_compoment')
                .col-xs-12.col-sm-8.col-md-9
                    .row
                        items-lists(v-bind:data='data',v-bind:show-detail='showDetail',v-bind:start='start')
                        pagination(v-bind:pages-list='pagesList')
        
            .row#app
                //- .patent-search-div.row
                    if normalInfo && normalInfo.title
                        div.patent-info.col-sm-3.text-center !{normalInfo.title}
                    else
                        div.patent-info.col-sm-3.text-center 检索
                    .patent-search-main.col-sm-9
                        //检索框
                        +searchBox(normalInfo,keyword)
                .col-xs-12.col-sm-4.col-md-3
                    items-number(v-bind:number='numFound')
                    database-lists(v-bind:cores='cores',v-bind:current-id='currentId',v-bind:jump-new='jumpNew')
                //- .col-xs-12.col-sm-8.col-md-9(v-if="!isShowDetail")
                    .row
                        items-lists(v-bind:data='data',v-bind:show-detail='showDetail',v-bind:start='start')
                        pagination(v-bind:pages-list='pagesList')
                //- item-detail(v-bind:is-show-detail='isShowDetail',v-bind:table-data='tableData',v-bind:back-fn='closeDetail')
                router-view(v-on:num-found='getnumFound')
        block page-js
            script(src="https://cdn.bootcss.com/vue/2.5.16/vue.js")
            script(src="https://cdn.bootcss.com/vue-resource/1.5.0/vue-resource.js")
            script(src="https://cdn.bootcss.com/vue-router/3.0.0/vue-router.js")    
            //- script(src="https://cdn.bootcss.com/vue/2.5.16/vue.min.js")
            //- script(src="https://cdn.bootcss.com/vue-resource/1.5.0/vue-resource.min.js")
            //- script(src="https://cdn.bootcss.com/vue-router/3.0.0/vue-router.min.js")
            script(src="/js/show_database/compoments.js")
            script(src="/js/show_database/router.js")    
            script(src="/js/show_database/show_database.js")
      
    • public/js/show_database/show_database.js

        var vm = new Vue({
            el:'#app',
            data:{
                name:'show_database',
                cores:[],
                currentId:'',
                currentCore:'',
                data:[],
                numFound:0,
                start:0,
                rows:50,
                pagesList:[],
                tableId:'',
                isShowDetail:false,
                detailData:{},
                tableData:[]
            },
            created:function () {
                this.$on('num-found',function (num) {
                    console.log(num);
                })
            },
            mounted:function  () {
                console.log(this.$router.params);
                
                // if (this.$router.params.core) {
                //     this.currentId = this.$router.params.core;
                // }
                // if (this.$router.query.rows) {
                //     this.rows = this.$router.query.rows;
                // }
        
                // if (this.$router.query.start) {
                //     this.start = this.$router.query.rows
                // }
        
                if (location.search) {
                    var search = location.search.slice(1,location.search.length);
                    var l = search.split('&&');
                    for (var index = 0; index < l.length; index++) {
                        var  element = l[index];
                        var ll = element.split('=');
                        if (ll.length&&ll[0]&&ll[1]&&ll[0]=='start') {
                            this.start = ll[1];
                            console.log(ll[1]);
                            
                        }
                        if (ll.length&&ll[0]&&ll[1]&&ll[0]=='rows') {
                            this.rows = ll[1];
                            console.log(ll[1]);
                            
                        }
                        if (ll.length&&ll[0]&&ll[1]&&ll[0]=='id') {
                            this.currentId = ll[1];
                            console.log(ll[1]);
                            
                        }
                    }
                }
                //获取所有的数据库,过滤后返回
                this.$http.get('/api/core')
                .then(function (response) {
                    if (response&&response.body.result) {
                        this.cores = response.body.result.filter(function (core) {
                            if (core.core.core&&core.core.core.indexOf('newscore')>-1) {
                                return false;
                            }
                            return core.core.core;
                        })
                        if (!this.currentId&&this.cores.length) {
                            this.currentId = this.cores[0].core._id || '';
                            this.tableId = this.cores[0].core._id || '';
                            // this.getDatabaseData(this.currentId);
                            this.$router.push({ name: 'core', params: {
                                core: this.currentId,
                                rows:this.rows,
                                start:this.start
                            },
                            query: { 
                                rows: this.rows,
                                start:this.start
                             }
                        })
                        }
                        var id = this.currentId;
                        var tableId,currentCore;
                        this.cores.filter(function (core) {
                            if (core.core._id == id) {
                                tableId = core.core._id
                                currentCore = core;
                            }
                            return false;
                        });
                        if (tableId) {
                            this.tableId = tableId;
                        }
                        if (currentCore) {
                            this.currentCore = currentCore;
                        }
                    }
                }).catch(function (err) {
                    console.log(err);
                });
        
                if (this.currentId) {
                    // this.getDatabaseData(this.currentId);
                    console.log(this.currentId,'dfdfdsfsdfsdf');
                    
                    this.$router.push({ name: 'core', params: {
                        core: this.currentId,
                        rows:this.rows,
                        start:this.start
                    },
                    query: { 
                        rows: this.rows,
                        start:this.start
                     }
                })
                }
            },
            methods:{
        
                //获取数据        
                // getDatabaseData(id){
                //     var id = id || this.currentId;
                //     this.currentId = id;
                //     var url = '/api/collection/search/'+id+'?start='+this.start+'&&rows='+this.rows;
                //     this.$http.get(url)
                //     .then(function (response) {
                //         console.log(response);
                //         this.data = response.body.result.docs;
                //         this.numFound = response.body.result.numFound;
                //         this.pagesList = getPageList(this.numFound,this.rows,this.start,'/show_database?id='+this.currentId)
                //     }).catch(function (err) {
                //         console.log(err);
                //     });
                // },
                // 展示详情
        
                //监听num-found事件
                getnumFound(num){
                    this.numFound = num;
                },
                showDetail(id,evt){
                    
                    if (!id || !this.tableId) {
                        return ;
                    }
                    var url = '/api/collection/search/'+this.tableId+'/'+id;
                    this.$http.get(url).then(function (response) {
                        
                        if (response.body.success) {
                            this.detailData = response.body.result;
                            this.isShowDetail = true;
                        }else{
                            alert(response.body.message)
                        }
                    }).catch(function (err) {
                        console.log(err);
                        
                    });
                },
                closeDetail(){
                    this.isShowDetail = false;
                },
                //TODO 重构
                jumpNew(core,rows,start){
                    this.currentId = core;
                    this.$router.push({ name: 'core', params: {
                        core: core,
                        rows:rows,
                        start:start
                    },
                    query: { 
                        rows: rows,
                        start:start
                     }
                    })
                }
                
            },
            watch:{
                detailData:function (nv,ov) {
                    console.log(nv,ov);
                    
                    if (nv) {
                        var arr = [];
                        for (var key in nv) {
                            if (nv.hasOwnProperty(key)) {
                                var e = nv[key];
                                var obj = {
                                    name:'',
                                    value:''
                                };
                                obj.value= e;
                                //获取中文名称
                                if (this.currentCore&&this.currentCore.schema&&this.currentCore.schema.length) {
                                    obj.name =  getAlias(this.currentCore.schema,key)
                                }
                                arr.push(obj);
                            }
                        }
                        this.tableData = arr;
                    }
                }
            },
            components:{
                'items-number':itemsNumber,//结果数目显示
                'database-lists':databaseLists,//数据库列表展示
                'items-lists':itemsLists,//数据列表展示
                'pagination':pagination,//分页
                'item-detail':itemDetail,//详情
                'list-compoment':listCompoment
            },
            router:router
        })
      
    • public/js/show_database/compoments.js

        var itemsNumber = {
            template:'#items_number',
            props:['number'],
        };
        var databaseLists = {
            template:'#database_lists',
            props:['cores','currentId','jumpNew'],
        };
        var itemsLists = {
            template:'#items_lists',
            props:['data','showDetail','start'],
            filters:{
                content:function (value) {
                    var ss = '';
                    // console.log(value);
                    if (!value) {
                        return ss;
                    }
                    if (typeof value =='string') {
                        return value;
                    }
                    if (typeof value =='object') {
                        for(var key in value){     
                            //获取中文名称
                            var name = key;
                            if (vm.currentCore&&vm.currentCore.schema&&vm.currentCore.schema.length) {
                                name =  getAlias(vm.currentCore.schema,key)
                                // console.log(name);
                                
                            }
                            if (value.hasOwnProperty(key) === true && key!='id'){  
                                var s = name+':'+value[key]+';'
                                ss+=s;
                            }                 
                        }  
                    }
                    if(ss&&ss.length>200){
                        ss = ss.slice(0,200)+'...'
                    }
                    return ss;
                }
            }
        };
        var pagination = {
            template:'#pagination',
            props:['pagesList']
        };
        
        var itemDetail = {
            template:'#item_detail',
            props:['isShowDetail','tableData','backFn']
        }
        var listCompoment = {
            template:'#list_compoment',
            // props:['data','showDetail','start','pagination'],
            props:['core','rows','start'],
            components:{
                'pagination':pagination,//分页
                'item-detail':itemDetail,//详情
                'items-lists':itemsLists
            },
            data:function () {
                return {
                    data:[],
                    showDetail:false,
                    pagination:[],
                    numFound:0,
                    currentId:'',
                    pagesList:[]
                }
            },
            methods:{
                //获取数据        
                getDatabaseData(id){
                    var id = id || this.currentId;
                    this.currentId = id;
                    var url = '/api/collection/search/'+id+'?start='+this.start+'&&rows='+this.rows;
                    this.$http.get(url)
                    .then(function (response) {
                        // console.log(response);
                        this.data = response.body.result.docs;
                        this.numFound = response.body.result.numFound;
                        //发送找到的数据
                        this.$emit('num-found',this.numFound);
                        this.pagesList = getPageList(this.numFound,this.rows,this.start,'/show_database?id='+this.currentId)
                    }).catch(function (err) {
                        console.log(err);
                    });
                }
            },
            created:function () {
                console.log(this.$route.params)
                // console.log(this.core,this.rows,this.start)
                this.getDatabaseData(this.core);
            },
            watch:{
                '$route':function (to, from) {
                    this.getDatabaseData(this.core);
                    console.log(to,from);
                            
                }
            }
        }
        function getAlias(schema,name) {
            if (!schema || !name || !schema.length) {
                return '';
            }
            var alias=name;
            for (var index = 0; index < schema.length; index++) {
                var e = schema[index];
                if (e.name && e.name == name && e.alias) {
                    alias = e.alias;
                    break;
                }
            }
            return alias;
        }
        function getPageList(total, rows, start, url) {
          var rtn = getPagesInfo(total, rows, start);
          var pages = rtn.pages;
          var _out = [];
          if (rtn.currentPage != 1) {
            _out.push({
              label: '上一页',
              link: url+'&&start='+rows*(rtn.previous - 1)+'&&rows='+rows
            //   link: toSearch(query, 'start', (rtn.previous - 1) * rtn.rows)
            })
          }
          if (rtn.pages.indexOf(1) < 0) {
            _out.push({
              label: '首页',
              link: url
            //   link: toSearch(query, 'start', 0)
            })
          }
          pages.map((p, i) => {
            _out.push({
              show: p == rtn.currentPage,
        
              link: p == '...' ? "" : url+'&&start='+rows*(p-1)+'&&rows='+rows,
            //   toSearch(query, 'start', (p - 1) * rtn.rows),
            //   link: p == '...' ? "" : toSearch(query, 'start', (p - 1) * rtn.rows),
              label: p
            })
          })
          if (rtn.pages.indexOf(rtn.totalPages) < 0) {
            _out.push({
              label: rtn.totalPages,
              link: url+'&&start='+rows*(rtn.totalPages - 1)+'&&rows='+rows,
            //   toSearch(query, 'start', (rtn.totalPages - 1) * rtn.rows)
            //   link: toSearch(query, 'start', (rtn.totalPages - 1) * rtn.rows)
            })
          }
          if (rtn.currentPage != rtn.totalPages) {
            _out.push({
              label: '下一页',
              link: url+'&&start='+rows*(rtn.next - 1)+'&&rows='+rows,
            //   toSearch(query, 'start', (rtn.next - 1) * rtn.rows)
            //   link: toSearch(query, 'start', (rtn.next - 1) * rtn.rows)
            })
          }
          return _out;
        }
        
        function getPagesInfo(total, rows, start) {
          total = parseInt(total);
          rows = parseInt(rows);
          start = parseInt(start);
          var totalPages = Math.ceil(total / rows);
          var currentPage = parseInt(start / rows) + 1;
          var pagaSize = rows;
          var rtn = {
            total: total,
            currentPage: currentPage,
            totalPages: totalPages,
            pages: [],
            previous: (currentPage > 1) ? (currentPage - 1) : false,
            next: (currentPage < totalPages) ? (currentPage + 1) : false,
            first: 0,
            last: totalPages * pagaSize,
            rows: pagaSize,
          };
          getPages(rtn, 10);
          console.log(rtn);
          
          return rtn;
        }
        
        function getPages (options, maxPages) {
        	var surround = Math.floor(maxPages / 2);
        	var firstPage = maxPages ? Math.max(1, options.currentPage - surround) : 1;
        	var padRight = Math.max(((options.currentPage - surround) - 1) * -1, 0);
        	var lastPage = maxPages ? Math.min(options.totalPages, options.currentPage + surround + padRight) : options.totalPages;
        	var padLeft = Math.max(((options.currentPage + surround) - lastPage), 0);
        	options.pages = [];
        	firstPage = Math.max(Math.min(firstPage, firstPage - padLeft), 1);
        	for (var i = firstPage; i <= lastPage; i++) {
        		options.pages.push(i);
        	}
        	if (firstPage !== 1) {
        		options.pages.shift();
        		options.pages.unshift('...');
        	}
        	if (lastPage !== Number(options.totalPages)) {
        		options.pages.pop();
        		options.pages.push('...');
        	}
        }
      
    • public/js/show_database/router.js

        // 0. 如果使用模块化机制编程,导入Vue和VueRouter,要调用 Vue.use(VueRouter)
        
        // 1. 定义(路由)组件。
        // 可以从其他文件 import 进来
        // var Foo = { template: '<div>foo-><router-link to="/bar">Go to Bar</router-link></div>' }
        // var Bar = { template: '<div>bar-><router-link to="/foo">Go to Foo</router-link></div>' }
        
        // 2. 定义路由
        // 每个路由应该映射一个组件。 其中"component" 可以是
        // 通过 Vue.extend() 创建的组件构造器,
        // 或者,只是一个组件配置对象。
        // 我们晚点再讨论嵌套路由。
        var routes = [
          { 
              path: '/core/:core', 
              component: listCompoment,
              name:'core',
              props:function (route) {
                //   console.log(route,'-----')
                //   routes.query.rows = route.params.rows;
                //   routes.query.start = route.params.start;
                  return {
                      core:route.params.core,
                      rows:route.params.rows,
                      start:route.params.start
                  }
              }
            }
            // ,
        //   { 
        //       path: '/detail/:tableId/:itemId', 
        //       component:itemDetail,
        //       name:'detail',
        //       props:{
        //         isShowDetail:this.isShowDetail,
        //         tableData:this.tableData,
        //         backFn:this.closeDetail
        //       }
        //     }
        ]
        
        // 3. 创建 router 实例,然后传 `routes` 配置
        // 你还可以传别的配置参数, 不过先这么简单着吧。
        var router = new VueRouter({
          routes: routes,
          mode: 'history',
          base:'/show_database/'
          //   routes // (缩写)相当于 routes: routes
        })
        
        // 4. 创建和挂载根实例。
        // 记得要通过 router 配置参数注入路由,
        // 从而让整个应用都有路由功能
        // var app = new Vue({
          
        // }).$mount('#app')
        
        // 现在,应用已经启动了!
      

    其实代码还没重构完。。

  • 相关阅读:
    JS使用小记
    CSS使用小记
    POST Raw JSON提交
    获取当月的某天
    bootstrap-datetimepicker的中文显示问题
    学习总结——Selenium元素定位
    Android常用控件及对应Robotium API
    Junit4断言
    Junit3断言
    Robotium怎样判断测试结果
  • 原文地址:https://www.cnblogs.com/ivanlee-ee-233/p/9017076.html
Copyright © 2020-2023  润新知