记录Vue2常见问题
props
$emit
provide
/inject
或者 element-ui
的广播broadcast
/dispatch
EventEmmitter
机制, 在复杂一些可以用tapable
jsVue.$prototype.$bus = new Vue();
this.$bus.on() // 监听
this.$bus.emit() // 触发
$refs
、$parent
、$children
、$attrs
、$listeners
也算 不推荐,存在耦合Vuex
当 <style>
标签有 scoped
属性时,它的 CSS
只作用于当前组件中的元素。
其原理是通过使用 PostCSS
来实现以下转换:
html<template>
<div class="red" data-v-f3f3eg9>hi</div>
</template>
<style>
.red[data-v-f3f3eg9] { color: red; }
</style>
>>>
/deep/
or ::v-deep
DOM
和 diff
算法使我们的应用拥有最佳的性能表现。追求高效的过程还在继续,vue3
中引入Proxy
对数据响应式改进以及编译器中对于静态内容编译的改进都会让vue更加高效。computed
参数可以是函数或对象,如果是函数转换为对象的存值器,返回一个值watch
参数可以是函数或对象,函数会转换为对象{immediate: false, deep: false}
beforeEach (to,from,next)
常用于登录权限相关验证
next
:路由控制参数next()
:如果一切正常,则调用这个方法进入下一个钩子next(false)
:取消导航(即路由不发生改变)next('/login')
:当前导航被中断,然后进行一个新的导航next(error)
:如果一个Error
实例,则导航会被终止且该错误会被传递给router.onError()
afterEach(to,from)
路由改变后的钩子beforeEnter(to, from, next)
this
,如果想使用this
则在next
方法回调里使用beforeRouteUpdate (to,from,next)
beforeRouteLeave (to,from,next)
strict: true
直接修改state
会控制台报红plugin: [myPlugin]
tsexport default store => {
// 初始化时从localStorage获取数据
if(localStorage) {
const user = JSON.parse(localStorage.getItem('user'))
if (user) {
store.commit('user/login')
store.commit('user/setUsername', user.username)
}
}
// 用户状态发生变化时缓存之
store.subscribe((mutation, state) => {
if (mutation.type.startsWith('user/')) {
localStorage.setItem('user', JSON.stringify(state.user))
} else if (mutation.type === 'user/logout') {
localStorage.removeItem('user')
}
})
}
key
的作用主要是为了高效的更新VDOM
,其原理是vue
在patch
过程中通过key
可以精准判断两 个节点是否是同一个,从而避免频繁更新不同元素,使得整个patch
过程更加高效,减少DOM
操作量,提高性能。key
可能引发一些隐蔽的bug
如列表更新或相同标签名元素的过渡切换new Vue(el:'#app')
只能指定一个入口template
下的元素div
。其实就是"树"状数据结构中的"根"。diff
算法要求的jsexport default {
data() => ({
list: []
}),
async created() {
const list = axios.get('/api/list');
this.list = Object.freeze(list);
}
}
如果是大数据长列表,可采用虚拟滚动,只渲染少部分区域的内容
参考vue-virtual-scroller、vue-virtual-scroll-list
html<recycle-scroller
class="items"
:items="items"
:item-size="24"
>
<template v-slot="{ item }">
<FetchItemView
:item="item"
@vote="voteItem(item)"
/>
</template>
</recycle-scroller>
functional
html<template functional>
<div class="cell">
<section v-else class="off"></section>
</div>
</template>
<script>
export default {
// 无状态组件不能有props和data
// props: ['value']
}
</script>
html<template>
<div>
<ChildComp/>
</div>
</template>
<script>
export default {
components: {
ChildComp: {
methods: {
heavy () { /* 耗时任务 */ }
},
render (h) {
return h('div', this.heavy())
}
}
}
}
</script>
key
v-show
与v-if
keep-alive
合理使用computed
替代method
或 watch
is
动态组件递归与不同组件使用无异,唯一要注意的是递归首要考虑终止条件,那递归组件必须与v-if
配合使用
父组件中定义 | 子组件中使用 | |
---|---|---|
默认插槽 | <template v-slot> 可简写 <my-comp v-slot> | <slot> |
具名插槽 | v-slot:header | <slot name='footer'/> |
作用域插槽 | v-slot:default="slotProps" | <slot v-bind:user='user'>{{user.name}}</slot> |
<slot>后备内容</slot>
我们认为Vue和WebComponents是互补的技术。可以把自定义元素继承到Vue应用中,也可以使用Vue来构建和分发自定义元素。
自定义元素和Vue组件的相同点
但是Vue组件显然更强大一下
jscomponents: {
'async-com': () => ({
component: new Promise(resolve => {
setTimeout(() => {
resolve(import('./components/AsyncComp.vue'))
}, 2000)
}),
loading: LoadingComp,
error: ErrorComponent,
// error: {render: () => h('div', 'error')}
timeout: 3000,
delay: 200,
timeout: 3000
})
}
jsVue.config.errorHandler = function (err, vm, info) {
// 可以捕获的错误
// 1. 组件生命周期钩子里的错误 2.2.0+
// 2. 捕获 Vue 自定义事件处理函数内部的错误 2.4.0+
// 3. 会捕获 v-on DOM 监听器内部抛出的错误 和 Promise 错误 2.6.0+
}
errorHandler(err: Error, vm: Component, info: string) => ?boolean
在捕获一个来自后代组件的错误时被调用。 可以通过返回 false
阻止事件的传播
LRU:Least Recently Used,最近最少使用算法
beforeCreate
之前做的事情
initLifecycle()
创建$parent
$children
initEvents()
事件监听initRender()
渲染模版beforeCreate
之后做的事情
initInjections()
initState
initProvide
keep-alive
钩子
activated
deactivated
根据尤大的PPT总结,Vue3.0改进主要在以下几点:
TypeScript
+ 模块化Composition API
关注点分离 useXXX
优于 mixins
vue2 也提供了一些方法来避免OptionsAPI天生的逻辑碎片化 如下示例
jsmounted: function () {
var picker = new Pikaday({
field: this.$refs.input,
format: 'YYYY-MM-DD'
})
this.$once('hook:beforeDestroy', function () {
picker.destroy()
})
}
本文作者:郭敬文
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!