Vue项目之简易版2
该文章是vue项目之简易版1的后续
1、评分效果
1 在vue项目1中,我们为每条电影信息添加一个评分效果。将原来的数字评分和票房替换为五颗星等级评分。因此我们需要在components内注册一个五颗星评分组件。
- 准备工作:找好五角星的小图标,过程与项目1引入过程类似,在此就不再详细介绍过程了。
2.在Prolist.vue中引入子组件Rating.vue,并注册。在html结构处就可以将原来的数字评分部分更改为新的五角星评分了。完成以上步骤就可以在页面中看到五个五角星了。
3.要想让五颗星依据评分显示,需要父组件给子组件传值。此时需要给子组件添加props选项来接受父组件的传值,同时给数据设定一个数据类型,此处为Number(提前观察拿到的数据类型)。
4.给五颗星设置css样式,设置一个active属性,为黄色。
5.在父组件中,在调用子组件的地方定义一个自定义属性,用来传值(该处属性值需要计算,因为五颗星所以我们采用五分制,且保留一位数字,最后需要乘1,保证传过去的值是number类型,方便五角星显示)
6.给子组件的每个星星的class绑定属性,用一个三目运算符来控制星星的颜色。(大于等于1分显示一颗星,大于等于2显示两颗星,以此类推,五颗星设置为大于等于4.5)
父组件Prolist.vue示例
<template>
<ul class="prolist">
<li class="proitem" v-for="item of attname" :key="item.id">
<div class="itemImg">
<img :src="item.images.small" alt="">
</div>
<div class="itemInfo">
<h4>
{{ item.title }}
</h4>
<div>
演员:
<span v-for="itm of item.casts" :key="itm.id">
{{ itm.name }}/
</span>
</div>
<div>
导演:
<span v-for="itm of item.directors" :key="itm.id">
{{ itm.name }}/
</span>
</div>
<Rating :rating="(item.rating.average/2).toFixed(1)*1"></Rating>
</div>
</li>
</ul>
</template>
<style lang="scss">
@import '@/lib/reset.scss';
.prolist{
.proitem{
@include rect(100%,1.2rem);
@include border(0 0 1px 0,#ccc,solid);
@include flexbox();
.itemImg{
@include rect(1.2rem,1.2rem);
img{
@include rect(1rem,1rem);
@include margin(0.1rem);
@include border(1px,#ccc,solid);
}
}
.itemInfo{
@include flex();
}
}
}
</style>
<script>
import Rating from './Rating'
export default {
props: {
attname: Array
},
components: {
Rating
}
}
</script>
子组件Rating.vue的示例
<template>
<div class="rating">
<span class="iconfont icon-wujiaoxingquanxing" :class="rating >= 1 ? 'active' : ''"></span>
<span class="iconfont icon-wujiaoxingquanxing" :class="rating >= 2 ? 'active' : ''"></span>
<span class="iconfont icon-wujiaoxingquanxing" :class="rating >= 3 ? 'active' : ''"></span>
<span class="iconfont icon-wujiaoxingquanxing" :class="rating >= 4 ? 'active' : ''"></span>
<span class="iconfont icon-wujiaoxingquanxing" :class="rating > 4.5 ? 'active' : ''"></span>
</div>
</template>
<script>
export default {
props: {
rating: Number
}
}
</script>
<style lang="scss">
.active{
color:#f66;
}
</style>
2.点击进入商品详情页
基本思想:新建一个商品详情页,再点击不同的商品时,可以跳转到同一个页面,通过路由传输不同的数据,实现页面的渲染。
1.在views文件夹下新建一个datail文件夹,里面放置商品详情页。先对其做基本布局,注意商品详情页与其他页面不同,其它页面分为主视图和底部视图(这种页面又叫命名视图或者多视图),但是商品详情页只应该有主视图,即不传底部。
2.因此一个路由需要由两个试图控制,将之前的底部抽离出来,作为一个独立的组件。在App.vue中,将底部换为< router-view>,此处需要给该标签增加一个name属性。主视图name可以不写,默认为default。
3.此时需要去更改路由,将component改为components,更改为两个视图(一个路由对应两个视图)。
4.详情页面的布局按需要而定。排版完成以后需要在路由文件中新添加详情页面的路由。底部不需要用到路由的懒加载,可以在引入Footer组件后直接写。其样式也是依据需要布局。
5.点击实现商品跳转,方法一:在Prolist.vue中,将li标签替换为router-link标签,实现声明式跳转。(声明式跳转遇到变量需要使用对象)方法二:编程式跳转,使用js去跳转。给每个li设置一个点击事件,在js中定义点击事件。每次点击将id传出去。
6.在实现商品跳转的同时,还需要将不同数据的id传输出去。因此在定义商品详情页的路由时,在path处将id作为参数传送出去。在声明式跳转中,因为跳转的是变量,所以需要用到对象,name为之前定义好的路由名称,后面紧跟字段pramas为每条数据的唯一id。此时再点击不同数据时,跳转到详情页的同时还将id作为参数传输出去了。
7.首先我们需要获取id,在我们不知道值从哪里来时,可以先打印this观察数据结构。打印后可以依据数据获取到id的值。详情页面获取数据。在详情页先做数据请求,需要用到axios。在组建中用钩子函数请求数据。在请求的数据后面加上id值可以获取到不同的数据详情。因此可以通过data拿到数据详情并去渲染页面。
下面案例只是单纯用电影题目渲染页面
组件Prolist.vue示例:
<template>
<router-link :to="{name:'detail', params:{ id: item.id }}" tag="li" class="proitem" v-for="item of attname" :key="item.id">
</template>
组件detail.vue示例:
<template>
<div class="box">
<div class="container">
<header class="header">头部</header>
<div class="content">
{{title}}
</div>
<footer class="footer">底部</footer>
</div>
</div>
</template>
<script>
import axios from 'axios'
export default {
data () {
return {
title: ''
}
},
mounted () {
//console.log(this)
//const id = this.$route.params.id
const { $route: { params: {id}}} = this
axios.get('https://www.daxunxun.com/detail?id=' + id).then(res => {
//console.log(res.data[0])
this.title = res.data[0].title
})
}
}
</script>
路由文件router.js示例:
import Vue from 'vue'
import Router from 'vue-router'
import Footer from '@/components/Footer'
/* eslint-disable */
Vue.use(Router)
export default new Router({
mode: 'history',
base: process.env.BASE_URL,
routes: [
{ //路由的重定向
path: '/',
redirect :'/home'
},
{
path: '/detail/:id',
name: 'detail',
components: {
default: () => import('@/views/detail/index.vue'), //路由的懒加载
}
},
{
path: '/home',
name: 'home',
components: {
default: () => import('@/views/home/index.vue'), //路由的懒加载
footer: Footer
}
},
{
path: '/kind',
name: 'kind',
components: {
default: () => import('@/views/kind/index.vue'), //路由的懒加载
footer: Footer
}
},
{
path: '/cart',
name: 'cart',
components: {
default: () => import('@/views/cart/index.vue'), //路由的懒加载
footer: Footer
}
},
{
path: '/user',
name: 'user',
components: {
default: () => import('@/views/user/index.vue'), //路由的懒加载
footer: Footer
}
}
]
})
3.通过嵌套路由实现登录与未登录的状态
1.在components下创建一个文件夹user,分别放置登录与未登录两个组件,表示两种状态。在路由文件下,给user路由添加children,将这两个组件的路由放置进去。(注意:path后方的路径不要加“/”,因为我们需要的是相对路径。)
2.在用户页面中添加router-view,即在个人中心页面嵌套一个路由。
3.在什么都不输人的情况下,设定路由重定向,到未登录页面(按需而定)。
登录组件示例:
<template>
<div>
欢迎您,亲爱的用户
</div>
</template>
未登录组件示例:
<template>
<div>
<button>登录</button>
<button>注册</button>
</div>
</template>
用户页面user/index.vue示例
<template>
<div class="container">
<header class="header">用户头部</header>
<div class="content">
<router-view></router-view>
个人中心
</div>
</div>
</template>
路由文件router.js示例
import Vue from 'vue'
import Router from 'vue-router'
import Footer from '@/components/Footer'
/* eslint-disable */
Vue.use(Router)
export default new Router({
mode: 'history',
base: process.env.BASE_URL,
routes: [
{ //路由的重定向
path: '/',
redirect :'/home'
},
{
path: '/detail/:id',
name: 'detail',
components: {
default: () => import('@/views/detail/index.vue'), //路由的懒加载
}
},
{
path: '/home',
name: 'home',
components: {
default: () => import('@/views/home/index.vue'), //路由的懒加载
footer: Footer
}
},
{
path: '/kind',
name: 'kind',
components: {
default: () => import('@/views/kind/index.vue'), //路由的懒加载
footer: Footer
}
},
{
path: '/cart',
name: 'cart',
components: {
default: () => import('@/views/cart/index.vue'), //路由的懒加载
footer: Footer
}
},
{
path: '/user',
name: 'user',
components: {
default: () => import('@/views/user/index.vue'), //路由的懒加载
footer: Footer
},
children: [ //嵌套两个路由
{
path: '',
redirect: 'nologin'
},
{
path: 'login',
name: 'login',
component: () => import('@/components/user/login')
},{
path: 'nologin',
name: 'nologin',
component: () => import('@/components/user/nologin')
}
]
}
]
})
4.设置404页面
1.在views中新建一个404页面。最好给其一个router-link,跳转到主页。
2.在路由文件最后配置一个路由,在输入别的不相关路径时,定位到404页面。
404页面示例:
<template>
<div>
你走错啦
<router-link to='/home'>回首页</router-link>
</div>
</template>
路由文件在最后添加如下代码:(一定要在最后添加)
{
path: '*',
component: ()=> import('@/views/notfound/index.vue')
}
补充知识:
1.路由别名
可以理解为小名,例:
{
path: '/cart',
alias:‘/h’,
name: 'cart',
components: {
default: () => import('@/views/cart/index.vue'), //路由的懒加载
footer: Footer
}
}
alias:‘/h’,这句代码的意思是,输入/h也可以跳转到该页面。就像生活中叫一个人大名或者小名,那个人都会知道在叫他。
2. 编程式跳转,
即使用js去跳转。给每个li设置一个点击事件,在js中定义点击事件。每次点击将id传出去。写法很多,具体看下方案例。
<template>
<ul class="prolist">
<!--给li绑定事件-->
<li class="proitem" v-for="item of attname" :key="item.id" @click="goDetail(item.id)">
<div class="itemImg">
<img :src="item.images.small" alt="">
</div>
<div class="itemInfo">
<h4>
{{ item.title }}
</h4>
<div>
演员:
<span v-for="itm of item.casts" :key="itm.id">
{{ itm.name }}/
</span>
</div>
<div>
导演:
<span v-for="itm of item.directors" :key="itm.id">
{{ itm.name }}/
</span>
</div>
<Rating :rating="(item.rating.average/2).toFixed(1)*1"></Rating>
</div>
</li>
</ul>
</template>
<script>
import Rating from './Rating'
export default {
props: {
attname: Array
},
components: {
Rating
},
methods: { //定义事件
goDetail (id){
//this.$router.push('/detail/'+id) //写法一
// this.$router.push({ //写法二
// name:'detail',
// params: {
// id
// }
// })
this.$router.push({path:'/detail/'+id}) //写法三
}
}
}
</script>