Vue2.0系列(三、vue-router)附SPA案例

vue-router是vue中的一个核心插件。
今天一起来学一下,因为笔者也是根据读书和API来学习和整理,资历尚浅,如有大神,还请指点一二。

03.jpg

一,安装

1.如果安装脚手架,那么可以npm install vue-router 即可安装
然后导入并且引用就可

import VueRouter from 'vue-router'
Vue.use(VueRouter)

2.也可下载vue-router.js ,然后直接script引用也可以。

二,使用

用 Vue.js + vue-router 创建单页应用,是非常简单的。使用 Vue.js ,我们已经可以通过组合组件来组成应用程序,当你要把 vue-router 添加进来,我们需要做的是,将组件(components)映射到路由(routes),然后告诉 vue-router 在哪里渲染它们。

2.1关于渲染标签

vue-router提供了两个指令标签组件来处理导航和自动渲染的逻辑
<router-view> 渲染路径匹配到的视图组件,还可以内嵌自己的<router-view> ,根据嵌套路径渲染嵌套组件
<router-link> 路由中的应用导航

2.2关于跳转

使用router-link组件来进行导航,通过传入“to”属性指定链接
<router-link to="/home">Go to Home</router-link>
但是同样,我们需要在js中配置路由的跳转

//定义好路由组件

//index.js  配置路由跳转
export default new Router({routes})
var routes = [
    {
      path: '/home',
      name: 'Home',
      component: Home
    }
]
2.3 关于传值

页面跳转时经常需要携带参数,所以路由跳转是可以携带参数的

//动态路径传参,以冒号开头
var routes = [
    {
      path: '/detail/:id',
      name: 'Detail',
      component: Detail
    }
] 

当然在路由中也需要配置一下

<router-link :to='{name:"Detail",params:{id:x.name}}'>
    ...
</router-link>
2.4 关于参数结接收

一个『路径参数』使用冒号 : 标记。当匹配到一个路由时,参数值会被设置到 this.$route.params,可以在每个组件内使用。于是,我们可以更新Detail的模板,输出当前用户的商品名

<template lang='html'>
    <div>
        <h1>水果详情页</h1>
        <h1>{{$route.params.id}}</h1>
    </div>  
</template>
2.5 关于渲染

默认情况下,<router-link>会被渲染成a标签输出,而有时候,为了页面的规范和美观,我们可以将其替换成其他标签,比如<router-link
to:"/home" tag="div" > 最终,<router-link>就会以div的形式显示在页面上

2.6 嵌套式路由

上文说过,路由之间是可以嵌套的,所以我们可以在路由中进行子路由的嵌套
那么此时,首先,我们需要先配置路由

//此时,我们在market组件下,配置2个子路由
var routes = [
    {
      path: '/market',
      name: 'Market',
      component: Market,
      children: [
        {
          path: '/',
          component: require('../pages/market/price')
        },
        {
          path: 'price',
          component: require('../pages/market/price')
        },
        {
          path: 'rank',
          component: require('../pages/market/rank')
        }
      ]
    }
]
export default new Router({routes})

market组件中

<template lang='html'>
    <div>
        <ul class="nav">
          <router-link to='/market/price' tag="li">天天特价</router-link>
          <router-link to='/market/rank' tag="li">热销榜</router-link>
        </ul>
        <router-view class='view'></router-view>
    </div>
</template>

其实这样我们对应的子路由就配置好了。

2.7命名视图

有时候想同时 (同级) 展示多个视图,而不是嵌套展示,例如创建一个布局,有 sidebar (侧导航) 和 main (主内容) 两个视图,这个时候命名视图就派上用场了。你可以在界面中拥有多个单独命名的视图,而不是只有一个单独的出口。如果 router-view 没有设置名字,那么默认为 default。

<router-view class="view one"></router-view>
<router-view class="view two" name="a"></router-view>
<router-view class="view three" name="b"></router-view>

一个视图使用一个组件渲染,因此对于同个路由,多个视图就需要多个组件。确保正确使用 components 配置 (带上 s):

const router = new VueRouter({
  routes: [
    {
      path: '/',
      components: {
        default: Foo,
        a: Bar,
        b: Baz
      }
    }
  ]
})

编程式导航
router.push({ name: 'user', params: { userId: 123 }})
router.replace(location)
跟 router.push 很像,唯一的不同就是,它不会向 history 添加新记录,而是跟它的方法名一样 —— 替换掉当前的 history 记录
router.replace({ name: 'Start'});
router.go(n)
这个方法的参数是一个整数,意思是在 history 记录中向前或者后退多少步,类似 window.history.go(n)。

// 带查询参数,变成 /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})

分割线


是不是有点懵,做一个系统的例子
1.根据笔者的第一篇文章,安装下vue-cli以及学习基本知识《Vue2.0(一,vue实例)》http://www.jianshu.com/p/d5272bd2db5e
2.根据笔者的第二篇vue文章,学习一下vue的基本指令《Vue2.0(vue基本指令)》http://www.jianshu.com/p/7a8f2ce9ef5e
3.看过分割线上的内容


