Vue
因为之前曾接触过小程序的开发,所以 入手 Vue 相对爽了一些,因为思想都是数据绑定,Vue是华人尤雨溪开发的,这可是个大佬,B站上有个关于大佬的纪律片,是 Up主:鱼C-小甲鱼 翻译的,有兴趣的话可以看看。
https://www.bilibili.com/video/BV1dT4y1V7Dn
M V VM
-
他是一种架构方式、开发思想
-
M:Model 数据模型 (操作数据的类)
-
V:View 视图界面 (HTML)
-
VM:ViewModel 视图模型
Vue 的思想
Vue是比较重要的是用数据来驱动页面,下面是一个简单的用Vue实现的页面
<body>
<div id="app">{{message}}</div>
</body>
<script src="js/vue.js"></script>
<script>
var app = new Vue({
el:"#app",
data:{
message:"hello world"
}
})
</script>
Vue 实例中常见对象
el
获取元素,你可以用#id
、.类名
,类似JQuery的选择器等等,也可以用document.querySelectAll()
之类的
data
实例中的数据都放在这里
computed 计算属性
计算属性的结果是放在缓存里的
method 方法
顾名思义,可以在这里定义方法
生命周期函数
需要记得有
-
beforeCreate
:data
和methods
都不能使用(可以在此声明周期中打印data
,报undefined
,或是执行method
方法:报错
) -
create
:可以使用data
和methods
-
beforeMount
:节点在内存中已经生成好了,但是没有挂载到页面上(我们可以通过document.querySelector('').innerHTML);
来获取页面上的信息,因为没有渲染到页面上,此时还是模板字符串的内容{{ msg }}
,说明数据还没有替换到页面上,但是内存里已经渲染好了) -
mounted
:挂载到页面上了,通过document.querySelector('').innerHTML)
也能获取到挂在上去的msg
了(mounted 是 实例创建期间的最后一个生命周期函数,当执行完 mounted 就表示,实例已经被完全创建好了,此时,如果没有其他操作的话,这个实例,就静静的躺在内存中,不动弹了)
-
beforeUpdata
:数据已经更新了,并且内存中也更新完了,但是没有渲染到页面上(测试方法:写个按钮,改变data
,触发此函数) -
updated
:渲染到页面上了,此时已经是新的数据 -
beforeDestroy
:从运行阶段,进入到销毁阶段,此时Vue实例
上所有的data
和methods
都可以使用 -
destroyed
:销毁完毕,什么都没了~
其实有规律可循,创造-挂载-更新-销毁
测试生命周期如下
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>生命周期测试</title>
<script src="vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
<div id="h3">{{ msg }}</div>
<input type="button" @click="msg = 'No'" value="点我变成No">
</div>
</body>
<script type="text/javascript">
var vm = new Vue({
el : "#app",
data : {
msg:'我是信息'
},
methods:{
show(){
console.log(this.msg);
}
},
beforeCreate(){
// 这是第一个生命周期 beforeCreate,表示实例完全被创建出来之前,会执行它
// 此时 data 和 methods 是不能使用的。
console.log('1. beforeCreate:', this.msg);
},
created(){
// 这是第二个生命周期,完成了data 和 method 的加载。
console.log('2. created:', this.msg);
// this.show();
},
beforeMount() {
// 这是第三个生命周期,表示 模板已经加载到内存中编译完成了,但是没有把模板渲染到页面中
console.log('3. beforeMount:', document.querySelector('#h3').innerHTML); // {{ msg }}
// 在 beforeMount 执行的时候,页面中的元素,黑没有被真正替换过来,只是之前写的一些模板字符串
},
mounted() {
// 这是遇到的第4个生命周期函数,表示,内存中的模板已经挂载到页面中了,用户已经可以看到渲染好的页面了
console.log('4. mounted:', document.querySelector('#h3').innerHTML); // 我是信息
// 注意1:mounted 是 实例创建期间的最后一个生命周期函数,当执行完 mounted 就表示,实例已经被完全创建好了
// 此时,如果没有其他操作的话,这个实例,就静静的躺在内存中,不动弹了
console.log('********************************************************************');
console.log('********************************************************************');
// 注意2:如果要通过某些插件操作页面上的 dom 节点,最早要在 mounted 中进行
},
// 以下两个是:运行阶段的生命周期函数
// 这两个事件,会根据 data 的变化,有选择性的触发 0 次或 多次
beforeUpdate() {
// 这个时候,页面没有被更新,【数据更新了吗? 肯定更新了】
console.log('beforeUpdate:data 中的 msg 的值是:', this.msg);
console.log('beforeUpdate:页面中的节点内容:',document.querySelector('#h3').innerHTML,'(说明内存中的数据已经改变了,但是没有渲染到页面上)');
// 结论:当执行 beforeUpdate 的时候,页面中的显示的数据,还是旧的
// 此时 data 的数据是最新的,页面还是旧的
console.log('---------------------------------------------------------------------');
},
updated() {
console.log('updated:data 中的 msg 的值是:', this.msg);
console.log('updated:页面中的节点内容:',document.querySelector('#h3').innerHTML);
// 页面和data 的数据已经保持同步了,都是最新的
},
beforeDestroy() {
// 当执行beforeDestroy 钩子函数的时候,Vue实例就已经从 运行阶段,进入到了销毁阶段
// 注意:当执行 beforeDestory 的之后,实例身上所有的 data 和所有的 methods,以及过滤器,指令...
// 都处于可用的状态,此时,还没有真正的执行销毁过程
},
destroyed(){
// 组件已经完全被销毁了
}
});
</script>
</html>
参考资料 黑马程序员:Vue 的声明周期
常见API的使用
v-if 条件
<body>
<!-- 条件语句必须if/else紧跟着 -->
<div id="app">
{{message}}
<div v-if="message == 'hello world'">if</div>
<div v-else-if="message == 'hello world1'">else-if</div>
<div v-else>else</div>
</div>
</body>
<script src="js/vue.js"></script>
<script>
var app = new Vue({
el:"#app",
data:{
message:"hello world"
}
})
</script>
v-show
v-show
不能搭配template
,即使条件不对也会显示到页面上
<template v-show="1 == 2">
<h1>我是个标题</h1>
</template>
- 如果
v-show
里面的条件不对的话,页面渲染的时候会使用display:none
把他隐藏掉
<div v-show="1 == 2">
<h1>我是个标题</h1>
</div>
这里有个经典面试问题:
v-if
和v-show
有什么区别?如果频繁的显示隐藏,我用那个更好?
要回答这个问题就需要知道这两个命令是怎么工作的,v-if
它是根据条件的真假,从而是否创建元素,v-show
是控制css
的属性display:none
,也就是不管真假,他都会创建并渲染,只是控制css
达到不显示的效果而已。
v-for 循环
- 比方说我要循环一个名字叫
li
的数组
<body>
<div id="app">
<!-- 这里也可以写成 (each,index) of li,借用了ES6的语法-->
<div v-for="(each,index) in li">
each:{{each}}-----index:{{index}}
</div>
</div>
</body>
<script src="../js/vue.js"></script>
<script>
var app = new Vue({
el:"#app",
data:{
li:['one','two','three','four','five']
}
})
</script>
v-key**
- 虚拟DOM的Diff算法,其核心是基于两个简单的假设:1. 两个相同的组件产生类似的DOM结构,不同的组件产生不同的DOM结构。2. 同一层级的一组节点,他们可以通过唯一的id进行区分。
- 总结一句话:为了更好的让Vue更新虚拟Dom,key来给每个节点做一个唯一标识。
- 影响:如果不加上标识的话,在插入的时候会发生错误
v-cloak 取消抖动
用Vue渲染页面的时候,你刷新页面,会有页面没有加载数据就渲染出来的情况,一闪而过(尝试截取动图但是截不到),但是为了美,这种缺点怎么可能忍呢!!!
只需两步轻松解决
- 在标签里写上
v-cloak
- 在样式里写
[v-cloak]{ display: none; }
举个小例子
<style>
[v-cloak]{
display: none;
}
</style>
<body>
<div id="app" v-cloak></div>
</body>
v-once
首次渲染之后,页面不再随着数据的变化而变化
<body>
<div id="app">
<div v-once>
<!--可以在控制台上改变数值 app.message = 'nihao' -->
{{message}}
</div>
</div>
</body>
<script src="js/vue.js"></script>
<script>
var app = new Vue({
el:"#app",
data:{
message:"hello world"
}
})
</script>
v-bind 绑定属性 **
v-bind可以简略写成:
,v-bind:后面接标签的属性,用来绑定标签的属性。
<body>
<div id="app">
<!-- 下面两个div的绑定类是一样的,都是name1 -->
<div v-bind:class="className"> v-bind:class="className"</div>
<div :class="className">:class</div>
</div>
</body>
<script src="js/vue.js"></script>
<script>
var app = new Vue({
el:"#app",
data:{
className:"name1"
}
})
</script>
v-on 绑定事件
v-on
也可以写成@
- 可以传递参数,如果向添加事件因子,可以
@click="函数名($event)
这样传递
<!-- 下面两个div都绑定了click点击事件,效果一样 -->
<div v-on:click=""></div>
<div @click=""></div>
<button @click="hand2(10,$event)">btn2---$event</button>
v-on
也可以绑定多个事件
<input type="text" v-on:click="click1()" v-on:change="change1" v-model="data1">
<input type="text" v-on:click="click1(),change1()" v-model="data1">
修饰符
.
这个点就是修饰符,能修饰什么呢?下面就是例子
冒泡与捕获
- 阻止冒泡:
.stop
<div @click="fa">fa
<div @click.stop="son">son</div>
<!-- 这样,点击son,就不会出发fa的点击事件了 -->
</div>
- 捕获:
.capture
<div @click.capture="fa">fa
<div @click="son">son</div>
</div>
<!-- 这样,点击son,就会先触发fa,然后son -->
按键触发事件
- 37是键盘上的左方向键
- 如果向要组合按键,触发连招的话,可以连着修饰符写,如下
<input type="text" @keydown.37="key1Handler">
<input type="text" @keydown.space="key1Handler1" placeholder="space">
<!-- 组合按键 -->
<input type="text" @keydown.shift.83="key1Handler2" placeholder="shift+S">
v-html 编译 & v-pre 跳过
注意 v-html
的一些细节
<body>
<div id="app">
<span v-html="tar">span1</span>
<span v-pre="tar1">span2</span>
</div>
</body>
<script src="js/vue.js"></script>
<script>
// v-html 转化成html
// 注意转化后的页面格式,是插入此标签内了,标签内原有的内容将被覆盖
// v-pre 跳过这个元素和它的子元素的编译过程。
// 可以用来显示原始 Mustache 标签。跳过大量没有指令的节点会加快编译。
var app = new Vue({
el:'#app',
data:{
tar:"<a href='#'>11</a>",
tar1:"<a href='#'>11</a>"
}
})
</script>
图片展示
v-model 绑定输入
v-model
可以绑定input
和textarea
的文本
<body>
<div id="app" v-cloak>
<input type="text" v-model="message">
{{message}}
<textarea rows="" cols="" v-model="message">
</textarea>
</div>
</body>
<script src="../js/vue.js"></script>
<script>
var app = new Vue({
el:"#app",
data:{
message:"hello world"
}
})
</script>
- input失焦时在改变data,把输入框中的值变为number、去掉输入框中值的首尾空格
<body>
<div id="app">
<!-- .lazy 是change事件,当失去焦点的时候会改变 -->
<input type="text" v-model.lazy="mes">
<!-- .number 把输入数据变成类型为number -->
<input type="text" v-model.number="mes">
<!-- .trim 去首和尾空格 -->
<input type="text" v-model.trim="mes">
<h1>{{mes}}</h1>
</div>
</body>
<script src="../js/vue.js"></script>
<script>
var app = new Vue({
el:"#app",
data:{
mes:"hello world"
}
})
</script>
单选框、复选框、下拉框
- 都是通过
v-model
来分组,相当于校服,不同学校相当于不同的组。校服一样说明是一个学校的 - 单选框
<body>
<div id="app">
<!-- 单选:多个互斥 -->
<input type="radio" v-model="pick" value="male"> <label>男</label>
<input type="radio" v-model="pick" value="female"> <label>女</label>
<input type="radio" v-model="pick" value="???"> <label>男女男</label>
</div>
</body>
<script src="../js/vue.js"></script>
<script>
// 单选框
// 页面上选择哪一项,pick的值就是哪一个value值
var app = new Vue({
el:"#app",
data:{
pick:"male"
}
})
</script>
- 多选框
<body>
<div id="app">
<!-- 复选框多选 -->
<input type="checkbox" v-model="check" value="checkBox1"> <label>复选框1</label>
<input type="checkbox" v-model="check" value="checkBox2"> <label>复选框2</label>
</div>
</body>
<script src="../js/vue.js"></script>
<script>
var app = new Vue({
el:"#app",
data:{
// check里存储谁被选中了
check:[]
}
})
</script>
- 下拉框
<body>
<div id="app">
<!-- select如果想添加多个属性,加multiple -->
<select v-model="select">
<!-- 默认是个option中的文本进行匹配
如果用了value的话优先value
-->
<option>1</option>
<option>2</option>
<option value='你好'>3</option>
</select>
</div>
</body>
<script src="../js/vue.js"></script>
<script>
var app = new Vue({
el:"#app",
data:{
select:"你好"
}
})
</script>
组件
组件命名要求
- 短横线分隔命名
- 首字母大写命名
全局/局部组件定义
顾名思义,组件的使用范围不一样
- 需要注意的是,全局组件要在实例化对象之前就要注册,说人话,就是
- 为什么要先注册在实例化呢?反过来行不行呢?我反过来会报如下的错误
[Vue warn]: Unknown custom element: <card> -
did you register the component correctly?
For recursive components, make sure to provide the "name" option.
报错信息提示说:不知道的元素card
,是否正确注册组件?,看一下生命周期那张流程图:创建完Vue实例之后就已经渲染完template
了,这时候在注册带有template
的组件的话,Vue是不认识的
<body>
<div id="app">
{{message}}
<else-name></else-name>
</div>
</body>
<script src="../js/vue.js"></script>
<script>
// 全局组件:
// else-name 是我自定义的标签名称
// 命名规范:不能用驼峰命名,推荐都用小写
Vue.component('else-name',{
template:'<div>这是组件中</div>'
})
</script>
局部的组件,这里写了两种写法
- 直接把模板放到组件里
- 把模板放到外边:方便修改
// 局部:只在当前vue中有效
var child = {
template:'<div>这是组件局部,内部中2</div>'
}
var app = new Vue({
el:"#app",
data:{
message:'hello world'
},
components:{
'demo1':{
template:'<div>这是组件局部,内部中1</div>'
},
'demo2':child
}
})
组件中的模板
- 模板里只能由只能有一个根元素,不能有两个以上的根元素
意思是说可以这样:<div> <div></div> </div>
不可以<div></div> <div></div>
,
前者两个div
是父子关系,后者两个div
是同级的哥们关系
组件中的变量
组件中的变量可以这样定义和使用
Vue.component('else-name',{
template:'<div>这是组件全局-外部中{{mess1}} {{mess2}}</div>',
data:function(){
return {
mess1:'<<这是组件中的data1>>',
mess2:'<<这是组件中的data2>>'
}
}
})
组件的通信
父传子: props的属性
- 是否要有必须值
- 默认值
- 约束数据类型
props: {
items: { // 必须提供字段
required: true,
default: 3,
type: Array
},
}
-
先来个简单的,Vue的实例对象和组件的通信
-
假如我设Vue实例是爸爸,实例中的组件是儿子,儿子里又有个组件叫孙子,那么,爸爸和孙子之间怎么交流?
<body>
<div id="app">
<son :msgson=msgfa></son>
</div>
</body>
<script src="../js/vue.js"></script>
<script>
// props单项传递,父向子传
var app = new Vue({
el: '#app',
data: {
msgfa: '我是你爸爸'
},
components:{
'son': {
props:["msgson"],
template:`<div>
介绍:{{msgson}}
<grandson :msggrandson='sonData'></grandson>
</div>`,
components:{
'grandson':{
props:['msggrandson'],
template:`<div>{{msggrandson}}</div>`
}
},
data:function(){
return {
sonData:'儿子'
}
}
}
}
})
</script>
子传夫:自定义事件 $emit
儿子如何向爸爸传递信息呢,也就是子向父传递,这时候用到了自定义函数
<body>
<div id="app">
<show @myevent="showVal"></show>
</div>
</body>
<script src="../js/vue.js"></script>
<script>
// 子向父亲 $emit()触发事件,只是为了传值 v-on
Vue.component('show', {
data: function(){
return {
str: '我是组件中的string'
}
},
methods: {
sendMsgToFa: function(){
// 这里的this指向组件
// 自定义事件
this.$emit('myevent',this.str);
}
},
template: `<button @click="sendMsgToFa">点击弹出组件传递的数据</button>`
})
var app = new Vue({
el:"#app",
data:{
message:"hello world"
},
methods:{
showVal: function(a){
alert(a)
}
}
})
</script>
- 如果我的孙子向给儿子传递信息呢?(就是组件中的组件 向 组件 传递信息)
<body>
<div id="app">
我有三个阶级关系,分别是父亲--儿子--孙子
<son :msgson=msgfa></son>
</div>
</body>
<script src="../js/vue.js"></script>
<script>
// props单项传递,父向子传
var app = new Vue({
el: '#app',
data: {
msgfa: '我是你爸爸'
},
components:{
'son': {
props:["msgson"],
template:`<div>
介绍:{{msgson}}
<grandson :msggrandson='sonData' @myevent='showVal'></grandson>
</div>`,
components:{
'grandson':{
props:['msggrandson'],
template:`<div>
{{msggrandson}}
<button @click="sendMsgToFa">孙子给儿子传值</button>
</div>`,
methods:{
sendMsgToFa: function(){
// 传值不是自发的,而是事件驱动的,所以需要个绑定事件
// 自定义事件确定了,父亲的接收函数名,和想要传递给父亲的数据,
this.$emit('myevent','我是孙子里面的消息')
}
}
}
},
data:function(){
return {
sonData:'儿子'
}
},
methods:{
showVal: function(val){
console.log(val);
}
}
}
}
})
</script>
中央事件总线bus:数据的中介
如果我现在还是有三层关系,分别是父亲,儿子,和孙子,父亲是Vue实例,儿子是实例中的组件,孙子是组件中的组件
如果这三个人,两两之间可以互相通信,那么就不向上面那样麻烦了,如何做到呢?
我们需要借助一个中介:中央事件总线
<body>
<div id="app">
<abc :myval="btnVal"></abc>
</div>
</body>
<script src="vue.js"></script>
<script>
// 注册中央时间总线
var eventBus = new Vue();
// 注册一个名为 abc 的组件
Vue.component('abc', {
props:["myval"],
template: `<div>
<button @click="showVal">{{myval}}</button>
</div>`,
methods: {
showVal() {
// $emit 需要事件驱动,比方点击事件,来发送信息给 eventBus
eventBus.$emit('myevent','你好啊')
}
}
})
var app = new Vue({
el: '#app',
data: {
msgfa: '我是你爸爸',
btnVal:"点击"
},
mounted(){
// 我们可以在挂载的生命周期函数里接收这个自定义事件。
// 当点击事件触发的时候,这边的on 事件就接收到消息了
eventBus.$on('myevent',function(res){
console.log(res);
this.msgfa = res;
})
}
})
</script>
中央事件总线在项目中的使用
代码如下
// bus.js
class Bus {
constructor() {
this.callback = {};
}
$on(eventName, fn) {
// 监听,相当于添加事件
this.callback[eventName] = this.callback[eventName] || [];
this.callback[eventName].push(fn);
}
$emit(eventName, argu) {
// 发送事件,其实就是执行时间是吧
this.callback[eventName].forEach((item) => {
item(argu);
});
}
}
module.exports = Bus;
父链 $parent
- 子组件可以通过父链拿到父组件的所有,也可以修改父组件的数据
- 取父组件中的数据可以,但是如果是修改的话,那么父子组件的关系就会更紧,这是解耦合的操作,不太推荐(组件之间的关系应该尽量独立,不要太过亲昵)
<body>
<div id="app">
<abc :myval="btnVal"></abc>
</div>
</body>
<script src="vue.js"></script>
<script>
// 注册中央时间总线
var eventBus = new Vue();
// 注册一个名为 abc 的组件
Vue.component('abc', {
props:["myval"],
template: `<div>
<button @click="showVal">{{myval}}</button>
</div>`,
methods: {
showVal() {
console.log("this.$parent :>>", this.$parent);
}
}
})
var app = new Vue({
el: '#app',
data: {
message: '我是你爸爸',
btnVal:"点击"
}
})
</script>
子链 $children
子链跟父链差不多,不过子链打印出来的是数组~(这很好理解啊孩子可以有很多,但是你爹还能有两个嘛???)
<body>
<div id="app">
<button type="button" @click="seeChildComp">点击查看儿子</button>
<abc :myval="btnVal" ></abc>
</div>
</body>
<script src="vue.js"></script>
<script>
// 注册中央时间总线
var eventBus = new Vue();
// 注册一个名为 abc 的组件
Vue.component('abc', {
props:["myval"],
template: `<div>
<button @click="showVal">{{myval}}</button>
</div>`,
methods: {
showVal() {
console.log("this.$parent :>>", this.$parent);
},
}
})
var app = new Vue({
el: '#app',
data: {
message: '我是你爸爸',
btnVal:"点击"
},
methods:{
seeChildComp(){
console.log("seeChildComp :>>", this.$children);
}
}
})
</script>
给组件起名字,并通过名字获得组件 $refs
- 给组件起名字
ref
- 取值的话通过
this.$refs.组件名字
<body>
<div id="app">
<!-- 给组件起名字 -->
<abc ref="Wangergou"></abc>
</div>
</body>
<script src="vue.js"></script>
<script>
// 注册一个名为 abc 的组件
Vue.component('abc', {
data: function() {
return {
sonMsg: "我是组件中的数据"
}
},
template: `<div>
{{sonMsg}}
</div>`
})
var app = new Vue({
el: '#app',
data: {
message: 'hello word'
},
mounted() {
// 通过组件的名字拿到组件
console.log(this.$refs.Wangergou);
}
})
</script>
组件的插槽:内容的分发
- 插槽的作用在于内容的分发
<body>
<!-- 编译的作用域 -->
<!-- 父组件的模板的内容实在父组件的作用域编译 -->
<!-- 插槽 -->
<div id="app">
<comp>
<!-- 可以把这个p标签注释掉,观察页面 -->
<p>父亲模板的内容</p>
</comp>
</div>
</body>
<script src="vue.js"></script>
<script>
// slot是插槽
Vue.component('comp',{
template:`<div>
<slot>如果父模板没有内容,就显示我</slot>
</div>`
})
var app = new Vue({
el:"#app",
data:{
message:"hello world"
}
})
</script>
- 指定插槽的内容分发,我们可以给每个插槽起个名字
<body>
<!-- 插槽: 具名的插槽分发-->
<div id="app">
<comp>
<!-- 注意这里不是v-slot -->
<!-- 具名插槽 -->
<p slot="top">top</p>
<p slot="foot">foot</p>
<!-- 无名插槽,注意他们插入的位置 -->
<p>我没有名字1</p>
<p>我没有名字2</p>
</comp>
</div>
</body>
<script src="vue.js"></script>
<script>
// slot是插槽
Vue.component('comp',{
template:`<div>
<slot name="top"></slot>
<slot name="foot"></slot>
<div>
<slot></slot>
</div>
</div>`
})
var app = new Vue({
el:"#app",
data:{
message:"hello world"
}
})
</script>
动态组件 is
- 在
component
标签上有个属性is
,里面填写组件的名字
路由
简单路由
<script type="text/javascript" src="vue.js"></script>
<script type="text/javascript" src="vue-router.js"></script>
<body>
<div id="app">
<router-link to="/shangcheng">商城</router-link>
<router-link to="/shuma">数码</router-link>
<router-link to="/jiaju">家具</router-link>
<router-view></router-view>
</div>
</body>
<script>
// 定义一些组件
var sc = { template:`<h1>商城组件</h1>` }
var sm = { template:`<h1>数码组件</h1>` }
var jj = { template:`<h1>家具组件</h1>` }
// 定义路由,这个跟组件一样,都是要卸载实例化vue之前!
var router = new VueRouter({
routes:[
// redirect 重定向,里面写路径
{ path: '/',redirect: '/shuma' },
{ path: '/shangcheng',component: sc},
{ path: '/shuma',component: sm},
{ path: '/jiaju',component: jj}
]
})
var app = new Vue({
el:"#app",
router, // 这里需要注册路由
})
</script>
动态路由
- 动态路由可以这样写,
<script type="text/javascript" src="vue.js"></script>
<script type="text/javascript" src="vue-router.js"></script>
<body>
<div id="app">
<!-- 点击,路由跳转到 hello/65 -->
<!-- 不过这里有个问题,这里的url是拼接关系,请看下面动图 -->
<router-link to="hello/65">点击</router-link>
<router-view></router-view>
</div>
</body>
<script>
// 动态路由
var Hello = {
template: `<h1>你好 {{$route.params.id}} </h1>`
}
var router = new VueRouter({
routes:[
{ path:'/hello/:id', component: Hello }
]
})
var app = new Vue({
el:"#app",
router
})
</script>
路由前进/后退
通过:this.$router.go(1)
,参数填整数
<body>
<div id="app">
<router-link to="hello">点击</router-link>
<router-view></router-view>
<button v-on:click="back">后退</button>
<button v-on:click="go">前进</button>
</div>
</body>
<script>
// 组件
var Hello = {
template: `<h1>名字{{name}},年龄{{age}} </h1>`,
props:['name', 'age']
}
// 路由传参
var router = new VueRouter({
routes:[
{
path: '/hello',
component: Hello ,
props: { name:'张三', age:11 }
}
]
})
var app = new Vue({
el:"#app",
router,
methods:{
// 路由的前进和后退
go(){
this.$router.go(1)
},
back(){
this.$router.go(-1)
}
}
})
</script>
监听路由
- 我想点击登录的时候在右上角更改信息,就是把原先的登录注册按钮改成用户名和注销
- 然而我的登录写成了组件,在组件中更改App.vue的一个data信息,奈何学术不精,百度了好久,想到通过监听路由来出发事件
- 主要的是
watch()
这个API,只要路由变化就会触发,但是浏览器的后退是不会触发的
export default{
data:function(){
return{
isLogin: false,
userName:''
}
},
methods:{
zhuxiao(){
window.sessionStorage.setItem('isLogin', false)
this.isLogin = false
this.$router.push({
path: `/login`
})
}
},
watch:{
$route(to){
if(to.path === '/view'){
this.isLogin = true
this.userName = window.sessionStorage.getItem('userName')
}
}
}
}