vue项目基本目录结构以及启动最基本组件
- 在文件路径 输入 cmd
- vue-init webpack 文件纯英文小写名称 回车
- 4个回车 y n n n v
- cd 文件名(输入文件首字“v母按teb键,自动切换以”v"开头的)
- npm install 下载以依赖,自动检索目录package.json,
- npm run dev 启动一个项目
build文件夹:
构建项目的文件夹 里面的文件都是配置当前项目构建的一些信息 ;例如:热更新,项目实时更新
config文件夹:
做项目配置的文件夹 比如 启动的地址 不要localhost 端口8080改成其他,都可以在这里面改
node_modules文件夹:
就是我们cnpm/npm install 下载的所有模块
src文件夹:
这个就是我们今后写代码主要的文件夹
src文件夹里面的东西:
assets文件夹:
静态资源文件夹:音频 视频 图片等一些静态资源,和打包有关。
components文件夹:
存放所有 组件 .vue 文件的文件夹
router文件夹:
存放路由配置的文件夹
App.vue文件:
是默认自带的 入口欢迎页的组件
main.js文件:
vue程序的入口文件 vue项目从这里开始加载
static文件夹:
一个存放静态文件资源的文件夹 (打包时 并不会一起打包的文件夹)
比如: html css js文件(不算静态文件) 都可以存放到这
index.html文件:
单页面应用 一个唯一的html, 欢迎页的文件;
main.js是程序入口,由main.js去加载index.html,index.html是辅助。
package.json文件:
所有依赖的记录的配置文件
默认从main.js
开始加载,然后把当前的组件都承载到index.html
里,index.html
里只有一个div#app(一片html代码)
,从main.js
程序进入,el挂载到"#app"上面,router,
路由,components:{App}
组件,App是当前vue的局部组件,App局部组件不是在main.js文件的components{}中 new的, App是一个对象,是通过 import 对象 from component文件路径
引入的。
认识main.js里面的功能
- import语句
import
语句时es6
推出的 可以让一个js文件去直接引入另一个js文件;
我们以前要想两个js相互关联 就必须在html中 通过 script:src同时引入两个js 这样关联;
现在 在我们vue中 直接通过import 对象 from "js文件路径"
;
就可以引入其他的js文件 但是 前提 是 那个js文件 必须export default {}对象
这样导出对外暴露;
import Vue form 'vue'
引入当前vue模块,引入进来的是一个构造函数,对应的Vue模块肯定有这么一句话 export default function (){},那么"vue’这个路径在哪?import Vue form 'vue'
没有./开头的就是默认去node_modulnoes文件夹
里面找对应模块。如果node_modulnoes文件夹
里面没找到就报错
import route form './router'
./默认打开当前文件夹下面的文件夹,没有文件后缀名默认打开文件夹中的index.js文件
- import 引入的路径是一个文件没有后缀名
默认找.js 或者 .vue 文件 例如:import Vue form './App'
- 如果引入的是个文件夹,默认去找这个文件的index.js 或者index.vue;
vue文件渲染组件的方式
Vue
的$options
里面的template
功能
如果Vue
没有定义template
属性 那么按照el
挂载的目标样式去加载
如果Vue
定义了template
属性 那么会把挂载目标本身全部替换成template
模板页面
使用.vue
文件的方式创建组件
如果不是欢迎页的组件那么就要创建到components
文件夹里面(潜规则)
.vue
组件文件的文件名最好是大驼峰(潜规则)
.vue
文件包含三个标签:
template
标签 负责定义当前组件的 页面模板
script
标签 负责定义当前组件的事件和数据 export default { data(){}, methods:{}}
style
标签 负责定义当前组件的样式
new Vue({
el: '#app',
/*template:"<h1>我是vue自己的template属性</h1>"
data:{msg:"我是vue数据"}
components:{
App:{
template:"<h1>我是aaa局部组件</h1>"
}
},
template:"<App/>"*/
// 原来渲染组件的方式
components:{
/*Hello:{} 这个大括号就是组件对象
但是现在我们的组件是在vue文件里面定义的
而且这个组件对象通过 import语句引入进来了
所以只需要把Hello:{} 后面的这个大括号换成 import引入进来的那个组件对象即可
Hello:{}*/
/*键表示组件标签名 值是组件对象 原来是大括号新创建的
现在是 通过 import语句引入的
Hello:Hello*/
//es6新写法 如果括号对象的属性名和属性值一模一样 则写一份即可
Hello,Demo
}
})
组件的.vue
文件编写成功后需要在其他地方通过 import
语句引入进行加载
import 组件对象名 from "组件的路径/文件名.vue"
后缀名.vue可以省略不写 如果是./开头 当前文件所在的文件夹出发
子组件的渲染使用
组件的template里面 必须有根节点
组件的template标签里面 最外层必须是一个单独的标签 不能是直接的两个或者两个以上标签,也就是说 至少有一个标签是作为父元素的。
子组件的渲染:
什么是子组件? 就是在当前组件下面再定义引入其他组件
那么当前引入的组件就是子组件 当前组件就是父组件
渲染子组件的步骤:
在当前父组件的script标签第一行 通过 import语句引入子组件对象
在当前 组件 的 export default{}里面定义 components属性
然后在 components属性里面注册子组件
子组件还可以继续引入子组件,一个父组件可以有多个子组件
当前组件如果是被另一个组件引入 并使用了 那么当前组件就是那个组件子组件
动态组件的渲染
什么是动态组件?
就是组件可以进行动态的切换更改,需要使用 component标签
<component is="组件的标签名"></component>
标签名是哪个组件 最后就渲染哪个组件
// main.js
import Vue from 'vue'
import Hello from "./Hello"
new Vue({
el: '#app',
components: {Hello},
template:"<Hello/>"
})
// Hello.vue
<template>
<div>
<ul class="nav">
<li @click="show('Home')">首页</li><li @click="show('Detail')">详情页</li><li @click="show('User')">个人中心</li>
</ul>
<div id="content">
<component :is="componentName"></component>
</div>
</div>
</template>
<script>
import Detail from "./components/Detail";
import Home from "./components/Home";
import User from "./components/User";
export default {
components:{Detail,Home,User},
data(){
return {componentName:"Home"}
},
methods:{
show(item){this.componentName=item;}
}
}
</script>
<style>
ul.nav{list-style: none;width: 600px;margin: 50px auto;height: 50px;}
ul.nav>li{float: left;width: 150px;text-align: center;height: 50px;line-height: 50px;background-color: hotpink;cursor: pointer;color: white;margin:0 20px;}
#content{width: 600px;margin: 0 auto;}
</style>
//Detail.vue
<template>
<div id="detail">
<h1>我是详情页的内容</h1>
<ul>
<li>详情页内容1</li><li>详情页内容2</li><li>详情页内容3</li>
</ul>
</div>
</template>
<script>
export default {name: "Detail"}
</script>
<style scoped></style>
// Home.vue
<template>
<div id="home">
<h1>我是首页的内容</h1>
<ul>
<li>首页内容1</li><li>首页内容2</li><li>首页内容3</li>
</ul>
</div>
</template>
<script>
export default {name: "Home"}
</script>
<style scoped></style>
// User.vue
<template>
<div id="user">
<h1>我是个人中心页的内容</h1>
<ul>
<li>个人中心页内容1</li><li>个人中心页内容2</li><li>个人中心页内容3</li>
</ul>
</div>
</template>
<script>
export default {name: "User"}
</script><style scoped>
</style>
slot插槽的使用
我们使用组件标签时 如果组件标签里面写了其他内容
最后渲染出来以后 该内容并不存在
也就是组件在渲染时 默认会把 组件标签里面的内容覆盖掉 无法渲染
那么如果我们要是想保留这个内容呢?
需要用到slot插槽标签
在当前组件的template里面 定义 slot标签
那么以后有人使用当前组件标签时 如果标签内部写了内容
渲染完以后 自动把这个内容放到我们定义slot标签的那个位置
这就是slot插槽
slot还可以保留指定内容
slot标签定义name属性
指定一个名字
外部传入内容时 在标签上面定义 slto=“这个名字”
那么定义 slot="这个名字"
的标签就会被保留下来
其他内容就不会被保留
//Hello.vue
<template>
<div id="hello">
<h1>我是Hello组件</h1>
<Child>
<!-- <span slot="myleft">哈哈</span>
<span slot="myright">嘿嘿</span> -->
<span slot="title">我是对话框标题</span>
<div slot="myleft">左边</div>
<div id="box" slot="myright"></div>
</Child>
</div>
</template>
<script>
import Child from "./components/Child";
export default {
name: "Hello",
components:{Child,}
}
</script>
<style scoped>
#box{width: 100px;height: 100px;background-color: hotpink;}
</style>
//Child.vue
<template>
<div id="child">
<p>
<slot name="title"></slot>
</p>
<h2>我是child组件</h2>
<!--<slot></slot>-->
<div class="left">
<slot name="myleft"></slot>
</div>
<div class="right">
<slot name="myright"></slot>
</div>
</div>
</template>
<script>
export default {
name: "Child"
}
</script>
<style >
#child{
height: 200px;width: 400px;border: 1px solid #e4393c;background-color: #fff;
}
.left{float: left;}
.right{float: right;}
</style>
父组件给子组件传参
父组件给子组件传参步骤:
- 在父组件的模板里面找到子组件标签
- 在子组件标签上面通过
v-bind
指令随便绑定一个属性名 - 属性值就是当前要传给子组件的数据的那个变量
- 子组件有两种接收方式:
子组件有接收方式 第一种:
在子组件的 export default {}
里面通过pros属性
来接收
格式:
props:["子组件标签绑定的那个自定义属性名","如果父组件传入多个就写多个元素"]
这个props数组里面接收的字符串元素 就是父组件传过来的变量数据
直接当做当前子组件data的一个变量使用即可
子组件有接收方式 第二种:
在子组件的 export default {}
里面通过pros属性
来接收
格式:
props:{
那个绑定的属性名: 这个属性值的类型名(类型名必须是大写的 并且类型不能乱写)
那个绑定的属性名1: 这个属性值的类型名(类型名必须是大写的 并且类型不能乱写)
}
面试题:
父组件给子组件传参是单向数据绑定还是双向数据绑定?
单向数据绑定, 父组件数据发生改变时 会再次传给子组件,
子组件也能接受到新数据响应,但是子组件把传过来的数据更改时 直接报错。父组件也不会响应!!!
//Parent.vue 相当于父组件
<template>
<div id="parent">
<h1>我是父组件的标题-----{{parent_msg}}----{{parent_num}}</h1>
<ul>
<li>父组件列表1</li><li>父组件列表2</li><li>父组件列表3</li>
</ul>
<input type="text" v-model="parent_msg">
<Child :parentData="parent_msg" :parentData1="parent_num"></Child>
</div>
</template>
<script>
import Child from "./Child";
export default {
components:{Child,},
data(){
return {
parent_msg:"我是父组件数据",
parent_num:15
}
}
}
</script>
<style scoped>
#parent{border: 1px solid #e4393c;}
</style>
//Child.vue 相当于子组件
<template>
<div id="child">
<h2>我是子组件标题----{{child_msg}}</h2>
<h2>我来渲染父组件数据-----{{parentData}}---{{parentData1}}</h2>
<ol>
<li>我是子组件列表1</li><li>我是子组件列表2</li><li>我是子组件列表3</li>
</ol>
<input type="text" v-model="parentData">
</div>
</template>
<script>
export default {
// props:["parentData","parentData1"],
props:{
parentData:String,
parentData1:Number
},
data(){
return{child_msg:"我是子组件数据"}
},
mounted(){}
}
</script>
<style scoped>
#child{border: 1px solid blue;}
</style>
//main.js
import Vue from 'vue'
import Hello from "./Hello";
new Vue({
el: '#app',
components:{
Hello,
},
template:"<Hello/>"
})
//Hellow.vue
<template>
<div id="hello">
<h1>我是默认首页</h1>
<parent></parent>
</div>
</template>
<script>
import Parent from "./components/Parent";
export default {
components:{Parent,}
}
</script>
<style scoped></style>
总结:
- 在父组件模板中找到子组件标签,通过v-bind指令(:属性名(自定义)=“属性值(要传给子组件的变量名)”);
- 把属性名(自定义)在子组件里通过props注册一下,props:数组,里边写双引号,必须是字符串,注册完之后这个属性名(自定义)就是当前子组件的变量;data中的变量咋用,这个变量就咋用。
子组件给父组件传参
子组件给父组件传参必须借助一个js事件
步骤:
- 在子组件的函数里面调用
this.$emit()方法
this.$emit("自己随便写一个(自定义)事件名",给父组件传的参数1,参数2...)
- 在父组件模板中找到子组件标签
- 在子组件标签上面通过 v-on/@ 绑定这个**$emit第一个参数**的自定义事件名称
- 父组件中这个自定义事件等于一个驱动函数(名字自己随便取)
- 该驱动函数在父组件的methods里面定义
- 父组件这个 函数的参数 就是
$emit方法
的第二个参数开始的值,
$emit()
从第二个参数开始传了几个参数 那么这个父组件的驱动函数就定义几个形参接收。
//Child.vue
<template>
<div id="child">
<h2 @click="show">我是子组件标题----{{child_msg}}</h2>
<ol>
<li>我是子组件列表1</li><li>我是子组件列表2</li><li>我是子组件列表3</li>
</ol>
</div>
</template>
<script>
export default {
data(){
return{child_msg:"我是子组件数据"}
},
methods:{
show(){this.$emit("child-event",this.child_msg)}
}
}
</script>
<style scoped>#child{border: 1px solid blue;}</style>
//Parent.vue
<template>
<div id="parent">
<h1>我是父组件的标题-----{{parent_msg}}</h1>
<h2>我来渲染子组件数据-----{{hehe}}</h2>
<ul>
<li>父组件列表1</li><li>父组件列表2</li><li>父组件列表3</li>
</ul>
<Child @child-event="parentShow"></Child>
</div>
</template>
<script>
import Child from "./Child";
export default {
components:{Child,},
data(){
return {
parent_msg:"我是父组件数据",
hehe:"",//data里定义变量
}
},
methods:{
parentShow(msg){
console.log("父组件的驱动函数被触发,子组件数据是:",msg);
this.hehe=msg;//把数据赋值给data里的变量,页面就可以使用了。
}
}
}
</script>
<style scoped>#parent{border: 1px solid #e4393c;}</style>
//main.js
import Vue from 'vue'
import Hello from "./Hello";
new Vue({
el: '#app',
components:{
Hello,
},
template:"<Hello/>"
})
//Hellow.vue
<template>
<div id="hello">
<h1>我是默认首页</h1>
<parent></parent>
</div>
</template>
<script>
import Parent from "./components/Parent";
export default {
components:{Parent,}
}
</script>
<style scoped></style>
总结:
- 在子组件中找一个事件(例如:点击事件,鼠标移入移出事件),触发子组件的点击事件时,触发一段代码:
- 第一个参数1,自定义一个事件名称,第二个
this.参数2,
this.参数3
后随便传参,this.参数
就是给父组件传的数据,子组件传几个数据,父组件就用几个接收; - 下一步在父组件模板中,找到子组件标签,通过
@绑定
刚才在子组件this.$emit()
中自定义的事件名称,等于= 一个事件驱动名称 : - 父组件的函数,在methods里定义,用参数去接受,子组件的
this.$emit
的第二个往后的参数,参数就是子组件传来的数据:
vue-resource在脚手架中的使用
拓展:在cmd中输入 npm install jQuery:就是下载jQ插件
在脚手架中如何使用 vue-resource
cnpm/npm install vue-resource --save
在当前 vue脚手架的文件夹 中 输入该命令 (--save
是自动在package.json目录里登记一下);以前我们原生开发 是用html的script:src引入一个js文件,现在我们下载的是一个文件夹模块 不能这样引入,需要在main.js里面通过 import语句引入
- 在main.js里面 写上
import VueResource from "vue-resource"
:
- 再写一句代码:
Vue.use(VueResource);
这句话就相当于 原来的
script:src="vue-resource.js"
- 这样全局的this就可以调用
this.$http.get/post
全局表示以后所有组件都可以通过this.$http
调用
总结:
form “vue-resoure”是因为node_modules依赖文件夹里面有vue-resoure这个模块,VueResource是引入的对象自定义名;
Vue.use(VueResource);构造函数.use是E6新语法,意思是加载这个模块
//main.js
import Vue from 'vue'
import Hello from "./Hello";
import VueResource from "vue-resource"
//让vue加载这个模块
Vue.use(VueResource);
new Vue({
el: '#app',
components:{Hello,},
template:"<Hello/>"
})
axios在脚手架中的使用
第一种引入方式:
cnpm/npm install vue-axios --save
下载vue-axios模块cnpm/npm install axios --save
下载 axios模块- 在
main.js
里面引入import VueAxios from "vue-axios" import Axios from "axios" // 上面两句引入都要写
Vue.use(VueAxios,Axios);
这句话相当于Vue.prototype.axios=Axios
;- 然后全局就可以使用
this.axios({})
方法进行交互了
this.axios.get()
this.axios.post()
this.axios({})
第二种引入方式:
-
cnpm/npm install axios --save
下载axios模块 -
在main.js里面引入 axios模块
import Axios from "axios"
-
全局绑定axios对象 ,(绑定的值是关键)
Vue.prototype.$axios=Axios;
$axios
是自定义名字,全局就可以通过 this.$axios
进行调用
路由的基本配置
什么是路由?路由概述
我们知道路由器的作用:分配地址,通过指定IP能够找到局域网内的指定电脑,路由器表面功能就是 用什么路径访问哪台电脑。
那我们由此可以理解,路由就是使用什么路径访问什么资源,路由其实就是一种导航手段,使用指定的路径去访问指定资源,这个路由和资源之间可以没有什么必然联系,通过后台代码路由的手段来联系到一起。
路由的基本配置
路由我们需要vue-router模块,我么使用vue-init命令初始化脚手架时,vue-router那一项我们选择y,所以我们现在默认自带vue-router模块。
配置路由的基本步骤:
-
在main.js里面 通过import语句引入vue-router模块;
-
在main.js 里面
Vue.use(VueRouter)
import VueRouter form 'vue-router' Vue.use(VueRouter)
-
在main.js里面 去
new
这个VueRouter对象
,并用变量接收。 -
构造方法中需要传入一个opation对象,进行各项属性的配置。
var myrouter=new VueRouter({ })
-
VueRouter的属性配置(详见下)
-
路由对象的options配置完之后,需要把路由对象加载注册到当前Vue中,让当前vue对象具有路由的功能。
var vm =new Vue({ router:myrouter(那个new出来的路由对象)})
键必须是router : 值必须是new 出来的那个对象
-
我们需要定义
route-view标签
,这个router-view标签
就是 当前路由最终要显示的位置。 -
路由跳转需要通过按钮跳转
路由官方给我们提供了一个</router-link>
标签,这个标签是专门用来跳转路由的,本质是a标签。
<router-link to="路由的路径">文本</router-link>
这就是跳转路由。
总结
模块引入进来,保证下载过,接受变量,定义routes,配置 /名字,访问什么组件 每个对象都是路由对象,myrouter 在 new Vue里注册一下,键router 值myrouter,最后定义在首页定义</router-view>
标签。
VueRouter 常用的属性有:
-
mode 路径模式----两种
(1)history(需要服务器配置对应环境才能使用)
(2)hash s (默h认值 url路径上面自带 /#/) -
base 基本路径配置
-
routes 是一个数组 进行每一个路由的配置,数组里面传的都是一个个对象,每一个对象都是一个路由配置,对象的属性有:
(1)path:“路由路径”
(2)name:“自己起一个名字”,name的值最好跟组件对象名字一样(潜规则)
(3)component:对象的组件对象
表示用什么路径显示什么组件,组件对象必须提前引入。
// main.js
import Vue from 'vue'
import App from './App'
import VueRouter from "vue-router"
Vue.use(VueRouter);
import Home from "./components/Home";
import Teacher from "./components/Teacher";
var myrouter=new VueRouter({
mode:"hash",//默认值hash
// base:"itszt" 基本路径
routes:[
{
path:"/home",
name:""Home,
component:Home
},
{
path:"/teacher",
name:"/Teacher",
component:Teacher
}
]
});
new Vue({
el: '#app',
router:myrouter,
components: { App },
template: '<App/>'
})
通过单独js文件配置路由的方式
在router文件夹里面创建路由的配置:
-
在router文件夹里面创建一个js文件
-
在js文件第一行引入指定模块
import VueRouter from "vue-router" import Vue from "vue"
-
new VueRouter进行配置
-
把 router对象对外进行暴露
export default router
-
在main.js文件,
import router from "./router"
,把import 过来的router对象在 new Vue里面注册一下即可
//index.js
import VueRouter from "vue-router";
import Vue from "vue";
Vue.use(VueRouter);
import Home from "../components/Home";
import Teacher from "../components/Teacher";
import Student from "../components/Student"
var router=new VueRouter({
routes:[
{
path:'/',
name:'Home',
component:Home
},
{
path:'/teacher',
name:'Teacher',
component:Teacher
},
{
path:'/student',
name:'Student',
component:Student
},
]
});
export default router;
//main.js
import Vue from 'vue'
import App from './App'
//引入
import router from "./router"
new Vue({
el: '#app',
router,//注册
components: { App },
template: '<App/>'
})
路由跳转的两种方式
1. router-link
通过<router-link to=" " id=" " @mousedown.native=" "></router-link>
这个标签的to属性 关联路由的path进行跳转;该标签加载完后就是一个a标签
。
(1) 如果想要修改样式,那么直接给router-link
添加class
或者id
然后修改样式即可;
(2) 如果想要给这个标签添加事件,那么事件修饰符必须加上.native
;
(3) 如果觉得<router-link to="/" id=" " tag="li" @mousedown.native="函数名"></router-link>
最终渲染出来的a标签
不喜欢 想要换成别的标签
那么使用tag属性 tag="li"
最红渲染成li标签
//App.vue
<template>
<div id="app">
<h1> 我是默认首页</h1>
<div>
<h2>使用router-link标签跳转路由</h2>
<router-link to="/">去首页</router-link>
<router-link to="/teacher" tag="div" class="teacher">去教师页</router-link>
<router-link to="/student" @click.native="showStudent">去学生页</router-link>
</div>
<p>
<button @click="goHome">去首页</button>
<button @click="goTeacher">去教室页</button>
<button @click="goStudent">去学生页</button>
</p>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'App',
methods:{
showStudent(){alert("去学生页面干嘛?")},
goHome(){this.$router.push("/")},
goTeacher(){this.$router.replace("/teacher")},
goStudent(){
/*this.$router.push({path:"/student"})*/
this.$router.push({name:"Student"})
}
}
}
</script>
<style>
.teacher{text-decoration: none;}
.teacher:hover{font-size: 25px;}
</style>
2. 通过js代码跳转路由(两种)
this.$router.push("路由的path路径");
this.$router.replace("路由的path路径")
push和replace的区别:
push
会把当前页面记录历史记录将来回退记录会有
replace
不会把当前页面存为历史记录 回退里面没有记录
//App.vue
<template>
<div id="app">
<h1> 我是默认首页</h1>
<p>
<button @click="goHome">去首页</button>
<button @click="goTeacher">去教室页</button>
<button @click="goStudent">去学生页</button>
</p>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'App',
methods:{
goHome(){this.$router.push("/")},
goTeacher(){this.$router.replace("/teacher")},
goStudent(){
/*this.$router.push({path:"/student"})*/
//通过路由的name方法跳转
this.$router.push({name:"Student"});
}
}
}
</script>
<style></style>
push和replace变化写法
this.$router.push({
path:"路由路的path路径"
})
this.$router.push({
name:"路由的name值"
})
通过 name
或者 path
都可以匹配路由跳转;
replace
写法一模一样!!! 区别就是不记录历史记录
子路由的配置:
所谓的子路由就是当前路由下面还继续有二级或者三级的路径
/home /detail 这都是一级路由
/home/haha , /detail/goods1 这就是二级路由 也是上面路由对应的子路由
子路由的配置步骤:
- 找到当前父路由对象 给父路由对象添加children属性;
- 值是一个数组 数组里面要传入多个对象;
- 每个对象都是当前父路由下面的子路由配置;
- 对象还是那三个属性
path
name
component
;
子路由的router-view标签
应该是在当前父路由页面里面找个地方定义;
子路由如何配置默认显示的路由呢?
children:[
{
path:"跟父路由一样的path"
不能定义name
component:组件对象
}
]
这样定义的子路由就是默认显示的路由
//index.js
import Vue from "vue"
import VueRouter from "vue-router"
Vue.use(VueRouter);
import Home from "../components/Home";
import Detail from "../components/Detail";
import Goods1 from "../components/Goods1";
import Goods2 from "../components/Goods2";
import Goods from "../components/Goods";
//解决当前路由已经显示 再次点击跳转当前路由报错问题
var originalPush = VueRouter.prototype.push
VueRouter.prototype.push = function push(location) {
return originalPush.call(this, location).catch(err => err)
}
var router=new VueRouter({
// mode:"history",
routes:[
{
//配置默认的首页内容
path:"/",
name:"Home",
component:Home
},
{
path:"/detail",
name:"Detail",
component: Detail,
children:[
{
//默认显示的子路由
path:"/detail",
component:Goods
},
{
path:"/detail/goods1",
name:"Goods1",
component:Goods1
},
{
path:"/detail/goods2",
name:"Goods2",
component:Goods2
},
]
}
]
})
export default router;
路由两次点击报错问题以及mode和base属性的使用
解决当前路由已经显示 再次点击跳转当前路由报错问题
const originalPush = VueRouter.prototype.push
VueRouter.prototype.push = function push(location) {
return originalPush.call(this, location).catch(err => err)
}
push方法等于一个函数,调用call(),把他的异常是系统默认报错抛出throw,我们把异常换成catch,捕获了。
路由的mode属性:
默认是hash 表面看路径里面自带 /#/
不好看,history
就不带/#/
好看一点。
但是以后学习打包项目 一旦使用了 history
,那么打包完的项目 页面全是空白无法呈现 必须服务器做配置,然后把打包完的项目扔到做好配置的服务器里面访问才行,所以目前我们就用hash。
base属性是要和history配合使用
在history模式下,base属性里面定义的路径表示当前项目基础路径。
路由跳转时,路由传参的两种方式
1. path+query的方式传参
this.$router.push({
path:"路由的path路径",
query:{
键1:值1,
键2:值2,
}
})
跳转到另一个路由以后 在另一个路由的 mounted(){ }
里面获取传过来的数据 this.$route.query
接收那个query对象
,根据属性名获取属性值, this.$route.query.传过来的键
。
2.name+params的传参方式:
this.$router.push({
name:"路由的name属性",
params:{
键1:值1,
键2:值2
}
})
跳转到另一个路由以后 在另一个路由的 mounted(){}
里面 获取传过来的数据this.$route.params
接收那个params对象
,根据属性名获取属性值,this.$route.params.传过来的键
。
补充:
replace跟push的用法一样!!!
path+query 和 name+params这两种方式不能混用。
比如: path+params是错误的!!!
这两种传参方式的区别:
path+query:
会在地址栏问号拼接传过去的参数, 页面刷新数据还在。
name+params:
不会在地址栏有显示,页面刷新数据就丢失 只会有一次机会, 以后学习vuex+session进行数据保留。
思考, router-link标签能否传参?
能! 但是实际开发基本不用 麻烦
格式:
<router-link :to="{name:"路由的name",params:{键:值}}"></router-link>
<router-link :to="{path:"路由的path",query:{键:值}}"></router-link>
动态路由的使用
什么是动态路由?
能够进行动态路径的匹配
举例说明:
如果我们的路由配置的是 /student,那么以后跳转时 只能根据 /student跳转,如果是/student/88 就无法跳转。
但是我们实际开发中有这样的需求:
员工/老师/学生 是一个单独的路由页面没有问题,
但是员工/老师/学生有很多,不能针对每一个人都配置一个路由页面,所以需要路由后面:拼接指定的ID变量来实现访问不同人的页面数据,页面结构还是那个页面 但是具体数据展现的是不同人的数据。
所以动态路由就是在路由里面定义变量 可以通过多个符合变量格式的路由来匹配跳转,并且能够获取动态变量的数据。
配置动态步骤:
在路由对象的path里面定义变量
routes:[
{
path:"/studen/:变量名"
name:"路由名字",
comcponent:组件对象
}
]
这个变量名自己随便写 将来 任何/student/值 的路由 都可以跳转到该路由,但是一旦定义了动态路由那么 /student 就无法直接访问了 必须拼接一个变量值。
//index.js
import Vue from "vue"
import VueRouter from "vue-router"
Vue.use(VueRouter);
import Home from "../components/Home";
import Teacher from "../components/Teacher";
import Student from "../components/Student";
//解决当前路由已经显示 再次点击跳转当前路由报错问题
var originalPush = VueRouter.prototype.push
VueRouter.prototype.push = function push(location) {
return originalPush.call(this, location).catch(err => err)
}
var router=new VueRouter({
routes:[
{
//配置默认的首页内容
path:"/",
name:"Home",
component:Home
},
{
path:"/teacher/:id",
name:"Teacher",
component:Teacher
},
{
path:"/student/:id",
name:"Student",
component:Student
},
]
})
export default router;
在动态路由的组件里面 mounted方法
中 可以获取当前动态路由拼接的变量值,this.$route.params
获取 里面的键就是配置路由时定义的变量名,可以根据键获取动态路由拼接的值。
//Home.vue
<template>
<div id="home">
<h2>我是首页路由</h2>
<ul>
<li>我是首页路由内容1</li>
<li>我是首页路由内容2</li>
<li>我是首页路由内容3</li>
</ul>
<p><input type="text" placeholder="请输入ID" v-model="id"></p>
<button @click="goTeacher">跳转到教师页</button>
<button @click="goStudent">跳转到学生页</button>
</div>
</template>
<script>
export default {
name: "Home",
data(){
return{
id:""
}
},
methods:{
goTeacher(){
this.$router.push("/teacher/"+this.id)},
goStudent(){
this.$router.push("/student/"+this.id)}
}
}
</script>
<style scoped></style>
//Teacher.vue
<template>
<div id="teacher">
<h2>我是教师页面</h2>
<h2>当前访问的教师ID为:{{id}}</h2>
</div>
</template>
<script>
export default {
name: "Teacher",
data(){
return{
id:""
}
},
mounted(){
console.log("教师页动态路由为:",this.$route.params);
this.id=this.$route.params.id;
}
}
</script>
<style scoped></style>