案例效果


GIF.gif

要点
1.一级路由跳转及传参
2.子路由的配置和跳转
3.基本组件的使用和传参
麻雀虽小,但是涵盖很多知识点,基本等价于一个小的app的功能

三,案例详解

3.1 构建页面组件
建立4个主页面组件以及1个详情页组件

01.jpg

3.1.1home.vue

//因为点击home.vue中的任何一个商品都跳转到商品详情页,所以在渲染每一个商品的时候,我们都加上router-link,并且进行跳转的传递参数
<template lang='html'>
    <div class="mod-home">
        <ul>
            <li v-for='x in list'>
                <router-link :to='{name:"Detail",params:{id:x.name}}'>
                    <div class="list">
                        ![](x.img)
                    </div>
                    <h3>
                        {{x.name}}{{x.price}}
                    </h3>           
                </router-link>
            </li>
        </ul>
    </div>
</template>

<script>
    export default{
        data(){
            return {
                list:[]
            }
        },
        beforeCreate(){},
        created(){},
        computed:{},
        mounted(){
            this.$http.get('http://www.vrserver.applinzi.com/aixianfeng/apihomehot.php')
            .then(response=>{
                this.list = response.body.data;
            },response=>{
            
        });
        },
        methods:{},
        components:{}
    }
</script>
<style lang='css'>
ul>li{
    display:block
}
</style>

3.1.2market.vue

<template lang='html'>
    <div>
        <ul class="nav">
          <router-link to='/market/price' tag="li">天天特价</router-link>
          <router-link to='/market/rank' tag="li">热销榜</router-link>
          <router-link to='/market/milk' tag="li">牛奶面包</router-link>
          <router-link to='/market/fruit' tag="li">优选水果</router-link>
        </ul>
        <router-view class='view'></router-view>
    </div>
</template>

<script>
    export default{
        data(){
            return {
                list:[]
            }
        },
        computed:{},
        mounted(){},
        methods:{},
        components:{}
    }
</script>
<style lang='css'>
ul,li{
        list-style: none;
    }
*{
        margin: 0;
        padding: 0;
    }
.nav{
    position: fixed;
    height: 100%;
    width:25%;
    background: #dfdfdf;
    list-style: none;
    text-align: center;
    left: 0;
    top: 0;
    
}
.footer{
    position: fixed;
    height: 40px;
    width:100%;
    background: #dfdfdf;
    list-style: none;
    text-align: center;
    left: 0;
    bottom: 0;
    z-index:10;
}
.nav li{
    /*width: 25%;*/
    padding: 10px;
}
.nav a{
    text-decoration: none;
}
.router-link-active{
    background:skyblue
}
.view{
    position: fixed;
    height: 100%;
    width:75%;
    background: #fff;
    list-style: none;
    text-align: center;
    right: 0;
    top: 0;
    overflow-y:auto
}
</style>

3.1.3car.vue和mine.vue简写

<template lang='html'>
    
    <h1>我的</h1>
</template>

<script>
    export default{
        data(){
            return {
            }
        },
        computed:{},
        mounted(){

        },
        methods:{},
        components:{}
    }
</script>
<style lang='css'>

</style>

3.2组件引用和路由配置

安装好路由,并且进行组件的引入和路由的配置

import Vue from 'vue'
import Router from 'vue-router'
import VueResource from 'vue-resource'

Vue.use(Router)
Vue.use(VueResource)

import Home from 'pages/home.vue'
import Market from 'pages/market.vue'
import Car from 'pages/car.vue'
import Mine from 'pages/mine.vue'
import Detail from 'pages/detail.vue'

var routes = [
    {
      path: '/',
      name: 'Home',
      component: Home
    },
    {
      path: '/home',
      name: 'Home',
      component: Home
    },
    {
      path: '/market',
      name: 'Market',
      component: Market,
      children: [
        {
          path: '/',
          component: require('../pages/market/price')
        },
        {
          path: 'price',
          component: require('../pages/market/price')
        },
        {
          path: 'rank',
          component: require('../pages/market/rank')
        },
        {
          path: 'milk',
          component: require('../pages/market/milk')
        },
        {
          path: 'fruit',
          component: require('../pages/market/fruit')
        },
      ]
    },
    {
      path: '/car',
      name: 'Car',
      component: Car
    },
    {
      path: '/mine',
      name: 'Mine',
      component: Mine
    },
    {
      path: '/detail/:id',
      name: 'Detail',
      component: Detail
    }
]

export default new Router({routes})

3.3detail.vue
点击home页中的每一个商品都需要跳转到商品详情页,所以我们要进行参数的接收和页面渲染

<template lang='html'>
    <div>
        <h1>水果详情页</h1>
        <h1>{{$route.params.id}}</h1>
    </div>  
</template>

