[知识点]
1. vue: 组件基础, 动态组件, 连接, watch
2. vue route: 基础, 动态路由
html 代码
1 <html> 2 <head> 3 <title>tab</title> 4 <style> 5 .aaa{border:solid 1px #f88;} 6 ul,li{padding:0;margin:0;list-style:none;} 7 .layout {border:solid 1px #f88;} 8 .content{padding:50px; border:solid 1px #eee;width:1000px;} 9 .left{float:left; width:150px;} 10 .right{margin-left:160px;} 11 12 .nav {padding:10px 0;} 13 .nav li{ padding:3px 5px; } 14 15 .tag-view li{display:inline-block; padding:5px 10px; background-color:#f7f7f7; margin-right:2px;cursor:pointer;min-width:60px;text-align:center;} 16 .tag-view li:hover{background-color:#fee;} 17 .tag-view li.cur{background-color:#888;color:#fff;} 18 19 .p404{padding:100px; font-size:100px;} 20 </style> 21 </head> 22 <body> 23 24 25 <div id="app"> 26 <h1>Hello App!</h1> 27 <ul class="left nav"> 28 <!-- 使用 router-link 组件来导航. --> 29 <li><router-link to="/foo">Go to Foo</router-link></li> 30 <li><router-link to="/bar?id=1">Go to Bar 1</router-link></li> 31 <li><router-link to="/bar?id=2">Go to Bar 2</router-link></li> 32 <li><router-link to="/bar?id=3">Go to Bar2 3</router-link></li> 33 </ul> 34 <!-- 路由出口 --> 35 <!-- 路由匹配到的组件将渲染在这里 --> 36 <div class="right"> 37 <router-view></router-view> 38 </div> 39 40 </div> 41 42 <script type="text/x-template" id="Foo-template"> 43 <ul class="content"> 44 <li v-for="(data, i) in dataList" :key="i"> 45 <router-link :to="'/bar?id='+data.id">{{data.title}}</router-link> 46 </li> 47 </ul> 48 </script> 49 <script type="text/x-template" id="Layout-template"> 50 <div class="layout"> 51 <tag-view /> 52 <keep-alive><router-view></router-view></keep-alive> 53 </div> 54 </script> 55 <script type="text/x-template" id="TagView-template"> 56 <ul class="tag-view"> 57 <li v-for="(tag, i) in tags" :key="i" @click="()=>click(tag, i)" :class="{cur:cur==i}">{{tag.title}}-id:{{tag.query.id}}</li> 58 <li @click="add"> + {{cur}}</li> 59 </ul> 60 </script> 61 62 63 64 <script src="https://unpkg.com/vue@2.6.12/dist/vue.js"></script> 65 <script src="https://unpkg.com/vue-router@3.4.9/dist/vue-router.js"></script> 66 67 <script src="tag-views.js"></script> 68 <!-- 69 <script src="vue.js"></script> 70 <script src="vue-router.js"></script>--> 71 <script> 72 73 let _id = 1; 74 function UUID(){return ++_id;} 75 76 const bus = Vue.observable({a:0, tagViews:[]}); 77 78 const tagManager = new TagManager(bus.tagViews); 79 //console.log('------------bus', bus) 80 81 const TagView = { 82 template:'#TagView-template', 83 name:'tag-view', 84 computed:{ 85 tags: () => bus.tagViews 86 }, 87 data(){return { 88 cur:0 89 }}, 90 methods:{ 91 add(){}, 92 click(tag, i){ 93 this.cur = i 94 console.log('[TagView] tab click, cur: ', this.cur) 95 this.$router.push(tag) 96 } 97 }, 98 watch:{ 99 '$route':function (r1, r0) { 100 //console.info(r1) 101 let i = tagManager.addTag(r1) 102 //console.log('watch $route, cur: ', this, this.cur, i) 103 this.cur = i 104 } 105 }, 106 created:function(){ 107 console.log('[TagView] created'); 108 tagManager.addTag(this.$route) 109 }, 110 udpated:function(){console.log('[TagView] udpated')} 111 } 112 113 // 114 const Layout = { 115 template: '#Layout-template', 116 name:'Layout', 117 data(){return {}}, 118 computed:{}, 119 created:function(){console.log('Layout created');}, 120 udpated:function(){console.log('Layout udpated');} 121 } 122 123 // 1. 定义 (路由) 组件。 124 const Foo = { 125 template: '#Foo-template', 126 name:'Foo', 127 data:function(){return { 128 dataList: [UUID(),UUID(),UUID(),UUID()].map((x)=>{return {id:x, title:'title '+ x}}) 129 }}, 130 created:function(){console.log('[Foo] created')}, 131 udpated:function(){console.log('[Foo] udpated')} 132 } 133 const Bar = { 134 template: '<div class="content">query.id:{{$route.query.id}} | id:{{ id }} | {{ new Date().getTime() }}</div>', 135 name:'Bar', 136 data:function(){return { 137 id: UUID() 138 }}, 139 activated:function(){ 140 console.log('[Bar] activated', this.$route.name, this.$route.query.id) 141 this.$nextTick(function(){ 142 tagManager.setTitle('title x ' + this.$route.query.id) 143 }) 144 }, 145 created:function(){console.log('[Bar] created')}, 146 udpated:function(){console.log('[Bar] udpated')} 147 } 148 149 const p404 = { 150 template: '<div class="p404">404</div>' 151 } 152 153 // 2. 定义路由 154 const routes = [ 155 {path:'/home', component:Layout, children:[ 156 {name:'foo', path: '/foo', component: Foo }, 157 {name:'bar', path: '/bar', component: Bar }, 158 {name:'bar2', path: '/bar2', component: Bar } 159 ]} 160 ] 161 162 const router = new VueRouter({ 163 routes 164 }) 165 166 Vue.component('TagView', TagView) 167 168 // 4. 创建和挂载根实例。 169 const app = new Vue({ 170 router 171 }).$mount('#app') 172 173 174 </script> 175 </body> 176 </html>
依赖JS:
tag-views.js
1 function TagManager(tagViews){ 2 this.cur = 0; 3 this.addTag = (route) => { 4 this.cur = tagViews.findIndex(x=>x.fullPath==route.fullPath) 5 if(this.cur < 0){ 6 tagViews.push(Object.assign({}, route, { 7 title: route.meta.title || 'no-name' 8 })) 9 console.log('add tagViews', route.fullPath) 10 this.cur = tagViews.length - 1 11 } 12 return this.cur 13 } 14 15 this.setTitle= (title) => { 16 tagViews[this.cur].title=title 17 } 18 19 this.removeTagByIndex = (index) => { 20 tagViews.splice(index,1) 21 } 22 23 this.removeTag = (route) => { 24 let index = tagViews.findIndex(x=>x.fullPath==route.fullPath) 25 if(index!==undefined){ 26 this.removeTagByIndex(index) 27 } 28 } 29 }