路由的基本使用和嵌套
import Vue from "vue";
import VueRouter from "vue-router";
import Index from "../views/Index"
import Setting from "../views/Setting"
import Setting_1 from "../views/Setting_1"
import Setting_2 from "../views/Setting_2"
Vue.use(VueRouter)
export default new VueRouter({
mode:"history",
routes:[
{ path:"/",component: Index},
{
path:"/setting",
component: Setting,
children:[
{ path:"/setting/setting_1",component: Setting_1},
{ path:"/setting/setting_2",component: Setting_2},
]
},
]
})
卖座网基本路由和嵌套
App.vue文件
<template>
<div id="app">
<!--
a标签的问题:
1)href="/#/films"
2)如果在地址栏中直接访问路由
-->
<!-- 声明式导航 -->
<!--<a href="/#/films" :class="{current:current=='films'}" @click="current='films'">电影</a> |
<a href="/#/cinemas" :class="{current:current=='cinemas'}" @click="current='cinemas'">影院</a> |
<a href="/#/center" :class="{current:current=='center'}" @click="current='center'">我的</a>-->
<!--tag="li" 渲染router-link时,渲染成li标签-->
<!-- 声明式导航 -->
<router-link to="/films" tag="li" active-class="current">电影</router-link>
<router-link to="/cinemas" tag="li" active-class="current">影院</router-link>
<router-link to="/center" tag="li" active-class="current">我的</router-link>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'App',
data(){
return{
current:"films",
}
},
components: {
}
}
</script>
<style scoped>
.current{
color: red;
}
</style>
index.js路由文件
import Vue from "vue"
import VueRouter from "vue-router"
import Film from "../views/Film";
import Cinemas from "../views/Cinemas";
import Center from "../views/Center";
import CommingSoon from "../views/film/CommingSoon";
import NowPlaying from "../views/film/NowPlaying";
Vue.use(VueRouter)
export default new VueRouter({
mode:"hash",
routes:[
{
path:"/films",
component:Film,
children:[
/*{path:"/films/nowPlaying",component:NowPlaying},*/
/*{path:"/films/comingSoon",component:ComingSoon},*/
{path:"nowPlaying",component:NowPlaying},
{path:"commingSoon",component:CommingSoon},
]
},
{path:"/cinemas",component:Cinemas},
{path:"/center",component:Center},
{path:"*",redirect:"/films"},
]
})
卖座网核心vue
cart.vue
<template>
<div>
<!--头部区域-->
<header class="header">
<a href="index.html" class="icon-back"></a>
<h3>购物车</h3>
<a href="" class="icon-menu"></a>
</header>
<!--安全提示-->
<section class="jd-safe-tip">
<p class="tip-word">
您正在安全购物环境中,请放心购物
</p>
</section>
<!--中间内容-->
<main class="jd-shop-cart-list">
<section>
<div class="shop-cart-list-title">
<div class="left">
<a href="javascript:;" class="cart-check-box" checked></a>
<span class="cart-logo"></span>
<span class="cart-title">京东自营</span>
</div>
<span class="right">您享受满100元免运费服务</span>
</div>
<!-- 以后,使用v-for,必须加上:key=“唯一值" :key="shop.shopId" -->
<div class="shop-cart-list-con" v-for="(shop,index) in shopList" :key="shop.shopId">
<div class="left">
<a href="javascript:;" class="cart-check-box"
:checked="shop.checked"
@click.prevent="singeShopSeclected(shop)"
></a>
</div>
<div class="center">
<img :src="shop.shopImage" alt="">
</div>
<div class="right">
<a href="#">{{shop.shopName}}</a>
<div>
<div class="shop-price">{{ shop.shopPrice | moneyFormat}} <span style="color: red;font-size: 18px">{{ shop.shopPrice*shop.shopNumber | moneyFormat}}</span></div>
</div>
<div class="shop-deal">
<span @click="singerShopPrice(shop,false)">-</span>
<!--<input type="number" disabled :value="shop.shopNumber">-->
<input type="number" disabled v-model="shop.shopNumber">
<span @click="singerShopPrice(shop,true)">+</span>
</div>
<div class="shop-deal-right" @click="clickTrash(shop,$event)">
<span></span>
<span></span>
</div>
</div>
</div>
</section>
</main>
<!--面板-->
<div ref="panel" class="panel" style="display: none;">
<div class="panel-content">
<div class="panel-title">您确认删除这个商品吗?</div>
<div class="panel-footer">
<a href="javascript:;" class="cancel" @click.prevent="hidePanel()">取消</a>
<a href="javascript:;" class="submit" @click.prevent="delShop()">确定</a>
</div>
</div>
</div>
<!--底部通栏-->
<div id="tab_bar">
<div class="tab-bar-left">
<a href="javascript:;"
class="cart-check-box"
:checked="isSelectedAll"
@click="selectAll(isSelectedAll)"
></a>
<span style="font-size: 16px;">全选</span>
<div class="select-all">
合计:<span class="total-price">{{totalPrice | moneyFormat}}</span>
</div>
</div>
<div class="tab-bar-right">
<a href="index.html" class="pay">去结算</a>
</div>
</div>
</div>
</template>
<script>
import './../assets/css/base.css'
import '../assets/css/cart.css'
import axios from 'axios'
export default {
name: "Cart",
data(){
return {
// 数据写在data中,vue就会监听它
// 只有监听到,数据发生改变了,vue会帮我们自动刷新视图
shopList:[], // 保存商品数据
isSelectedAll:false, // 控制全选按钮是否被选中
totalPrice:0, // 选中商品的总价
up:null, // 垃圾桶的盖子
currentDelShop:null, // 要删除的商品
}
},
created() {
this.getProduct();
},
methods: {
// ajax获取商品数据
getProduct(){
/* axios.get("https://mockapi.eolinker.com/2ZhGVxjacb39010e6753bd9c02ee803e6e3bfeab6e8007c/data").then(response=>{
// console.log(response)
if(response.data.status == 200){
let shopList = response.data.result.shopList
/!*console.log(shopList)*!/
this.shopList = shopList;
}
}).catch(error=>{
alert("网络错误~")
})*/
axios.get("http://localhost:8080/data.json").then(response=>{
// console.log(response)
if(response.data.status == 200){
let shopList = response.data.result.shopList
/*console.log(shopList)*/
this.shopList = shopList;
}
}).catch(error=>{
alert("网络错误~")
})
},
// 单个商品的加减
singerShopPrice(shop,flag){
if(flag){
// 点击了+
/* shop.shopNumber = shop.shopNumber + 1;*/
shop.shopNumber += 1;
}else{
// 点击了-
if(shop.shopNumber <= 1){
shop.shopNumber = 1;
alert("只有一件商品了,不能减了~")
return;
}
shop.shopNumber -= 1;
}
this.getAllShopPrice(); // 计算选中商品的总价
},
// 全选与反选
selectAll(flag){
this.isSelectedAll = !flag
this.shopList.forEach((item,index)=>{
// 没有check属性,需要添加一个check属性
if(item.checked == undefined){
// 没有这个属性 item代表这个商品 需要给这个商品添加checked属性
// 我们添加这个checked属性,我们学想让vue监听它。
// 要想让vue监听到你添加的属性,必须使用vue提供的api $set
this.$set(item,'checked',!flag);
}else{
// item中默认就有checked属性 不需要监听了
item.checked = !flag;
}
})
this.getAllShopPrice(); // 计算选中商品的总价
},
// 单个商品的选中与否
singeShopSeclected(shop){
if (shop.checked == undefined){
this.$set(shop,"checked",true)
}else{
shop.checked = !shop.checked;
}
this.hasSelectedAll(); // 判断全选按钮是否要被选中
this.getAllShopPrice(); // 计算选中商品的总价
},
// 当每一个商品都选中了,需要让全选按钮也被选中
hasSelectedAll(){
let flag = true;
this.shopList.forEach(item=>{
if(!item.checked){
// 说明有商品没有被选中
flag = false;
}
})
this.isSelectedAll = flag && this.shopList.length>0;
},
// 计算总价
getAllShopPrice(){
let tPrice = 0;
this.shopList.forEach(item=>{
if(item.checked){
tPrice += item.shopNumber*item.shopPrice;
}
})
this.totalPrice = tPrice;
},
// 点击垃圾桶
clickTrash(shop,e){
let up = e.target.parentNode.firstElementChild; // up指垃圾桶的盖子
this.up = up;
// 过渡动画
up.style.transition = "all .3s ease"
// 过渡动画 变形动画 自定义动画
// 先突变后过渡
// 改变科旋转中心
up.style.transformOrigin = "left bottom"
up.style.transform = "rotate(-45deg)"
// 让panel显示
this.$refs.panel.style.display = "block";
// this.$refs.panel.className = "panel-content jump";
// 记录你要删除的商品
this.currentDelShop = shop;
},
// 点击了取消
hidePanel(){
this.$refs.panel.style.display = "none";
// 盖上盖子
this.up.style.transformOrigin = "left bottom"
this.up.style.transform = "rotate(0deg)"
},
// 点击了确定
delShop(){
this.$refs.panel.style.display = "none";
let index = this.shopList.indexOf(this.currentDelShop);
console.log(index)
if(index !== -1){
this.shopList.splice(index,1)
}
// 重新计算总价
this.getAllShopPrice();
// 当删除商品时,还需要判断全选按钮是否需要全选
this.hasSelectedAll();
},
},
filters:{
// 定义了一个过滤器,专六对价格进行过滤
moneyFormat(money){
/*3299 ---> ¥3299.00*/
return `¥${Number(money).toFixed(2)}`
}
}
}
</script>
卖座网的动态路由和编程路由
index.js路由文件
import Vue from "vue"
import VueRouter from "vue-router"
import Film from "../views/Film";
import Cinemas from "../views/Cinemas";
import Center from "../views/Center";
import CommingSoon from "../views/film/CommingSoon";
import NowPlaying from "../views/film/NowPlaying";
import Detail from "../views/detail/Detail";
Vue.use(VueRouter)
export default new VueRouter({
mode:"hash",
routes:[
{
path:"/films",
component:Film,
children:[
{path:"nowPlaying",component:NowPlaying},
{path:"commingSoon",component:CommingSoon},
{path:"",redirect:"nowPlaying"},
]
},
{path:"/cinemas",component:Cinemas},
{path:"/center",component:Center},
{path:"/detail/:myid",component:Detail},
{path:"*",redirect:"/films"},
]
})
Detail.vue文件
<template>
<div>
这是{{$route.params.myid}}电影的详情
<!-- 根据ID发起ajax请求,获取此电影详情 -->
</div>
</template>
<script>
export default {
name: "Detail",
}
</script>
<style scoped>
</style>
NowPlaying.vue文件
<template>
<div>
正在热映的电影
<ul>
<li
v-for="(item,index) in films"
:key="item.filmId"
@click="toDetail(item.filmId)"
>{{item.name}}</li>
</ul>
</div>
</template>
<script>
export default {
name: "NowPlaying",
data(){
return{
films:[
{filmId: 1001,name:"热映电影1"},
{filmId: 1002,name:"热映电影2"},
{filmId: 1003,name:"热映电影3"},
{filmId: 1004,name:"热映电影4"},
{filmId: 1005,name:"热映电影5"},
]
}
},
methods:{
toDetail(id){
// 编程式路由 $route后面跟属性 $router后面跟方法
// this.$router.push("/detail") 只是跳到/detail路由
this.$router.push({path:`/detail/${id}`}) // 跳到/detail/1002路由
// this.$router.push({path:"/detail",params:id}) // 跳到/detail路由,并且传递id数据到Detail组件
}
}
}
</script>
<style scoped>
</style>
命名路由和路由的别名
App.vue文件
<template>
<div id="app">
<router-link to="/films" tag="li" active-class="current">电影</router-link>
<!--<router-link to="/cinemas" tag="li" active-class="current">影院</router-link>-->
<router-link to="/yingyuan" tag="li" active-class="current">影院</router-link>
<router-link to="/center" tag="li" active-class="current">我的</router-link>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'App',
data(){
return{
current:"films",
}
},
components: {
}
}
</script>
<style scoped>
.current{
color: red;
}
</style>
index.js路由文件
import Vue from "vue"
import VueRouter from "vue-router"
import Film from "../views/Film";
import Cinemas from "../views/Cinemas";
import Center from "../views/Center";
import CommingSoon from "../views/film/CommingSoon";
import NowPlaying from "../views/film/NowPlaying";
import Detail from "../views/detail/Detail";
Vue.use(VueRouter)
export default new VueRouter({
mode:"hash",
routes:[
{
path:"/films",
component:Film,
children:[
{path:"nowPlaying",component:NowPlaying},
{path:"commingSoon",component:CommingSoon},
{path:"",redirect:"nowPlaying"},
]
},
{path:"/cinemas",component:Cinemas,alias:"/yingyuan"},
{path:"/center",component:Center},
{
path:"/detail/:myid",
name:"detail", // 给当前的路由起一个名字
component:Detail,
},
{path:"*",redirect:"/films"},
]
})
命名视图
App.vue文件
<template>
<div id="app">
<div class="header"><router-view name="Header"></router-view></div>
<div class="body">
<div class="sidebar"><router-view name="Sidebar"></router-view></div>
<div class="main"><router-view name="Main"></router-view></div>
</div>
<div class="footer"><router-view name="Footer"></router-view></div>
<router-view></router-view>
<router-view></router-view>
<router-view></router-view>
<router-view></router-view>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'App',
data(){
return{
current:"films",
}
},
components: {
}
}
</script>
<style scoped>
.current{
color: red;
}
</style>
index.js路由文件
import Vue from "vue"
import VueRouter from "vue-router"
import NotFount from "../views/NotFount"
import Header from "../views/Header"
import Sidebar from "../views/Sidebar"
import Main from "../views/Main"
import Footer from "../views/Footer"
Vue.use(VueRouter)
export default new VueRouter({
mode:"hash",
routes:[
{ path:"/",components:{ Header,Sidebar,Main,Footer } },
{ path:"*",component:NotFount } // 配置404页面
]
})
组件复用
<template>
<h1>{{$route.params.userName}}的个人中心</h1>
</template>
<script>
export default {
name: "Profile",
data(){return { firstName:"" }},
mounted() { // 因为这个组件会被缓存起来,vue为了提升性能
// 就想在mouted勾子中获取用户名,我要根据用户名发起ajax请求
// console.log(this.$route.params.userName)
// 我需要拿着用户名去请求服务器
},
/*watch:{
firstName(){},
$route(to,from){
/!* console.log("to:",to)
console.log("from:",from)*!/
// console.log(to.params.userName)
// 发起ajax请求
}
}*/
beforeRouteUpdate(to,from,next){ // 这是一个路由的钩子
// 当路由变化,自动地执行这个钩子函数
console.log(to.params.userName)
next();
}
}
</script>
<style scoped>
</style>