<script>
    export default{
        data(){},
        computed:{},
        mounted(){

        },
        methods:{},
        components:{}
    }
</script>
<style lang='css'>
</style>

3.4market.vue

在market组件中,我们引用二级路由,所以需要定义router-link和router-view,因为每一个二级路由需要渲染不同的部分,比如天天特价,热销榜等等,所以我们还需要这四个组件,看3.4

<template lang='html'>
    <div>
        <ul class="nav">
          <router-link to='/market/price' tag="li">天天特价</router-link>
          <router-link to='/market/rank' tag="li">热销榜</router-link>
          <router-link to='/market/milk' tag="li">牛奶面包</router-link>
          <router-link to='/market/fruit' tag="li">优选水果</router-link>
        </ul>
        <router-view class='view'></router-view>
    </div>
</template>

<script>
    export default{
        data(){
            return {
                list:[]
            }
        },
        computed:{},
        mounted(){},
        methods:{},
        components:{}
    }
</script>
<style lang='css'>
ul,li{
        list-style: none;
    }
*{
        margin: 0;
        padding: 0;
    }
.nav{
    position: fixed;
    height: 100%;
    width:25%;
    background: #dfdfdf;
    list-style: none;
    text-align: center;
    left: 0;
    top: 0;
    
}
.footer{
    position: fixed;
    height: 40px;
    width:100%;
    background: #dfdfdf;
    list-style: none;
    text-align: center;
    left: 0;
    bottom: 0;
    z-index:10;
}
.nav li{
    /*width: 25%;*/
    padding: 10px;
}
.nav a{
    text-decoration: none;
}
.router-link-active{
    background:skyblue
}
.view{
    position: fixed;
    height: 100%;
    width:75%;
    background: #fff;
    list-style: none;
    text-align: center;
    right: 0;
    top: 0;
    overflow-y:auto
}
</style>

3.5 market的四个组件

02.jpg

3.5.1 fruit.vue

<template lang='html'>
    <List type='优选水果'></List>
</template>

<script>
import List from '../../components/List'
    export default{
        data(){
            return {
            }
        },
        computed:{},
        mounted(){
            
        },
        methods:{},
        components:{
            List
        }
    }
</script>
<style lang='css'></style>

3.5.2 milk.vue

<template lang='html'>
    <List type='牛奶面包'></List>
</template>

<script>
import List from '../../components/List'
    export default{
        data(){
            return {
            }
        },
        beforeCteate(){},
        create(){},
        computed:{},
        mounted(){},
        methods:{},
        components:{
            List
        }
    }
</script>
<style lang='css'></style>

3.5.3price.vue

<template lang='html'>
    <List type='天天特价'></List>
</template>

<script>
import List from '../../components/List'
    export default{
        data(){
            return {
                
            }
        },
        beforeCteate(){},
        create(){},
        computed:{},
        mounted(){},
        methods:{},
        components:{
            List
        }
    }
</script>
<style lang='css'></style>

3.5.4rank.vue

<template lang='html'>
    <List type='热销榜'></List>
</template>

<script>
import List from '../../components/List'
    export default{
        data(){
            return {
            }
        },
        beforeCteate(){},
        create(){},
        computed:{},
        mounted(){},
        methods:{},
        components:{
            List
        }
    }
</script>
<style lang='css'></style>

仔细看着四个小组件,是不是都是同样引用了一个List.vue的组件,以为如果这四个页面的结构是一样的,所以我们只需要引用要给共同的组件即可

3.5.5 List.vue

<template>
<div class="mod-home">
        <ul>
            <li v-for='x in list'>
                <div class="">
                    ![](x.img)
                </div>
                <h3>
                    {{x.name}}{{x.price}}
                </h3>
            </li>
        </ul>
    </div>
</template>

<script>
export default {
  data () {
    return {
      list:[]
    }
  },
  props:['type'],
  computed:{},
  mounted(){
     var type = this.type || '天天特价';
 this.$http.get('http://www.vrserver.applinzi.com/aixianfeng/apicategory.php?category='+type)
     .then(response=>{
        this.list = response.body.data
     },response =>{
        
     })
  },
  methods:{}
  
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
    h1, h2 {
      font-weight: normal;
    }
    
    ul {
      list-style-type: none;
      padding: 0;
    }
    
    li {
      display: block;
      margin: 0 10px;
    }
    
    a {
      color: #42b983;
    }
</style>

这里我们在不同的父组件传入一个type,在子组件List中,我们接收type,并且根据type不同,请求不同的ajax即可。

这样我们一个小案例就可以正常运行了。

这篇文章真心耗时,噗,单身妹子该出去浪才对,伤不起~啦啦啦

文章不定时更新~

喜欢就点赞,真爱就打赏笔芯

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,179评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,229评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,032评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,533评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,531评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,539评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,916评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,813评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,568评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,654评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,354评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,937评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,918评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,152评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,852评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,378评论 2 342

推荐阅读更多精彩内容