Vue2.x常见问题

1.如何将获取data中某一个数据的初始状态?

export default {
	data() {
		return {
			price: 100
		}
	},
	methods: {
		changePrice() {
			this.price = 101
		},
		getInitPrice() {
			// 可以通过this.$options.data().xxx来获取初始值
			console.log('初始price', this.$options.data().price)
		}
	},
	mounted() {
		this.getInitPrice()
	}
}

2.为什么不建议v-forv-if同时存在

<div v-for="item in list" :key="item.id" v-if="item.name === '诸葛亮'">
	{{item.name}}
</div>
export default {
	data() {
		return {
			list: [
					{ id: 1, name: '刘备' },
                    { id: 2, name: '张飞' },
                    { id: 3, name: '诸葛亮' }
                ]
		}
	}
}

v-for的优先级比v-if高,会优先执行v-for,即会先把所有个元素都遍历出来,然后再一个个判断是否符合条件,这样的坏处就是,渲染了无用点,增加无用的dom操作,建议使用computed来解决这个问题。

<div v-for="item in resultList" :key="item.id">
	{{item.name}}
</div>
export default {
	computed: {
		resultList() {
			return this.list.filter(v => v.name === '诸葛亮')
		}
	},
	data() {
		return {
			list: [
					{ id: 1, name: '刘备' },
                    { id: 2, name: '张飞' },
                    { id: 3, name: '诸葛亮' }
                ]
		}
	}
}

3.相同的路由组件如何重新渲染?

多个路由解析为同一个Vue组件,Vue出于性能原因,默认情况下共享组件将不会重新渲染,如果你尝试在使用相同组件的路由之间进行切换,则不会发生任何变化。

const routes = [
  {
    path: '/a',
    component: MyComponent
  },
  {
    path: '/b',
    component: MyComponent
  },
];

如果依然想重新渲染,怎么办呢?可以使用key

<template>
    <router-view :key="$route.path"></router-view>
</template>

4.使用动态指令和参数

<my-component @[someEvent]="handleSomeEvent()" [someProp]="prop"></my-component>
export default {
	computed: {
		someEvent() {
			return this.condition ? 'click' : 'dblclick'
		},
		someProp() {
			return this.condition ? 'propA' : 'propB'
		}
	},
	data() {
		return {
			condition: false
		}
	}
}

5.hook的使用

  1. 优化定时器的使用方式

    这是我们常用的使用定时器的方式

export default {
	data() {
		return {
			timer: null  
		}
	},
	mounted(){
		this.timer = setInterval(() => {
	      	//具体执行内容
			console.log('优化定时器的使用方式');
		}, 2000);
	},
	beforeDestory(){
		clearInterval(this.timer);
		this.timer = null;
	}
}

上面做法不好的地方在于:得全局多定义一个timer变量,可以使用hook这么做:

export default {
	methods: {
		fn() {
      		let timer = setInterval(()	=>	{
		      	//具体执行内容
				console.log('优化定时器的使用方式');
			}, 2000);
	      	this.$once('hook:beforeDestroy', () => {
	        	clearInterval(timer);
	        	timer = null;
	      	})
    	}
	},
	mounted() {
		this.fn()
	}
}
  1. 子组件在特定生命周期触发父组件函数(向父组件传值)

如子组件需要在mounted时触发父组件的某一个函数,平时都会这么写:

<!-- 父组件 -->
<my-child @someEvent="handleEvent()" />
// 父组件
export default {
	methods: {
		handleEvent(e) {
			// 逻辑代码
		}
	},
}
// 子组件
export default {
	mounted() {
		this.$emit('someEvent', '子组件数据')
	}
}

使用hook的话可以更方便:

<!-- 父组件 -->
<my-child @hook:mounted="handleEvent()" />
// 父组件
export default {
	methods: {
		handleEvent(e) {
			// 逻辑代码
		}
	},
}

6.computed传参

返回一个带参数的匿名函数,该匿名函数返回计算最终的结果值

<span>{{totalMoney(3)}}</span>
export default {
	computed: {
		totalMoney() {
 			return n => n * this.price
		}
	},
	data() {
		return {
			price: 100
		}
	},
}

7. watch监听对象newValoldVal相同

<div>
	<button @click="handleClick('a')">改变a</button>
	<button @click="handleClick('b')">改变b</button>
	<button @click="handleClick('c')">改变c</button>
	<button @click="handleClick('d')">改变d</button>
</div>
export default {
	watch: {
		params: {
			handler(newVal, oldVal) {
				// 这里日志打印的newVal和oldVal相同。因为它们索引同一个对象/数组。Vue 不会保留修改之前值的副本。
				console.log('newVal', newVal);
				console.log('oldVal', oldVal);
			}
		},
	},
	data() {
		return {
			params: {
				a: 1,
				b: 2,
				c: 3,
				d: 4,
			}
		}
	},
	methods: {
		 handleClick(type) {
            for (const key in this.params) {
                if (key === type) {
                	// 修改属性值
                    this.params[type] = 100
                }
            }
        },
	},
}

深度复制对象,使得引用类型的地址不是同一个地址。

export default {
	watch: {
		params: {
			handler(newVal, oldVal) {
				console.log('newVal', newVal);
				console.log('oldVal', this.newParams);
			}
		},
	},
	data() {
		return {
			params: {
				a: 1,
				b: 2,
				c: 3,
				d: 4,
			},
			newParams: null,
		}
	},
	methods: {
		 handleClick(type) {
		 	// newParams 为 params 的深克隆副本,用于记录修改之前的值
		 	this.newParams = JSON.parse(JSON.stringify(this.params))
            for (const key in this.params) {
                if (key === type) {
                	// 修改属性值
                    this.params[type] = 100
                }
            }
        },
	},
}

8. 用到scrollresize等事件监听,利用防抖函数做性能优化处理时,解除事件绑定失效。

	/* 防抖函数 */
    const throttle = (fn, time) => {
        let timer = null
        return (...args) => {
            if (!timer) {
                timer = setTimeout(() => {
                    timer = null
                    fn.apply(this, args)
                }, time)
            }
        }
    }
mounted() {
	window.addEventListener('scroll', throttle(this.doSomething, 300))
}
destroyed() {
	window.removeEventListener('scroll', throttle(this.doSomething, 300))
}

此时,removeEventListener解除事件绑定并不会生效,因为addEventListenerremoveEventListener第二个参数的函数必须是同一函数才行,也就是这两个函数他们的地址指针指向同一个地址。由于防抖函数返回的是一个匿名函数,所以此时他们俩个是不同的函数,导致removeEventListener不起作用。
解决方法是用一个变量接收throttle函数的返回结果。

methods: {
	fn: throttle(this.doSomething, 300)
}
mounted() {
	window.addEventListener('scroll', this.fn)
}
destroyed() {
	window.removeEventListener('scroll',this.fn)
}

当然你不想挂一个属性在this上,也可以直接这样写(比较推荐这种写法)

mounted() {
    const fn = throttle(this.doSomething, 300)
    this.$refs['xxx'].addEventListener('scroll', fn)
    this.$on('hook:beforeDestroy', () => {
        this.$refs['xxx'].removeEventListener('scroll', fn)
    })
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值