1.初始容器
容器和组件是一对一的
<div id="root">
<h1>姓名:{{name}}</h1>
<h1>年龄:{{age}}</h1>
</div>
<script>
//阻止生产提示
Vue.config.productionTip = false;
const x = new Vue({
el: "#root",
data: {
name: "rokned",
age: 18,
},
});
</script>
2.模板语法
<div id="root">
<!-- 插值语法 -->
<h1>姓名:{{name}}</h1>
<h1>年龄:{{age}}</h1>
<!-- 指令语法,可以简写成: -->
<a v-bind:href="url">跳转b站</a>
<a :href="url">跳转b站</a>
</div>
<script>
Vue.config.productionTip = false;
const x = new Vue({
el: "#root",
data: {
name: "rokned",
age: 18,
url: "https://www.bilibili.com/",
},
});
</script>
3.数据绑定
v-model只支持表单类元素
<div id="root">
<!-- 单向数据绑定 -->
单向<input type="text" :value="name" />
<hr />
<!-- 双向数据绑定 可以简写成v-model=-->
<!-- 双向<input type="text" v-model:value="name" /> -->
双向<input type="text" v-model="name" />
</div>
<script>
Vue.config.productionTip = false;
const x = new Vue({
el: "#root",
data: {
name: "数据绑定",
},
});
</script>
4.事件处理
事件修饰符写在事件后,例:@click.stop=“xxx”
<div id="root">
<!-- 使用v-onxxx: ,缩写@xxx-->
<!-- <button v-on:click="showinfo">点击提示信息</button> -->
<button @click="showinfo">点击提示信息</button>
<button @click="showinfo2(1)">点击提示信息</button>
</div>
<script>
const vm = new Vue({
el: "#root",
methods: {
showinfo(e) {
console.log(e.target);
},
showinfo2(value) {
console.log(value);
},
},
});
</script>
5.键盘事件
6.计算属性
<div id="root">
姓:<input type="text" v-model="fn" /><br />
名:<input type="text" v-model="ln" /> <br />
姓名:<span>{{fullname}}</span>
</div>
<script>
const vm = new Vue({
el: "#root",
data() {
return {
fn: "rok",
ln: "ned",
};
},
computed: {
// 完整写法
// fullname: {
// get() {
// return this.fn + this.ln;
// },
// set(v) {
// console.log(v);
// },
// },
//简写,只有getter
fullname(){
return this.fn + this.ln;
}
},
});
</script>
7.监视属性
watch可以开启异步任务,而computed不行
注:定时器要写成箭头函数,如果写成普通函数,this会指向window,因为箭头函数的this作用域在当前函数之下
**所以非Vue管理的函数最好写成箭头函数 **
<div id="root">
姓:<input type="text" v-model="fn" /><br />
名:<input type="text" v-model="ln" /> <br />
姓名:<span>{{fullname}}</span>
<hr />
<span>{{number.a}}</span>
<button @click="number.a++">a+1</button>
</div>
<script>
const vm = new Vue({
el: "#root",
data() {
return {
fn: "rok",
ln: "ned",
number: {
a: 1,
},
};
},
computed: {
fullname() {
return this.fn + this.ln;
},
},
watch: {
//注:当只有handler函数时,可以简写
fn(newValue, oldValue) {
//一定要写成箭头函数,不然指向window
setTimeout(() => {
console.log("改变了", newValue, oldValue);
}, 1000);
},
//正常写法
// fn: {
// immediate: true, //初始化调用一下handler
// handler(newValue, oldValue) {
// console.log("改变了", newValue, oldValue);
// },
// },
//深度监视,使多层次数据可以被发现
number: {
deep: true,
handler() {
console.log("number改变了");
},
},
},
});
</script>
8.绑定class样式
<div id="root">
<div :class="color"></div>
<button @click="change" :style="StyObj">改变颜色</button>
</div>
<script>
const vm = new Vue({
el: "#root",
data() {
return {
color: "T1",
StyObj: {
fontSize: 50 + "px",
color: "orange",
},
};
},
methods: {
change() {
this.color == "T2" ? (this.color = "T1") : (this.color = "T2");
},
},
});
</script>
9.V-指令
v-show,v-if
注:template只能和v-if使用,不能和v-show
<!-- v-show调整display,里面可以是一个表达式 -->
<h1 v-show="false">v-show</h1>
<!-- v-if调整结构,里面可以是一个表达式,v-else,v-else-if也可以使用 -->
<h1 v-if="false">v-if</h1>
v-for
<ul>
<li v-for="p in persons" :key="p.id">{{p.name}}</li>
</ul>
<br>
<ul>
<li v-for="(p,index) in persons" :key="index">{{index}}</li>
</ul>
data() {
return {
persons: [
{ id: "1", name: "张三" },
{ id: "2", name: "李四" },
{ id: "3", name: "王五" },
],
};
},
key的作用(虚拟dom的对比)
Vue.set()
后期添加属性,第一个参数表示添加的对象,第二三个参数表示键值对
注:添加的对象不能是vm或根对象
v-text
作用与插值语法类似,无法解析标签
v-html
作用与v-text类似,不过可以解析标签
v-clock
在页面渲染完成时删除,配合css
v-once
在初次渲染后就称为静态
v-pre
跳过有v-pre的节点不进行解析
自定义指令
只要指令所在的模板重新解析时,就会调用
<div id="root">
<h2>当前n</h2>
<h2>放大十倍: <span v-big="n"></span></h2>
<button @click="n++">点击n+1</button>
</div>
<script>
const vm = new Vue({
el: "#root",
data() {
return {
n: 1,
};
},
directives: {
// big(element, binding) {
// console.log(element, binding);
// element.innerText = binding.value * 10;
// },
big: {
bind(e, b) {
console.log("bind");
},
inserted(e, b) {
console.log("inserted");
e.innerText = b.value * 10;
},
update(e, b) {
console.log("update");
e.innerText = b.value * 10;
},
},
},
methods: {},
});
</script>
10.过滤器
只能使用在插值语法和v-bind
将管道符前面作为参数传递给管道符后面,管道符后面的函数也可以带参数,但第一个参数是管道符前面那个,第二个参数才是括号内传递的
11.生命周期
12.组件
基本使用
注册全局组件:Vue.component(‘xxx’,xxx)
<div id="root">
<!-- 编写组件标签 -->
<school></school>
<hr />
<student></student>
</div>
<script>
//创建组件
const school = Vue.extend({
template: `
<div>
<h2>学校名称{{Scname}}</h2>
<h2>学校地址{{Scadd}}</h2>
</div>
`,
data() {
return {
Scname: "nju",
Scadd: "nj",
};
},
});
const student = Vue.extend({
template: `
<div>
<h2>学生名称{{Sname}}</h2>
<h2>学生年龄{{Sage}}</h2>
</div>
`,
data() {
return {
Sname: "rokned",
Sage: 18,
};
},
});
new Vue({
el: "#root",
//注册组件,局部注册
components: {
//左边是最终变量,右边只是一个中转变量
school: school,
student: student,
},
});
</script>
组件嵌套
<div id="root">
<hr />
</div>
<script>
//创建组件
const student = Vue.extend({
template: `
<div>
<h2>学生名称{{Sname}}</h2>
<h2>学生年龄{{Sage}}</h2>
</div>
`,
data() {
return {
Sname: "rokned",
Sage: 18,
};
},
});
const school = Vue.extend({
template: `
<div>
<h2>学校名称{{Scname}}</h2>
<h2>学校地址{{Scadd}}</h2>
<student></student>
</div>
`,
data() {
return {
Scname: "nju",
Scadd: "nj",
};
},
components: {
student: student,
},
});
const app = Vue.extend({
template: `
<school></school>
`,
components: {
school,
},
});
new Vue({
el: "#root",
template: ` <app></app>`,
components: {
app,
},
});
</script>
单文件组件
详细见代码
13.脚手架
脚手架代码笔记
将需要运行的代码笔记替换src文件夹
基本使用
new Vue({
//将app组件放入容器
render: h => h(App),
//$mount('#app')等价于el:'#app'
}).$mount('#app')
ref属性
<template>
<div>
<h1 v-text="msg" ref="title"></h1>
<button @click="showDom">点击控制台输出</button>
<demo ref="demo" id="demo"></demo>
</div>
</template>
<script>
methods: {
showDom() {
//非组件标签获得的是DOM
console.log(this.$refs.title);
//如果是组件标签则会获得vc组件
console.log(this.$refs.demo);
//如果使用原生获取则是DOM
console.log(document.getElementById('demo'));
},
},
</script>
props配置
外部接收数据
外部传入优先级大于内部
如果外部传入数据之后还需要对其进行修改,需要在子模块data声明一个新的属性
子模块
<template>
<!-- 组件结构 -->
<div>
<h1 class="demo">{{ NTest + 1 }}</h1>
<button @click="change">点击修改</button>
</div>
</template>
<script>
export default {
name: "demo", //一般和文件名相同
// 简单接收
props: ["Test"],
//简单接收2
// props: {
// //设置接收类型,如果数据类型不对会在控制台报错
// Test: Number,
// },
//完整接收
// props: {
// Test: {
// type: Number,
// require: false,
// default: 99,
// },
// },
data() {
return {
NTest: this.Test,
};
},
methods: {
change() {
//会进行报错警告
// this.Test += 1;
this.NTest += 1;
},
},
};
</script>
app模块
<template>
<div>
<h1 v-text="msg"></h1>
<!-- 直接传递引号中字符串 -->
<demo Test="18"></demo>
<!-- 动态绑定相当于将引号中作为js执行 -->
<demo :Test="18"></demo>
<!-- 可以使用默认值进行配置 -->
<!-- <demo></demo> -->
</div>
</template>
mixin混入
组件共有配置可以写入混合,可以混合多个,使用分别暴露即可
混合优先级没有内部优先级高
main.js
//全局混合
import mixin from "./mixin";
Vue.mixin(mixin);
demo.vue
<script>
//引入混合,局部引入
// import mixin from "../mixin";
export default {
name: "demo", //一般和文件名相同
data() {
return {
NTest: 100,
};
},
// mixins: [mixin],
};
</script>
demo2.vue
<script>
//引入混合,局部引入
// import mixin from "../mixin";
export default {
name: "demo2", //一般和文件名相同
data() {
return {
NTest: 200,
};
},
// mixins: [mixin],
};
</script>
mixin.js(文件名随意)
export default {
name: "mixin",
methods: {
change() {
this.NTest += 1;
},
},
};
插件
//引入插件,可以带参数
import plguin from "./plugin";
Vue.use(plguin);
scoped
当组件样式冲突时,使用scoped,表示样式只负责此处的组件
自定义事件
父组件传递函数给子组件使用
三种方法,一种使用props一种使用v-on(自定义事件)还有一种使用ref
ref更加灵活
子组件
<template>
<div>
<h1 class="demo">{{ NTest }}</h1>
<button @click="sendname">发送名字</button>
<br />
<button @click="dotage">触发tage</button>
</div>
</template>
<script>
export default {
name: "demo", //一般和文件名相同
data() {
return {
NTest: 100,
name: "rokned",
};
},
methods: {
sendname() {
this.getname(this.name);
},
dotage() {
//触发tage,可以传参
this.$emit("tage");
},
},
props: ["getname"],
};
</script>
<style>
.demo {
color: aqua;
}
</style>
父组件
<template>
<div>
<h1 v-text="msg"></h1>
<!-- 父组件传递函数给子组件,通过props实现 -->
<demo :getname="getname"></demo>
<!-- 绑定事件,在vc身上 -->
<!-- <demo v-on:tage="tage"></demo> -->
<!-- 通过ref标签 -->
<demo ref="demo"></demo>
</div>
</template>
<script>
import demo from "./components/demo.vue";
export default {
name: "app",
data() {
return {
msg: "this is a test",
};
},
methods: {
getname(name) {
console.log(name);
},
tage() {//可以接收参数
console.log("tage触发");
},
},
components: {
demo,
},
//从ref标签获取vc进行绑定
mounted() {
this.$refs.demo.$on("tage", this.tage);
},
};
</script>
<style></style>
解绑
解绑多个
全部解绑:this.$off()
unbind(){
this.$off('tage')
}
解绑还可以直接进行销毁
全局事件总线
收数据的组件绑定事件创建回调,发送数据的组件触发事件并将数据带入
demo.vue
<template>
<div>
<h1 class="demo">{{ NTest }}</h1>
</div>
</template>
<script>
export default {
name: "demo", //一般和文件名相同
data() {
return {
NTest: 100,
name: "rokned",
};
},
mounted() {
//挂载方法
this.$bus.$on("hello", (data) => {
console.log("demo1,参数:", data);
});
},
// 销毁方法
beforeDestroy() {
this.$bus.$off("hello");
},
};
</script>
<style>
.demo {
color: aqua;
}
</style>
demo2.vue
<template>
<div>
<h1 class="demo">{{ NTest }}</h1>
<button @click="sub">转交数据</button>
</div>
</template>
<script>
export default {
name: "demo2", //一般和文件名相同
data() {
return {
NTest: 200,
name: "rokned",
};
},
methods: {
sub() {
//调用方法
this.$bus.$emit("hello",666);
},
},
};
</script>
<style>
.demo {
color: aqua;
}
</style>
main.js
import Vue from "vue";
import App from "./app.vue";
Vue.config.productionTip = false;
// //创建构造
// const demo = Vue.extend({});
// //生成一个傀儡vc
// const d = new demo();
// //挂载到原型上供所有其他vc访问
// Vue.prototype.x = d;
new Vue({
render: (h) => h(App),
beforeCreate() {
//标准安装全局事件总线
Vue.prototype.$bus = this;
},
}).$mount("#app");
插槽
同一模块的复用中可以添加不同的属性
默认插槽
<template>
<div>
<h1 class="demo">{{ NTest }}</h1>
<slot>默认值 </slot>
</div>
</template>
<template>
<div>
<h1 v-text="msg"></h1>
<demo>使用了插槽</demo>
<hr />
<demo>也使用了插槽</demo>
<hr />
<demo></demo>
</div>
</template>
具名插槽
<template>
<div>
<h1 v-text="msg"></h1>
<demo><span slot="s1">使用了插槽s1</span></demo>
<hr />
<demo><span slot="s2">使用了插槽s2</span></demo>
<hr />
<demo></demo>
</div>
</template>
<template>
<div>
<h1 class="demo">{{ NTest }}</h1>
<slot name="s1">默认值s1</slot><br />
<slot name="s2">默认值s2</slot>
</div>
</template>
还可以使用v-slot配置
<demo>
<template v-slot:s1>
<span>使用了v-slot</span>
</template>
</demo>
作用域插槽
从子组件传递数据给父组件插槽,可以传入多个数据
子组件
<template>
<div>
<h1 class="demo">{{ NTest }}</h1>
<slot :names="names">默认值s1</slot><br />
</div>
</template>
<script>
export default {
name: "demo", //一般和文件名相同
data() {
return {
NTest: 100,
names: ["rokned", "ywj", "wy"],
};
},
};
</script>
<style>
.demo {
color: aqua;
}
</style>
父组件
<template>
<div>
<h1 v-text="msg"></h1>
<demo>
<!-- scope只能使用在template中 -->
<template scope="names">
<ul>
<li v-for="(n, index) in names.names" :key="index">{{ n }}</li>
</ul>
</template>
</demo>
<hr />
<demo>
<template v-slot="names">
<ol>
<li v-for="(n, index) in names.names" :key="index" style="">
{{ n }}
</li>
</ol>
</template>
</demo>
</div>
</template>
<script>
import demo from "./components/demo.vue";
export default {
name: "app",
data() {
return {
msg: "this is a test",
};
},
components: {
demo,
},
};
</script>
<style></style>
slot-scope
属于作用域插槽
<template lang="">
<div>
<h3>这是父组件</h3>
<son>
<template slot="myslot" slot-scope="scope">
<ul>
<li v-for="item in scope.data">{{item}}</li>
</ul>
</template>
</son>
</div>
</template>
<template>
<div>
<h4>这是子组件</h4>
<input type="text" placeholder="请输入">
<slot name="myslot" :data='list'></slot>
</div>
</template>
<script>
export default {
name:'Son',
data(){
return{
list:[
{name:"Tom",age:15},
{name:"Jim",age:25},
{name:"Tony",age:13}
]
}
}
}
</script>
14.脚手架的配置文件
详情见官网配置参数https://cli.vuejs.org/zh/config/
//vue.config.js
// vue.config.js
/**
* @type {import('@vue/cli-service').ProjectOptions}
*/
module.exports = {
// 选项...
}
15.Vuex
与全局总线区别
工作原理
可以跳过actions直接进行commit,因为action实际上是与其他服务器进行请求数据的,就是dispatch时不发送具体数据,而让action与backend Api进行交互请求。
创建Store
//本文件用于创建store
import Vuex from "vuex";
import Vue from "vue";
Vue.use(Vuex);
const actions = {
add(context, value) {
context.commit("add", value);
},
sub(context, value) {
context.commit("sub", value);
},
};
const mutations = {
add(state, value) {
state.NTest += value;
},
sub(state, value) {
state.NTest -= value;
},
};
const state = {
NTest: 0,
};
// 创建store
export default new Vuex.Store({
actions,
mutations,
state,
});
demo.vue
<template>
<div>
<h1 class="demo">当前和为:{{ $store.state.NTest }}</h1>
<select v-model.number="n">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<button @click="add">+</button>
<button @click="sub">-</button>
<button @click="addOdd">奇加</button>
</div>
</template>
<script>
export default {
name: "demo", //一般和文件名相同
data() {
return {
n: 1,
};
},
methods: {
add() {
this.$store.dispatch("add", this.n);
},
sub() {
this.$store.dispatch("sub", this.n);
},
addOdd() {
if (this.n % 2 != 0) {
this.$store.dispatch("add", this.n);
}
},
},
};
</script>
<style>
.demo {
color: aqua;
}
button {
margin: 5px;
}
</style>
main.js
import Vue from "vue";
import App from "./app.vue";
Vue.config.productionTip = false;
// 引入store
import store from "./store/index";
new Vue({
render: (h) => h(App),
store,
beforeCreate() {},
}).$mount("#app");
getter
加工数据
const getters = {
bigsum(state) {
return state.NTest * 10;
},
};
// 创建store
export default new Vuex.Store({
actions,
mutations,
state,
getters,
});
应用:
<h1>放大十倍和:{{$store.getters.bigsum}}</h1>
mapState
帮助生成计算属性,映射state
当键值对相同时,可以使用数组写法
mapGetters
用法作用与mapstate相同,不过是映射getter
mapMutations
同上
注:需要传参
mapActions
同上,也需要传参
模块化配置
分两个配置模块
分别加载
分别使用
也可以这么写
要开启namespace:true
16.Vue-router
基本使用
main.js
import Vue from 'vue'
import App from './App.vue'
import VueRouter from 'vue-router' // 引入VueRouter
import router from './router' // 引入路由器
Vue.config.productionTip = false
Vue.use(VueRouter) // 应用插件
new Vue({
el:'#app',
render: h => h(App),
router:router
})
index.js
import VueRouter from 'vue-router'
// 引入组件
import About from '../components/About'
import Home from '../components/Home'
// 创建并暴露一个路由器
export default new VueRouter({
routes:[
{
path:'/about',
component:About
},
{
path:'/home',
component:Home
}
]
})
About.vue
<template>
<h2>我是About的内容</h2>
</template>
<script>
export default {
name:'About'
}
</script>
Home.vue
<template>
<h2>我是Home的内容</h2>
</template>
<script>
export default {
name:'Home'
}
</script>
App.vue
<template>
<div>
<div class="row">
<div class="col-xs-offset-2 col-xs-8">
<div class="page-header"><h2>Vue Router Demo</h2></div>
</div>
</div>
<div class="row">
<div class="col-xs-2 col-xs-offset-2">
<div class="list-group">
<!-- 原始html中我们使用a标签实现页面的跳转 -->
<!-- <a class="list-group-item active" href="./about.html">About</a> -->
<!-- <a class="list-group-item" href="./home.html">Home</a> -->
<!-- Vue中借助router-link标签实现路由的切换 -->
<router-link class="list-group-item"
active-class="active" to="/about">About</router-link>
<router-link class="list-group-item"
active-class="active" to="/home">Home</router-link>
</div>
</div>
<div class="col-xs-6">
<div class="panel">
<div class="panel-body">
<!-- 指定组件的呈现位置 -->
<router-view></router-view>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name:'App'
}
</script>
多级路由
//使用children配置
routes:[
{
path:'/about',
component:About,
},
{
path:'/home',
component:Home,
children:[ // 通过children配置子级路由
{
path:'news', // 此处一定不要带斜杠,写成 /news
component:News
},
{
path:'message', // 此处一定不要写成 /message
component:Message
}
]
}
]
路由query参数
传递参数
<!-- 跳转并携带query参数,to的字符串写法 -->
<router-link :to="`/home/message/detail?id=${m.id}&title=${m.title}`">跳转</router-link>
<!-- 跳转并携带query参数,to的对象写法(推荐) -->
<router-link
:to="{
path:'/home/message/detail',
query:{
id: m.id,
title: m.title
}
}"
>跳转</router-link>
接收参数
$route.query.id
$route.query.title
路由params参数
{
path:'/home',
component:Home,
children:[
{
path:'news',
component:News
},
{
component:Message,
children:[
{
name:'xiangqing',
path:'detail/:id/:title', // 🔴使用占位符声明接收params参数
component:Detail
}
]
}
]
}
注意:路由携带params参数时,使用to对象写法时,不能使用path参数,只能使用name
<!-- 跳转并携带params参数,to的字符串写法 -->
<router-link :to="/home/message/detail/666/你好">跳转</router-link>
<!-- 跳转并携带params参数,to的对象写法 -->
<router-link
:to="{
name:'xiangqing',
params:{
id:666,
title:'你好'
}
}"
>跳转</router-link>
接收参数
$route.params.id
$route.params.title
路由props参数
让路由组件更方便接收参数
{
name:'xiangqing',
path:'detail/:id',
component:Detail,
//第一种写法:props值为对象,该对象中所有的key-value的组合最终都会通过props传给Detail组件
// props:{a:900}
//第二种写法:props值为布尔值,为true时,则把路由收到的所有params参数通过props传给Detail组件
// props:true
//第三种写法:props值为函数,该函数返回的对象中每一组key-value都会通过props传给Detail组件
props($route){
return {
id: $route.query.id,
title: $route.query.title
}
}
}
命名路由
配置路有名字,简化代码
{
path:'/demo',
component:Demo,
children:[
{
path:'test',
component:Test,
children:[
{
name:'hello' // 给路由命名
path:'welcome',
component:Hello,
}
]
}
]
}
<!--简化前,需要写完整的路径 -->
<router-link to="/demo/test/welcome">跳转</router-link>
<!--简化后,直接通过名字跳转 -->
<router-link :to="{name:'hello'}">跳转</router-link>
<!--简化写法配合传递参数 -->
<router-link
:to="{
name:'hello',
query:{
id:666,
title:'你好'
}
}"
>跳转</router-link>
编程式路由导航
作用:不借助routerlink实现路由跳转,让路由跳转更加灵活
push,replace
this.$router. push({}) 内传的对象与 中的 to 相同
this.$router.push({
name:'xiangqing',
params:{
id:xxx,
title:xxx
}
})
this.$router.replace({
name:'xiangqing',
params:{
id:xxx,
title:xxx
}
})
forward,back, go
forward前进,back后退,go可前进也可后退,n为正数前进n,为负数后退
<template>
<div class="col-xs-offset-2 col-xs-8">
<div class="page-header">
<h2>Vue Router Demo</h2>
<button @click="back">后退</button>
<button @click="forward">前进</button>
<button @click="test">测试一下go</button>
</div>
</div>
</template>
<script>
export default {
name:'Banner',
methods:{
back(){
this.$router.back()
},
forward(){
this.$router.forward()
},
test(){
this.$router.go(3)
}
},
}
</script>
路由缓存
因为切换路由组件,会导致之前的组件被销毁
// 缓存一个路由组件
<keep-alive include="News"> // include中写想要缓存的组件名,不写表示全部缓存
<router-view></router-view>
</keep-alive>
// 缓存多个路由组件
<keep-alive :include="['News','Message']">
<router-view></router-view>
</keep-alive>
activated,deactivated
两个路由生命周期
activated:路由组件被激活时触发
deactivated:路由组件失活时触发
路由守卫
全局守卫
// 全局前置守卫:初始化时、每次路由切换前执行
router.beforeEach((to,from,next) => {
console.log('beforeEach',to,from)
if(to.meta.isAuth){ // 判断当前路由是否需要进行权限控制,meta自己定义
if(localStorage.getItem('school') === 'nju'){ // 权限控制的具体规则
next() // 放行
}else{
alert('暂无权限查看')
}
}else{
next() // 放行
}
})
// 全局后置守卫:初始化时、每次路由切换后执行
router.afterEach((to,from) => {
console.log('afterEach',to,from)
if(to.meta.title){
document.title = to.meta.title //修改网页的title
}else{
document.title = 'vue_test'
}
})
独享守卫
没有后置守卫
{
name:'zhuye',
path:'/home',
component:Home,
meta:{title:'主页'},
children:[
{
name:'xinwen',
path:'news',
component:News,
meta:{title:'新闻'},
// 🔴独享守卫,特定路由切换之后被调用
beforeEnter(to,from,next){
console.log('独享路由守卫',to,from)
if(localStorage.getItem('school') === 'nju'){
next()
}else{
alert('暂无权限查看')
}
}
},
组件内守卫
<template>
<h2>我是About组件的内容</h2>
</template>
<script>
export default {
name:'About',
// 通过路由规则,离开该组件时被调用
beforeRouteEnter (to, from, next) {
console.log('About--beforeRouteEnter',to,from)
if(localStorage.getItem('school')==='nju'){
next()
}else{
alert('学校名不对,无权限查看!')
}
},
// 通过路由规则,离开该组件时被调用
beforeRouteLeave (to, from, next) {
console.log('About--beforeRouteLeave',to,from)
next()
}
}
</script>
路由工作模式
const router = new VueRouter({
mode:'history',
routes:[...]
})
export default router
Objcet.defineProperty
let number = 18;
let number2 = 100;
let person = {
name: "rokned",
//不使用getter
age: number,
};
//使用getter
Object.defineProperty(person, "weight", {
get() {
console.log("联动修改");
return number2;
},
set(value) {
number2 = value;
},
});