Object.defineProperty
有缺陷,就是无法监控到对象属性临时添加的属性,必须使用VUE.set($set)
属性去添加,这个方法原理就是重新设定一个Object.defineProperty
监听新属性,所以VUE3.0改为使用proxy去监听,没有这种缺陷数组在添加过程中也是会无法监听的,所以在VUE中写了
push,pop,shift ...
这类直接修改数组方法(因为不修改原数组的方法是会返回新数组的,可以通过监听新数组去触发)的变异方法,通过改写这类方法进行数组值的监听,例:
let push = Array.prototype.push
Array.prototype.push = function(...args) {
// 中间做些类似中间件的代码,获取新增的数据,进行监听
....
push.call(this, ...args)
}
3.v-once只渲染一次
4.v-pre忽略这个元素和它子元素内容的编译
5.v-model修饰符
v-model.lazy,取代change方法,等输入完之后再进行输出
v-model.number,只能输入数字
v-model.trim,收尾空格去除
6.鼠标修饰符
.stop,阻止冒泡
.self,点击事件绑定元素与当前元素一致时才会触发
//stop和self分别什么情况下使用,当子元素不想产生冒泡触发父级事件时使用stop,
//而self则时在很多嵌套元素情况下,只想触发当前元素的时候使用
.prevent,阻止默认事件
.once,事件只绑定一次
.passive,告诉浏览器没有阻止默认事件
//每次触发事件,浏览器都要等线程执行到事件监听器对应的代码时,才能查询代码是否有阻止默认事件这个行为,而这个查询过程会导致在使用scroll,手势,移动等事件出现卡顿,
//添加上这个修饰符后就是直接告诉浏览器没有做这个行为,就不用去查询了
//原生写法:el.addEventer('click', function() {}, {once:true,passive:true})
7.键盘修饰符
.exact,精确键盘事件
//@keyDown.ctrl.exact="fn" 表示只能在单独按ctrl键的时候才能触发
8.watch
new Vue({
el: '#app',
data: {
a: {
b: {
c: 1
}
}
},
watch: {
'a.b.c': {
handler: function(new, old) { console.log() }, //对于多层数据的监听,可以使用字符串+点语法
immediate: true, //当第一次绑定值时就直接监听
deep: true //深层监听,最多监听5层
}
}
//
})
9.v-model在除input元素外的使用
const child= {
model: {
// 指定v-model绑定的prop属性,需要和下方props的属性名对应
prop: 'checked',
// 执行内部触发的哪个事件会修改指定的prop
event: 'check'
},
props: ['checked'],
data() {
return {
status: this.checked
}
},
template: `
`,
methods: {
changeStatus() {
this.status = !this.status;
this.$emit('check', this.status);
}
}
};
let vm = new Vue({
el: '#app',
data: {
val: true
},
components: {
'kkb-radio': kkbRadio,
'kkb-plane': kkbPlane
},
methods: {
change(status) {
this.val = status;
}
}
});
10.作用域插槽
11.生命周期
//捕获子孙组件错误
new Vue({
.....
errorCaptured(err, vm, info) {
//err: 错误信息
//vm: 错误的组件对象
//info: 错误类型
}
})
12.动态加载组件,keep-alive组件
13.自定义组件
new Vue({
el: '#app',
directives: {
'指令名称' : {指令配置}
}
})
### 指令生命周期
- bind : 只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置
- inserted : 被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)
- update : 所在组件更新的时候调用
- componentUpdated : 所在组件更新完成后调用
- unbind : 只调用一次,指令与元素解绑时调用
### 例子
14.路由守卫
### 组件内路由
beforeRouteEnter(to, from, next) { //路由组件进入前
//这个阶段不能访问this,组件未创建
//实在需要访问的话
next(vm => { console.log(vm) })
}
beforeRouteUpdate(to, form, next) {} //当前路由变化,但该组件属于复用时调用
beforeRouteLeave(to, form, next) {} //离开对应路由时调用
### 路由独享守卫
beforeEnter(to, from, next) {} //直接使用在路由中, 如:
const router = new VueRouter({
routes: [
{
path: '/foo',
conponent: Foo,
beforeEnter: (to, from, next) => {}
}
]
})
### 全局路由守卫
router.beforeEach((to, from, next) => {})
router.beforeResolve((to, from, next) => {})
router.beforeEach((to, from) => {}) //导航被确认后调用,就是在整个路由完成最后调用的生命周期
15.route组件的props
//路由中可以定义props属性,值为`true/false`。
//router.js
const router = new VueRouter({
...
routers: [
{
path: '/home/:itemId',
name: 'home',
compoment: Home,
props: true
}
]
})
`使用了props属性后,那么在组件中就不需要使用this.$route.params.itemId进行获取,可以直接在组件的props:['itemId']中获取到`
// child.vue
export default {
...
props:['itemId'],
created() { console.log(this.itemId) }
}
`PS: vue在处理props传值时,如果在组件中的props没有定义所传的属性名,将会保存在this.$attrs中,如:
//parent.vue
//child.vue
export default {
props: ['a'],
data() {
return {}
},
created() { console.log(this.$attrs) } //{b:2, c:3}
}
`
`路由props有三种处理模式`
//1.默认处理
//直接将route.params中的数据和组件中props的数据进行合并
//2.对象模式
//有选择的返回props
{
path: '/home/:itemId',
compoment: home,
props: {a:1, b:2}
}
//3.回调函数模式
{
path: '/home/:itemId',
compoment: home,
props: r => ({itemId: Number(r.params.itemId)})
}
16.切换路由时,页面滚动条保持/归顶
//必须使用浏览器前进回退功能(使用js触发前进回退也行)
const router = new VueRouter({
scrollBehavior(to, from, savedPosition) {
if(savedPosition) {
return savedPosition //保存上一页的x、y坐标
} else {
return {x: 0, y: 0}
}
},
routes: [...]
})