vue2学习笔记vue2记录
vue基础知识 初识:
Vue实例跟容器是一对一的关系。
尝试2容器1vue实例 vue实例只能接管前面一个 后面一个容器管不了
<h1 id="title">nihao,{{name}}</h1>
<h1 id="title">nihao,{{name}}</h1>
<script>new Vue({el:'#title',//尝试用了class 效果也是一样的 只照顾到前面那个data:{name:'北京'}
})
</script>
(js表达式可以理解成一个用变量去装的东西,a++,字符串拼接。。。)
插值里面的变量自动获得data对象里面的数据(其实是暴露VM模型的内部结构),data对象类似之前那个windows对象,属性为变量,里面再嵌套对象就按照对象:属性来调用。 模板语法:
通过vue命令改变标签的属性、行为等,用于解析标签。 数据绑定(v-bind、v-model)
简写:
动态地绑定一个或多个 attribute,或一个组件 prop 到表达式。
我的理解是:
v-bind就是动态地绑定dom元素的属性,让dom元素里面的属性的那个值跟表达式一样
eg:
v-bind: 将url当成一个变量 就去Vue实例里面找url属性了
可以简写成:
其实是对元素的value进行操作
<input class="inputbox" v-model:keywords="keywords" type="text" />
绑定class样式
可以使用v.$mount(‘css选择器’)来绑定对象
const v=new Vue({// el: ".title",//第一种写法data: {name: "北京",},
});
v.$mount('.title');//第二种写法
在写成普通函数声明的时候,函数的this指向vue实例,写成箭头函数的时候函数的this指向全局的window对象
可以理解成dom是表示层 VueModel是逻辑层 Model是数据层。VM在页面dom元素设置监听,并且绑定数据层data中的数据,当data中数据更新时,将实时更新表示层dom,如果采用双向绑定,dom元素value改变数据层data中的数据也会实时改变。
补充:下面这样写会报Reference ERROR 说找不到alert属性 这是因为表示层dom绑死在VM上了,表示层只能看到VM作用域里面的数据 alert是window的 VM模型里面没有。。不是作用域链可以往外找这样。。可以将window作为内置对象解决(但是Vue实例是可以读到的window的属性的 那个是作用域链 要分清楚捏
就是不直接操作对象,使用中间商操作数据 补充:Object.defineProperties(要修改的对象,属性,配置对象)
例子:obj2通过中间商x来操作obj对象
let obj={x:100}
let obj2={y:200}
Object.defineProperty(obj2,'x',{get(){return obj.x//每次通过obj2访问obj.x都是通过getter去访问的},set(value){obj.x=value//每次通过obj2修改obj.x都是通过getter去访问的}
})
VM模型采用的也是数据代理,使用一个对象去new一个vue实例,数据层data中的数据**到vm模型里面,并进行加工之后使用_data属性存起来。使用数据代理,vm做中间商,好少写个_data。好像还用了观察者模式(?
<button id="root" v-on:click="show">nihao</button>
const v = new Vue({data: {name: "北京",},methods: {//记住不要写成method了 有sshow:function() {console.log("hello");},},
});
v.$mount("#root");
事件修饰符
事件修饰符可以连用
v-on:click
简写:v-on:简写成@
v-on:click===》@click 键盘事件
ctrl+y
计算实例通过对Vue现有属性的计算得到新的属性,叫做计算属性。数据源改变,计算属性根据改变的数据源在原来数据的基础上进行修改。
我感觉跟数据代理很像,计算属性的数据源于Vue实例里面的data对象里面的值,双向绑定的。数据源改变,计算属性调用getter更新,注意,不更新绑定的数据就没什么用,不更新数据源计算属性不会变(其实跟页面元素很像耶。。不过计算属性也的的确确是Vue、VC实例里面的属性就是说。
不同的是计算属性是基于它们的响应式依赖进行缓存的。只在相关响应式依赖发生改变时它们才会重新求值
这也同样意味着下面的计算属性将不再更新,因为 Date.now() 不是响应式依赖:
computed: {now: function () {return Date.now()}
}
缓存这两个字很重要,缓存意味着是计算属性先保留了一份数据源的值,等到响应式依赖数据源发生变化的时候才会更新计算属性数据源。
methods的this是整个Vue实例,不加this就找不到的原因已经是不在methods这个对象里面,找上一层一直找到最外层的window也没有(作用域链想起没哇(。 以前的知识不要丢哇
<div id="root">姓 <input type="text" v-model='fn'></br>名<input type="text" v-model='sn'></br>
full<span>{{full()}}</span>
</div>
new Vue({el:'#root',data:{fn:'fn',sn:'sn'},methods:{full(){return this.fn+'-'+this.sn//为什么要加this才能用 不加this会报错//[Vue warn]: Error in render: "ReferenceError: fn is not defined"}}})
</script>
在最外面加了就能过了
fn=2
sn=1
new Vue({el:'#root',data:{fn:'fn',sn:'sn'},methods:{full(){return fn+'-'+sn}}
})
姓名例子:
let vm=new Vue({el:'#root',data:{fn:'fn',sn:'sn'},computed:{full:{get(){console.log('getter');return this.fn+'-'+this.sn},set(value){const arr=value.split('-')this.fn=arr[0]this.sn=arr[1] }}}
})
计算属性简写(只读不改):
计算属性setter
计算属性默认只有 getter,不过在需要时你也可以提供一个 setter: // ...
computed: {fullName: {// getterget: function () {return this.firstName + ' ' + this.lastName},// setterset: function (newValue) {var names = newValue.split(' ')this.firstName = names[0]this.lastName = names[names.length - 1]}}
}
// ...
现在再运行 vm.fullName = 'John Doe' 时,setter 会被调用,vm.firstName 和 vm.lastName 也会相应地被更新。
计算属性setter是会更改数据源的。 监视属性 Watch
监视的属性不存在监视没有作用 但是不会报错(f u
watch:{keyWord:{immediate:true,handler(value)//value传的是监控的值的新值,第二个变量传的是之前的值{this.filPer=this.per.filter((p)=>{//vue管理的函数this应该是vue实例return p.id.indexOf(value)!==-1})}}
}
深度监视 deep
监视引用变量的时候,watch默认检测的变量存的地址值,只要对象不变,watch是不会检测到变化的,可开启deep值,检测引用的对象的变化。
例子:
点击btn,obj的bool置反。watch监视的是对象obj,开了deep,能监视到对象里面的改变,但是由于监视的对象没变,所以传给handler的newValue跟oldValue都没有变化,打印的bool值就都是较新那个值啦。
<div id="root"><button @click="sw">{{obj.bool}}</button></div>
new Vue({el:"#root",data:{obj:{bool:true}},methods:{sw(){this.obj.bool=!this.obj.bool// this.obj={}}},watch:{obj:{deep:true,handler(newValue,oldValue){console.log(newValue.bool+','+oldValue.bool)}}}
})
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6ebo4jka-1647068009438)(D:/Typora/image-20211025201456438.png)] 监视简写(只使用handler):
那个function别写成箭头函数了,会出this问题(。
使用观察者模式
要知道js里面只有两种作用域(es5):函数作用域跟全局作用域。es6新增的作用域是对于let关键字而言的,对于其他还是只有两种作用域啦。
箭头函数本质是return语句啦,没有自己的this,所以用的定义时父级的this
如例子中 作用域只有一个:全局window 对象a并不是作用域哦!对象没有自己的作用域,所以不能充当箭头函数的this,套一个普通函数,里面再放箭头函数,移花接木一下估计可以。
var name = 'window'; var A = {name: 'A',sayHello: () => {console.log(this.name)}
}A.sayHello();// 还是以为输出A ? 错啦,其实输出的是window
移花接木ver
var A = {name: 'A',sayHello:function (){let a=()=> {console.log(this.name)}a()}
}A.sayHello();//A
普通函数的this可以指向A 是因为自己分割出了一个作用域
var name = 'window'; // 其实是window.name = 'window'var A = {name: 'A',sayHello: function(){console.log(this.name)}
}A.sayHello();// 输出A
条件渲染(v-if、v-show)
底层通过调整css的display v-show='false’是 元素节点还是在的只不显示了。
<div v-show="false" id="root" ><button @click="sw">{{obj.bool}}</button>
</div>
v-if 也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。
条件判断语句,v-if条件为真时才渲染元素,条件为假时是不渲染元素的,所以节点根本就不在dom树里面。
<div v-show="false" id="root" ><button @click="sw">{{obj.bool}}</button>
</div>
还有v-else-if v-else跟普通的一样 就是形成一组判断了就是说 btw v-else后面跟条件没有用(但是也不会报错就是说
为了形成一组判断 不可以被打断 被打断后的就判断作废 被没有相通的v-if
<div id="root" ><div v-if="false"></div><button @click="sw">{{obj.bool}}</button><div v-else-if='true'>11111111</div>
</div>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RtFv9Tzi-1647068009443)(D:/Typora/image-20211026184032244.png)]
v-if 例子2
window.onload = function () {//创建一个vue实例var app = new Vue({el: "#app",data: {type: "A",loginType: "username",},methods: {changeloginType() {let self = this;if (self.loginType == "username") {self.loginType = "";} else {self.loginType = "username";}},},});
style="color: green"
>v-if的弹框切换</div><template v-if="loginType === 'username'"><label>用户名:</label><input placeholder="Enter your username" key="username-input" /></template><template v-else><label>密码:</label><input placeholder="Enter your e**il address" key="e**il-input" /></template><button @click="changeloginType">切换状态</button>
</div> 针对例子补充 template标签:
浏览器不对template进行渲染 渲染时自动丢掉 不会出现在dom节点里面 只能和v-if配合使用 v-show不行
<div><div id="root"><template><div v-if="false"></div><button @click="sw">{{obj.bool}}</button><div>11111111</div></template></div>
</div>
而且会导致找不到root 不是外面包东西的原因 好像就是因为template
<div><template><div id="root"><div v-show="false"></div><button @click="sw">{{obj.bool}}</button><div>11111111</div></div></template>
</div>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Sqyf0ekB-1647068009444)(D:/Typora/image-20211026184944175.png)] 列表渲染(v-for) 基本概念
当 v-if 与 v-for 一起使用时,v-for 具有比 v-if 更高的优先级。(但是文档并不推荐两个一起用!)
基于源数据多次渲染元素或模板块。此指令之值,必须使用特定语法 alias in expression,为当前遍历的元素提供别名
首先要明确,v-for写在哪里就是列表渲染哪个,如下面。v-for写在div里面,渲染items.length个div!!!
v-for别名的作用域是自己跟子元素。
<div v-for="item in items"><!--item就是别名-->{{ item.text }}
</div>
另外也可以为数组索引指定别名 (或者用于对象的键): <div v-for="(item, index) in items"></div>
<div v-for="(val, key) in object"></div>
<div v-for="(val, name, index) in object"></div>
v-for 的默认行为会尝试原地修改元素而不是移动它们。要强制其重新排序元素,你需要用特殊 attribute key 来提供一个排序提示(绑定的key就变成数组元素的索引了)(有看到说key不止这种用法)
以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key attribute(文档原文)
<div v-for="item in items" :key="item.id">{{ item.text }}
</div>
key注意点:
建议尽可能在使用 v-for 时提供 key attribute,除非遍历输出的 DOM 内容非常简单,或者是刻意依赖默认行为以获取性能上的提升(有key性能会好一点?)
不要使用对象或数组之类的非基本类型值作为 v-for 的 key。请用字符串或数值类型的值。
v-for就是做循环,就是包装了for循环
v-for可以连着in跟of一起(即支持for..in、for...of) v-for…in遍历数组
<div id="root"><ul><li v-for="p,index in person">{{p}},{{index}}</li></ul>
</div>
new Vue({el: "#root",data: {person:[{id:001,name:1},{id:002,name:2},{id:003,name:3},]},
});
第一个参数是属性的值,第二个参数是属性名,第三个是index,属性排第几个(只有对象可以这么搞,数组不行,数组第二个一定是index)
<div id="root"><ul><li v-for="(value,attr,index) in person">{{value}}---{{attr}}---{{index}}</li></ul>
</div>
new Vue({el: "#root",data: {person:{id:"dsasf",name:"sdgvsdf"},},
});
遍历次数跟python的for in range一样。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yAteWrSX-1647068009452)(D:/Typora/image-20211026190235388.png)] v-for注意点
在遍历对象时,会按 Object.keys() 的结果遍历,但是不能保证它的结果在不同的 JavaScript 引擎下都一致。
<ul> <li v-for="item in items"><li>{{items}}</li> </li></ul> <ul> <li></li><li>{{items}}</li> </ul>由于兄弟是看不见的 所以不能看到那个items 也就出错了
v-for是先做循环 然后再跟着下面的(其实这个就是很普通的一个点,就是要记住v-for就是for就是经过包装的for 可以用来控制虚拟dom节点
<li @mouseenter="changeLiBgc(index)"v-for="(groupMenuitem, index) in groupMenuitems"
:key="index"
:class="{ cur: currentIndex == index }"></li>
changeLiBgc(index) {this.$data.currentIndex = index;console.log("index"+index)console.log(this.$data.currentIndex)},
这个是在写尚品汇的时候的一个小的li标签,是三级联动部分。
当鼠标移动到li上的时候触发mouseenter事件,函数changeLiBgc(index)执行,传的是li执行v-for的索引,只会传鼠标enter的那个元素的index。按照这个的话,后面就比较好理解,但是我自己说不出个所以然来。(是不是因为mouseenter,传EventTarget传了li的index)
我觉得可能不能完全按照以前的for循环去理解v-for,我以前学的for循环做完就不会再进行改变了,但是v-for是动态的。
=》v-for做完循环,将虚拟dom变成真实dom,它就会有各种各样的属性,渲染出来的li对象里面有自己的index,当鼠标放上去的时候触发mouseenter事件,将currentIndex赋值成index,然后classv-bind绑定了,计算{}里面js表达式的值。
key原理 diff
在内存中对key相同的节点进行比较,如果内容一样则将之前渲染过的节点直接拿来用,否则就将放弃掉之前的节点,重新渲染虚拟dom节点成真实dom节点。 总结:
就是使用index作为key的时候(不写key默认将遍历时候的index作为唯一标识),当在前面插入/删除节点时,会造成节点与index的顺序改变 从而造成输入类元素对应不上
如果自定义唯一标识的话,就可以进行更多的重用 只新增新的节点 省去了重新生成旧节点 效率更高
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4xr6IwQ4-1647068009454)(D:/Typora/image-20211026222826520.png)]
补一个用index做key的坏处:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6ufJExOV-1647068009459)(D:/Typora/image-20211027201206101.png)]
new Vue({el:'#root',data:{keyWord:'',per:[{id:'001',name:'aa'},{id:'002',name:'bb'},{id:'003',name:'cc'},],filPer:[]},watch:{keyWord:{immediate:true,handler(value){this.filPer=this.per.filter((p)=>{return p.id.indexOf(value)!==-1})}}}
})
Array.filter(),不会对空数组进行检测,不会改变原始数组。
Array.filter(()=>{return 判断条件//这个函数的返回值要是布尔值 要么true 要么false
})//filter返回由旧数组符合条件的值的数构成的新数组
表单收集数据的技巧
防止网速过慢出现插值语法。。
全局指令和局部指令的区别:
全局指令可供整个页面使用,而局部指令只作用于他定义的那个vue实例
全局指令就是直接定义在Vue上,局部就是包在一个vue实例里面 函数式声明
自己敲了一遍 修改name已经不会调用big了(不知道是不是vue3的优化?
调用big应该修改成:
1.第一次解析模板时 被调用
2.指令其绑定的数据源发生改变
const vm=new Vue({el: "#root",data: {n: 1,name:"shang"},directives: {big(el, binding)//第一个传的是要操作htmlElement元素 第二个传的是这个绑定的对象{console.log('big')el.innerText=binding.value*10},},
});
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YOyWisMA-1647068009466)(D:/Typora/image-20211028132122785.png)]
输出的binding:
官方文档的使用函数式获取不了焦点是因为一开始在vue执行指令的时还没有放到页面上 所以element.focus没有用
上面简写的函数式声明,只用了bind、update,没有inserted。自定义指令里面函数的this都是window,并不是vue去维护指令的。其实也好理解,因为自定义指令是直接对dom操作,不经vue手也很正常。
Vue.config.productionTip = false;
const vm=new Vue({el: "#root",data: {n: 1,name:"shang"},directives: {big(el, binding) {console.log(this)//windowel.innerText=binding.value*10},fbind:{//指令与元素成功绑定时(元素还在内存 vue还没有将元素放到页面上 简写成函数式的话就是只用bind+update了bind(el,binding){el.value=binding.valueconsole.log(this)//window},//指令所在元素**入到页面时inserted(el,binding){el.focus()},//指令所在模板被重新解析时(模板重新解析?update(el,binding){console.log('update')}}}
});
全局指令
写在vue实例里面的是局部指令 只能那个vue实例用 其他实例用不了 写全局指令的话要放到Vue里面(写到构造函数里面 当成属性一起继承使用 生命周期
beforeCreate:初始化生命周期、事件(mothods)但是还没执行数据代理(没有_data _data是undefined!beforeCreate的before是指在数据检测、数据代理之前
created:初始化数据检测、数据代理
然后开始找el、template编译虚拟dom
beforeMount:对dom的操作最终不奏效
在挂载之前,将虚拟dom编译,产生el用el 用el用el替换掉el
将真实dom挂载到页面上
Mounted:东西都挂好了,页面上显示的是经过vue编译、解析的dom元素 可以对页面上的元素做点想做的操作了。
beforeUpdate:在内存中 已经更新了数据 但是页面上的数据还没更新 还没将更新的元素解析挂到页面上
updated:数据已经更新到页面了 页面数据与内存数据同步
beforeDestroy:可以读到data、method,但是不能够进行修改 因为更新要进行update 已经走到这里了 不能回头走update了
destoryed:
摧毁阶段 断掉事件监听、数据检测、跟其他实例的联系 虽然说断掉了事件监听 但是已经绑上的dom事件不会随着vue事件被摧毁而解开 比如给btn绑了点击事件 vue实例destoryed了btn的点击事件还是绑着的
页加载渲染完成之后,会自动执行的方法。
Vue完成模板解析,并将真实dom放到页面(挂载)之后执行,只会执行一次。
Vue.createApp({data() {return {counter: 1,};},mounted(){console.log("页面加载完成之后自动执行的函数")setInterval(()=>{this.counter+=1},1000)},template: "<div>{{counter}}</div>",
}).mount("#app");
<div id="root">姓 <input type="text" v-model='fn'></br>名<input type="text" v-model='sn'></br>full<span>{{full}}</span>
</div>
组件
模块化跟组件化是两种并行的思想。模块化跟组件化都是封装,就是封装内部逻辑,暴露一些接口。 data要用函数式:
对象为引用类型,当重用组件时,由于数据对象都指向同一个data对象,当在一个组件中修改data时,其他重用的组件中的data会同时被修改;而使用返回对象的函数,由于每次返回的都是一个新对象(Object的实例),引用地址不同,则不会出现这个问题
Vue.config.productionTip = false;
//组件
const school = Vue.extend({template: `<div>{{names}}<br>{{address}}</div>`,data() {return {names: "dsgfd",address: "gz",};},
});
//反正只是一个配置对象 自动有个判断 其实也调用了 Vue.extend
const school = {template: `<div>{{names}}<br>{{address}}</div>`,data() {return {names: "dsgfd",address: "gz",};},
}new Vue({el: "#root",components: {//配置项都是对象 要写对 真无语了 我是笨蛋schools: school,},
});
VueComponent
在写props代码的时候一直没有注册 然后就提示没有使用子组件 原来是因为没有注册 人家不认识 就说没有用!!!
Vue.config.productionTip = false;
//组件
const school = Vue.extend({//在调用Vue.extend()的时候其实自动new VueComponent()来构造组件了template: `<div>{{names}}<br>{{address}}</div>`,data() {return {names: "dsgfd",address: "gz",};},
})new Vue({el: "#root",components: {//一定要注册 注册才算使用了 不登记谁tm知道你名字 人家不认识啊schools: school,},
});
console.log(school)
vc跟vm差不多 belike vm删减版
vm-》app(vc头子)-》其他vc 还是子父节点那套
//简写
new Vue({render: h => h(App),
}).$mount('#app')
//完整版
new Vue({render(createElement) {return createElement(App)},
}).$mount('#app')
render(createElement)
渲染函数,根据拿到的虚拟节点渲染到页面上。一定要有返回值,用createElement返回,要拿到节点才能去渲染。
createElement(html元素|组件,元素属性,子节点内容)用于创建虚拟dom元素。约定的简写叫 h, vm中有一个方法 _c, 也是这个函数的别名。在Vue2中,虚拟DOM就是通过一种VNode类表达,每个DOM元素或组件都对应一个VNode对象。
相当于原生的getElementById()
app.vue文件函数里面的this都是vc组件 确实(。不然呢
show(){console.log(this)}给html标签加上ref属性之后,就自动加到vc的$refs里面,被收集了。跟以前加id是一样的。
如果加的是组件标签就将组件加到$refs里面
首先要明确 props传的东西只是变量里面的值(也就是belike浅**) 传的只是对象的地址 并不是对象的值(props是只读的)
首先可以实现组件间通信,主要是父子间的通信,实现兄弟间的通信就比较麻烦,要借助父组件,子传父再传兄弟,不如直接使用vuex比较方便。
为什么说是父子组件间通信呢,这主要是通过给组件的属性赋值来传递。要注册组件这必然是父子组件了。父传子:
//home.vue
<div><three :i**ove="true"></three></div>
此外,从子->父的通信 父给子一个函数子调用,传参,数据传回父组件里面。
除了上面的通过props来静态地绑定,也可以通过v-bind动态绑定。
prop 可以通过 v-bind 动态赋值,例如:
<!-- 动态赋予一个变量的值 -->
<blog-post v-bind:title="post.title"></blog-post><!-- 动态赋予一个复杂表达式的值 -->
<blog-postv-bind:title="post.title + ' by ' + post.author.name"
></blog-post>
传入一个对象的所有 property
如果你想要将一个对象的所有 property 都作为 prop 传入,你可以使用不带参数的 v-bind (取代 v-bind:prop-name)。例如,对于一个给定的对象 post:
post: {id: 1,title: 'My Journey with Vue'
}
<blog-post v-bind="post"></blog-post>
等价于:
<blog-postv-bind:id="post.id"v-bind:title="post.title"
></blog-post>
改变一个prop的方法(2种):
**这个 prop 用来传递一个初始值;这个子组件接下来希望将其作为一个本地的 prop 数据来使用。**在这种情况下,较好定义一个本地的 data property 并将这个 prop 用作其初始值:
props: ['initialCounter'],
data: function () {return {counter: this.initialCounter}
}
**这个 prop 以一种原始的值传入且需要进行转换。**在这种情况下,较好使用这个 prop 的值来定义一个计算属性:
props: ['size'],
computed: {nor**lizedSize: function () {return this.size.trim().toLowerCase()}
}
注意:
在 JavaScript 中对象和数组是通过引用传入的,所以对于一个数组或对象类型的 prop 来说,在子组件中改变变更这个对象或数组本身****将会影响到父组件的状态。 mixin
mixin的话this是指向组件的 纯纯滴工具人
//组件
<template>
<div>
<h1>子组件</h1><button @click="showname">showname</button>
</div>
</template><script>
import {mixin} from './mixin'
export default {name:'child',props:{zsq:{type:String,default:'zzzsq'}},methods: {showzsq(){console.log(this.zsq)}},data(){return {name:'jack'}},mixins:[mixin]//配置项一定是数组 一个也是
}
</script>
//mixin.js
export let mixin={methods:{showname(){console.log(this.name)}}}
插件
在vue单文件组件中,为了防止全局同css类名名样式的污染,vue-loade对单文件组件 <style> 标签增加了scoped属性的处理。原理就是在html标签上添加data-v-xxxxxxxx属性,然后在css类名后添加属性选择器,即利用css类选择 + 属性选择器实现样式局部化。
使用了scoped之后,就加了data-v-xxxxxxxx属性属性而已,避免污染其他的。
以键值对的形式保存,只能够保存字符串,对象用json.stringify转成字符串再保存,不然会就直接调用tostring方法没啥意义
sessionStorage是会话存储,打开一次浏览器算是一次会话,关闭浏览器就没有了。
LocalStorage清除:1.调用clear/removeStorage 2.浏览器设置里面清除缓存
有两种调用:
1.通过$emit
sname是自定义事件名 当事件触发是调用**函数
App.vue
<template><student @sname="**"></student>
</template>
student.vue
<template><div><span>{{ studentName }}</span><button @click="send**">获取学生姓名</button></div>
</template><script>
export default {name: "student",data() {return {studentName: "李华",};},methods: {send**() {this.$emit('sname',this.studentName);//调用函数 $emit触发sname事件,后面就是给sname传的参,可以传无限多个},},
};
</script>
2.ref
<script>
export default {name: 'App',components: {school:school,student:student},methods: {**(sn){console.log(sn)}},mounted() {this.$refs.student.$on("sname",this.**)//this.refs.student拿到了App上的student子组件 然后通过$on给子组件绑定自定义事件sname,sname触发时调用**函数
//这里有一个坑 当使用methods里面声明的函数,函数的this一定是methods的那个vue对象
//如果这里写成 这样虽然可以输出 但是app实际上是没有拿到sn的 因为下面这个函数的this指向的是student子组件
//回调函数也是普通的函数,js里面就函数跟对象可以切割作用域。
//回调函数有自己的this 里面保存的就是调用回调函数的对象=》谁调用,回调函数的this就是谁this.$refs.student.$on("sname",function(sn){console.log(sn)this.sname=snconsole.log(this)})//改成箭头函数就行 //箭头没有自己的作用域,没有自己的this 所以用mounted的作用域(?用的就是当前组件的作用域,即Appthis.$refs.student.$on("sname",(sn)=>{console.log(sn)this.sname=snconsole.log(this)})},
}
</script>
要加native才会当成原生 默认是自定义事件
解绑:
能够实现任意组件间通信
我的理解就是在用一个所有人都能看到的中介,也有点像计网里面的总线结构。所有人都在总线(中介)里面做一个自定义事件,a要给b传数据就调用触发b的自定义事件。其实用的也是昨天学的使用自定义事件来实现子传父的那一套。
为了让所有人都能够看见中介使用直接在Vue里面定义。
beforeCreate()这时候还没有初始化完,所以可以在这里放个prototype,来让实例继承$bus。
补充$on:
this.$bus.$on("checkTodo",this.checkTodo) 消息订阅与发布订阅者:
mounted(){pubsub.subscribe('hello',function(msgName,data){console.log('hellllo订阅'+msgName+" "+data)console.log(this)//undefined//使用第三方库的话,普通函数的this就是undefined 毕竟第三方库vue也不知道你用的什么//使用箭头函数就可以跳出调用的 直接出去找this 就是这个vc实例了
})
发布者:
methods: {send**() {pubsub.publish('hello','6666666666')//消息名 数据//传的时候传的第一个参数是消息名,第二个参数才是数据..//就是回调函数收到第一个参数是消息名,第二个才是数据 //改todo案例的时候给我整无语了 一直删不掉 才知道参数收的消息名},
},
取消订阅:
todo发布:
del(id) {this.$bus.$emit("delTodo", id);// pubsub.publish('delTodo',id,'xx');},
delTodo(id){//这个参数是消息名 谁狠狠无语了。。this.todos=this.todos.filter( (todo) =>{return todo.id!=id}) nextTick
在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。
Vue的更新DOM是异步的。数据变化(比如vm.someData = 'new value'),Vue不会立即重新渲染组件,执行DOM的更新。而是把这些要更新的事件放入一个队列里面,并进行去重。在下一个的事件循环“tick”中,Vue 刷新队列并执行实际 (已去重的) 工作。
当你设置 vm.someData = 'new value',该组件不会立即重新渲染。当刷新队列时,组件会在下一个事件循环“tick”中更新。这样回调函数将在 DOM 更新完成后被调用。为了在数据变化之后等待 Vue 完成更新 DOM,可以在数据变化之后立即使用 Vue.nextTick(callback)
<div id="example">{{message}}</div>
var vm = new Vue({el: '#example',data: {message: '123'}
})
vm.message = 'new message' // 更改数据
vm.$el.textContent === 'new message' // false
Vue.nextTick(function () {vm.$el.textContent === 'new message' // true
})
组件内使用:
回调函数中的 this 将自动绑定到当前的 Vue 实例上:
<script>
Vue.component('example', {template: '<span>{{ message }}</span>',data: function () {return {message: '未更新'}},methods: {updateMessage: function () {this.message = '已更新'console.log(this.$el.textContent) // => '未更新'this.$nextTick(function () {//这里的this是vcconsole.log(this.$el.textContent) // => '已更新'})}}
})
</script>
因为 $nextTick() 返回一个 Promise 对象,所以你可以使用新的 ES2017 async/await语法完成相同的事情: methods: {updateMessage: async function () {this.message = '已更新'console.log(this.$el.textContent) // => '未更新'await this.$nextTick()console.log(this.$el.textContent) // => '已更新'}
}
总结?
这个是在尚硅谷那个项目里面看到的 顺便看了一下vue的响应式原理 才知道vue的更新是异步的
在组件里发请求,我们希望的是等到返回的数据,然后对数据执行v-for,但是由于这个vue对dom更新是异步的。可能由于返回太久,先对没有返回的的数据执行v-for,执行dom更新,对于后面返回的数据无动于衷。使用this.$nextTick的话就可以把操作排到队伍较后面,等到异步完成了再上。 动画
下面这几种才能用vue的动画
条件渲染 (使用 v-if)
条件展示 (使用 v-show)
动态组件
组件根节点
vue的动画用的是transition 的封装组件,就是什么要加上动画效果,就用<transition><\transition>包起来。
如果有多个组件执行动画:
用v-for然后用<transition-group><\transition-group>包起来,而且要执行key
用div包起来,这样就是还是一个节点
下例(过渡、动画帧):
过渡例子:
<div id="**"><button v-on:click="show = !show">Toggle</button><transition name="fade"><p v-if="show">hello</p></transition>
</div>
.fade-enter-active, .fade-leave-active {transition: opacity .5s;
}
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {opacity: 0;
}
动画帧例子:
<div id="example-2"><button @click="show = !show">Toggle show</button><transition name="bounce"><p v-if="show">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris facilisis enim libero, at lacinia diam fermentum id. Pellentesque habitant morbi tristique senectus et netus.</p></transition>
</div>
.bounce-enter-active {ani**tion: bounce-in .5s;
}
.bounce-leave-active {ani**tion: bounce-in .5s reverse;
}
@keyframes bounce-in {0% {transform: scale(0);}50% {transform: scale(1.5);}百% {transform: scale(1);}
}
当插入或删除包含在 transition 组件中的元素时,Vue 将会做以下处理:
自动嗅探目标元素是否应用了 CSS 过渡或动画,如果是,在恰当的时机添加/删除 CSS 类名。
如果过渡组件提供了 JavaScript 钩子函数(before-enter,enter,after-enter,enter-cancelled,before-leave,leave,after-leave,leave-cancelled),这些钩子函数将在恰当的时机被调用。
(当只用 JavaScript 过渡的时候,在 enter 和 leave 中必须使用 done 进行回调。否则,它们将被同步调用,过渡会立即完成。
推荐对于仅使用 JavaScript 过渡的元素添加 v-bind:css="false",Vue 会跳过 CSS 的检测。这也可以避免过渡过程中 CSS 的影响。)
如果没有找到 JavaScript 钩子并且也没有检测到 CSS 过渡/动画,DOM 操作 (插入/删除) 在下一帧中立即执行。(注意:此指浏览器逐帧动画机制,和 Vue 的 nextTick 概念不同) 过渡的类名
在进入/离开的过渡中,会有 6 个 class 切换。
v-enter:定义进入过渡的开始状态。在元素**入之前生效,在元素**入之后的下一帧移除。(我感觉就是插入的那一帧?)
v-enter-active:定义进入过渡生效时的状态。在整个进入过渡的阶段中应用,在元素**入之前生效,在过渡/动画完成之后移除。这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数。
v-enter-to:定义进入过渡的结束状态。在元素**入之后下一帧生效 (与此同时 v-enter 被移除),在过渡/动画完成之后移除。
v-leave:定义离开过渡的开始状态。在离开过渡被触发时立刻生效,下一帧被移除。
v-leave-active:定义离开过渡生效时的状态。在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,在过渡/动画完成之后移除。这个类可以被用来定义离开过渡的过程时间,延迟和曲线函数。
v-leave-to:2.1.8 版及以上定义离开过渡的结束状态。在离开过渡被触发之后下一帧生效 (与此同时 v-leave 被删除),在过渡/动画完成之后移除。
对于这些在过渡中切换的类名来说,如果你使用一个没有名字的 <transition>,则 v- 是这些类名的默认前缀。如果你使用了 <transition name="my-transition">,那么 v-enter 会替换为 my-transition-enter。 css动画补充: @keyframes(关键帧)
关键帧 @keyframes at-rule 规则通过在动画序列中定义关键帧(或waypoints)的样式来控制CSS动画序列中的中间步骤。
@keyframes slidein {from {transform: translateX(0%); }to {transform: translateX(百%);}
}
(mdn)要使用关键帧, 先创建一个带名称的 @keyframes 规则,以便后续使用 ani**tion-name性将动画同其关键帧声明匹配。每个 @keyframes 规则包含多个关键帧,也就是一段样式块语句,每个关键帧有一个百分比值作为名称,代表在动画进行中,在哪个阶段触发这个帧所包含的样式。也可以按任意顺序列出关键帧百分比;它们将按照其应该发生的顺序来处理。
(菜鸟教程)创建动画是通过逐步改变从一个CSS样式设定到另一个。
在动画过程中,您可以更改CSS样式的设定多次。
指定的变化时发生时使用%,或关键字"from"和"to",这是和0%到100%相同。
0%是开头动画,100%是当动画完成。
感觉有点像进度条,from是开始0%处,干什么,然后中间20%、30%干什么,较后是到to干什么。逐渐从0%相似到百%相似。 重复定义
如果关键帧重名的话,以较后一次定义的为准。一个动画在一个时间只会用一个关键帧。一个关键帧(@keyframes)里面有多个一样的百分比,比如有两个20%,就将这两个20%的样式重叠。 配置代理(解决跨域问题)
为了解决跨域问题可以配置一个代理服务器
8080端口跟8080代理服务器的话就不算跨域,代理服务器跟真的要传数据的服务器之间也没什么跨域问题(跨域是ajax
浏览器的一个保护措施
这个public就是8080代理服务器的根目录 如果使用第一种方式的话,在里面找到就直接用自己的,就不进行转发了。
一定要写pathRewrite,不然url就会带api,在后端服务器中根本没这个路径,or拿错(。 插槽 默认插槽
在<slot> <\slot>的位置插入自定义标签的
app.vue
允许在自定义标签里面放多个标签 为slot指定名字 然后再放进去
↓已废弃
这种是现在推荐的v-slot写法:但是只支持template标签
通过给子组件里面的slot插槽绑定数据来传数据给父组件 slot-scope 废弃
推荐 2.6.0 新增的 v-slot。
预期:function argument expression
用法:
用于将元素或组件表示为作用域插槽。attribute 的值应该是可以出现在函数签名的参数位置的合法的 JavaScript 表达式。这意味着在支持的环境中,你还可以在表达式中使用 ES2015 解构。它在 2.5.0+ 中替代了 scope。
此 attribute 不支持动态绑定。
参考:作用域插槽 scope 移除
被 2.5.0 新增的 slot-scope 取代。推荐 2.6.0 新增的 v-slot。
用于表示一个作为带作用域的插槽的 <template> 元素,它在 2.5.0+ 中被 slot-scope 替代。
用法:
除了 scope 只可以用于 <template> 元素,其它和 slot-scope 都相同。
使用案例:
专门在Vue中实现集中式状态(数据)管理的一个Vue插件,对vue应用中的多个组件的共享状态进行集中式的管理(读/写),也是一种组件间的通信方式,且适用于任意组件间通信。
集中式:把所有人集中在一起上课,上课只需要上一遍。
分布式:到每个人的家里面,给每一个人都上一遍课。 适用场景(多个组件要共享统一份数据)
多个视图依赖于同一状态。
来自不同视图的行为需要变更同一状态。 工作原理
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9d4ro2yr-1647068009518)(D:/Typora/20220105180904.png)]
脚手架import机制:
先全局扫描一遍,将import的文件先执行一次
store/index.js
**in.js
// 这个文件用于准备Vuex的核心storeimport Vue from 'vue'
import Vuex from 'vuex'
// actions响应组件中的动作
const actions={// 这里context上下文就是那种的ministore 传两个值 一个ministore一个是valueplus:function(context,value){console.log("actions",context)// 这样做的就是一个转发 context.commit("plus",value)}// plus:function(context,value){// console.log("actions")// }
}
// mutations用于操作数据(state)
const mutations={// this.sum++plus:function(state,value){// console.log(state,value)state.sum++console.log(state,value)// console.log("mutations")}
}
// state储存数据
const state={sum:0
}
// Vue.use(Vuex)
export default new Vuex.Store({actions,mutations,state
})
__ob__: Observer这些数据是vue这个框架对数据设置的监控器,一般都是不可枚举的。
网上有很多解决的方案:
第一种:__ob__: Observer 是 Vue 对数据监控添加的属性,如果想去掉可以用赋值的方式。例如Object.assign({},this.owner)。 用这种方式也是可以解决。
**第二种:**假设list里面存放的就是那些带有__ob__: Observer的可以用JSON.parse(JSON.stringify(this.list))完美解决
完整案例:
score/index.js
// 这个文件用于准备Vuex的核心storeimport Vue from 'vue'
import Vuex from 'vuex'
// actions响应组件中的动作
const actions={// 这里context上下文就是那种的ministore 传两个值 一个ministore一个是valueplus:function(context,value){// 这样做的就是一个转发 context.commit("plus",value)},oddplus:function(context,value){if(this.state.sum%2){// 这样做的就是一个转发 context.commit("plus",value)}}
}
// mutations用于操作数据(state)
const mutations={// this.sum++plus:function(state,value){// console.log(state,value)state.sum++console.log(state,value)// console.log("mutations")}
}
// state储存数据
const state={sum:0
}
// Vue.use(Vuex)
export default new Vuex.Store({actions,mutations,state
})
count.vue
<template>
<div><span>计算结果:{{$store.state.sum}}</span><button @click="plus">+1</button><button @click="oddplus">奇数+1</button>
</div>
</template><script>
export default {name:"count",data() {return {// sum:0,value:0}},methods: {plus(){this.$store.dispatch('plus',2)// console.log(this.$store)},oddplus(){this.$store.dispatch('oddplus',2)}},
}
</script><style></style>
<template><div id="app"><count></count></div>
</template><script>
import count from './components/count'export default {name: 'App',components: {count}
}
</script><style>
#app {font-family: Avenir, Helvetica, Arial, sans-serif;-webkit-font-**oothing: antialiased;-moz-osx-font-**oothing: grayscale;text-align: center;color: #2c3e50;**rgin-top: 60px;
}
</style>
actions muation
更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。
Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的事件类型 (type)和一个回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数
mutation 必须是同步函数。
mutations: {someMutation (state) {api.callAsyncMethod(() => {state.count++})}
}
devtools需要记录mutation。然后如果mutation里面的函数是异步的话,不能控制异步函数什么时候做回调,也追踪不了回调函数里面的状态的改变,所以devtools根本就记录不了mutation了。 state
vuex使用单一状态树,用一个对象就包含了全部的应用层级状态,作为一个“唯一数据源 (SSOT)”而存在。整个应用只有一个store实例。
state作为构造器选项,定义了所有我们需要的基本状态参数。 getters
记得要在vuex里面进行引入
就是从state里面取出属性来当计算属性的
数组写法:
computed:{//意思是将vuex中的city数据映射到组件的computed属性里...**pState(["city"])
}
对象写法:
意思是将store里面的state里面的city属性映射到computed属性中的currentCity中(**p本身就有映射的意思)。即currentCity代表了$store.state.city
computed:{...**pState({currentCity:"city"})}
computed: **pState({// 第一种写法count: 'count', // 第二种写法**: (state) => state.**,// 用普通函数this指向vc组件,要注意 from: function (state) { return this.str + ':' + state.from},// 注意下面的写法看起来和上面相同,事实上箭头函数的this指针并没有指向vue实例(this是undefined 应该是es6用的严格模式 所以顶层的this是undefined的原因),因此不要滥用箭头函数from: (state) => this.str + ':' + state.frommyCmpted: function () {// 这里不需要state,测试一下computed的原有用法return '测试' + this.str}}),
写成函数的都会在用那个属性的时候 函数会调用一下 我感觉是计算属性的原因 **pGetters
我传的是pointerevent
其实就是跟谁交流就**p谁 **p其实还有一个映射的意思捏
分块暴露
里面记得写一个namespaced用以区分 让外面的人认识它!!注意是namespaced
通过切换页面内的部分组件 实现单页面部分内容(组件)的一个切换
路由是vue的一个插件 app.use(router)
路由配置:
router/index.js
import VueRouter from 'vue-router'import change from '../pages/change'
import home from '../pages/home'
import next from '../pages/next'//这里就是路由配置
const router=new VueRouter({//这里写的就是路由规则routes:[{path:'/change',component:change},{path:'/home',// name:'home',component:home,//嵌套了多级路由children:[{path:'next',component:next,}]}]
})export default routerconst originalPush = VueRouter.prototype.push
VueRouter.prototype.push = function push (location) {return originalPush.call(this, location).catch(err => err)
}
模板 router-link
这个是放url来进行跳转的,放在模板里面 较后经过vue-router库的编译会变成a标签。这使得 Vue Router 可以在不重新加载页面的情况下更改 URL。
active-class 点击激活里面配置的css样式
一级路由的写法:
多级路由:
这个用于指定组件的呈现位置。放在那里就是哪块组件进行变化。
1.文档
通过调用 app.use(router),我们可以在任意组件中以 this.$router 的形式访问它,并且以 this.$route 的形式访问当前路由。
所以可以this.router是全局的路由,每一个组件都能访问到它,this.router是全局的路由,每一个组件都能访问到它,this.router是全局的路由,每一个组件都能访问到它,this.route是当前组件的路由。
我的理解:
$router:全局路由的实例,是router构造方法的实例,用于编程式路由导航进行的路由跳转
$route:当前的路由信息对象
$router里面有全局的路由什么的 还有history、mode什么的,而且还能看到路由规则
route我理解成当前的路由对象(也不是页面,就是当前的路由对象)
2.注册完路由组件之后,不管是路由、路由组件、非路由组件上都有$router、$route属性
两者之间的联系this. router中的currentRoute(其实就是当前路由、、)就是组件路由的this.route
跳转路由并携带query参数 to的字符串写法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eryYzsk3-1647068009545)(D:/Typora/image-20220111231355329.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Iu14Ohn2-1647068009546)(D:/Typora/image-20220111231635073.png)]
如果使用params必须使用name 不能使用path 因为这个path已经找不到了。原路径预留的path有占位符:(路径参数)。
当一个路由被匹配时,它的 params 的值将在每个组件中以 this.$route.params 的形式暴露出来。
拿这个过去匹配不到
模板
一个配置项命一个名
原来的path改成name也可以正常使用 必须要写成对象然后配置name 写成字符串就是默认是路径了
以props的形式组件间传参数
params版
query版:
有点像数组那种 一层一层追加再一层一层退出 默认就是push模式 replace
有点像无痕浏览 是采用取代 历史记录只有一条
不使用router-link的路由导航,用this.$router使用路由器对象来进行路由的切换
// 字符串路径
router.push('/users/eduardo')// 带有路径的对象
router.push({ path: '/users/eduardo' })// 命名的路由,并加上参数,让路由建立 url params参数地址栏不显示参数
router.push({ name: 'user', params: { username: 'eduardo' } })// 带查询参数,结果是 /register?plan=private
router.push({ path: '/register', query: { plan: 'private' } })// 带 hash,结果是 /about#team
router.push({ path: '/about', hash: '#team' })
负数是后退 正数是前进 我感觉是读栈里面 前进就是往栈尾走 后退就是往后走(。 说一些废话
下面是后退两步(连点两下后退
1.路由传递参数(对象写法) path是否可以结合params参数一起使用?
不可以 会报错 params和name一起用
this.$router.push({ path: '/Search/', params: { keywords:this.keywords } })
Uncaught (in promise) NavigationDuplicated: Avoided redundant navigation to current location: “/Search/”.
2.如何指定params参数可传可不传
3.params传空串
我的url有点问题 明明已经跳转到login了 但是还是显示这个
ps:路由规则是这样的
{path: "/Login/:keywords",component:Login ,name:"Login",meta:{showFooter:"false"}
},
4.路由能不能使用props
可以,
1)布尔值
在接收的路由组件路由规则上加props
{path: "/Login/:keywords",component:Login ,name:"Login",meta:{showFooter:"false"},//传布尔值props:true//传对象props:{keywords:"1111111111"}//传函数props:(route)=>({params:route.params,a:1,b:2})}
},
然后照常使用就ok
<script>
export default {
name:"Login",
props:["keywords"]
}
</script>
解决 错误NavigationDuplicated: Avoided redundant navigation to current location
这个错误主要是已经在这个页面然后路由又要转到这个页面导致的
goSearch() {console.log("goSearch");let re = this.$router.push({ name: "Login", params: { keywords: this.keywords } }// ,// () => {// // console.log("yes");// },// () => {// // console.log("no");// });console.log(re);//Promise对象},
goSearch() {console.log("goSearch");let re = this.$router.push({ name: "Login", params: { keywords: this.keywords } },() => {console.log("yes");return 1},() => {console.log("no");});console.log(re);//undefined},
不知道为什么会这样 加了两个函数返回的变成undefined了…
重写push、replace
const originalPush = VueRouter.prototype.push
VueRouter.prototype.push = function push (location) {return originalPush.call(this, location).catch(err => err)
}
缓存路由组件 keep-alive
include里面填的组件名
home.vue
<router-link active-class="active" to="/home/next">next</router-link>
<keep-alive><router-view></router-view>//缓存的是跳转的那个next组件</keep-alive>
路由组件独有的生命周期钩子
next.vue
<script>
export default {name:'next',beforeDestroy() {console.log("next被销毁了")},activated() {console.log("home actttttt")},deactivated() {console.log("home deactttt")},
}
</script>
重定向
通过配置route
router/index.js
{// 重定向 访问/的时候,让它定位到path:'*',redirect:'/home'}
也可以写别的path 下面例子是从 /a 重定向到 /b
const router = new VueRouter({routes: [{ path: '/a', redirect: '/b' }]
})
甚至是一个方法,动态返回重定向目标:
const router = new VueRouter({routes: [{ path: '/a', redirect: to => {// 方法接收 目标路由 作为参数// return 重定向的 字符串路径/路径对象}}]
})
注意导航守卫并没有应用在跳转路由上,而仅仅应用在其目标上。在下面这个例子中,为 /a 路由添加一个 beforeEnter 守卫并不会有任何效果。(这个写法没有看过 下次遇到写写看 路由守卫 路由前置
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Rw6CvKZC-1647068009576)(D:/Typora/image-20220113021733886.png)]
meta元数据(就是所谓的路由元信息了) 配置对象里面的不能随便加属性的,自己在配置对象里面加的属性是读不到的 ,会被无视掉 要放属性就放到meta里面
我们称呼 routes 配置(就是router/index.js 暴露的那个全局路由)中的每个路由对象为 路由记录。路由记录可以是嵌套的,因此,当一个路由匹配成功后,它可能匹配多个路由记录。
例如,根据上面的路由配置,/posts/new 这个 URL 将会匹配父路由记录 (path: '/posts') 以及子路由记录 (path: 'new')。
一个路由匹配到的所有路由记录会暴露为 $route 对象(还有在导航守卫中的路由对象)的$route.**tched 数组。我们需要遍历这个数组来检查路由记录中的 meta 字段,但是 Vue Router 还为你提供了一个 $route.meta 方法,它是一个非递归合并所有 meta 字段的(从父字段到子字段)的方法。这意味着你可以简单地写
router.beforeEach((to, from) => {// 而不是去检查每条路由记录// to.**tched.some(record => record.meta.requiresAuth)if (to.meta.requiresAuth && !auth.isLoggedIn()) {// 此路由需要授权,请检查是否已登录// 如果没有,则重定向到登录页面return {path: '/login',// 保存我们所在的位置,以便以后再来query: { redirect: to.fullPath },}}
})
路由后置
只对某一个组件进行限制
通过路由规则,进入跟退出分别调用beforeRouterEnter,beforeRouterLeave。
进入组件跟离开组件与之前的前置/后置路由守卫完全不一样。前置、后置路由守卫是有一点点像钩子,自动启动,然后我觉得组件内路由守卫更像我本人,推一下动一下。。
点了button路由进入home组件才启动,离开home组件 切换才启动
又及 不通过路由规则 直接展示路由组件是不会触发beforeRouterEnter,beforeRouterLeave的
eg
直接放home组件没有触发 由于有初始化还是触发了前置、后置路由守卫(beforeEach、afterEach)
可以使用nignx/node的一个中间件完成匹配
文档下载
转载:感谢您阅览,转载请注明文章出处“来源从小爱孤峰知识网:一个分享知识和生活随笔记录的知识小站”。
链接:vue2学习笔记vue2记录http://www.gufeng7.com/niaolang/1822.html
联系:如果侵犯了你的权益请来信告知我们删除。邮箱:119882116@qq.com
上一篇: element UI 中table表格循环滚动方法
下一篇: Vue基础入门篇学习总结