1、 状态共享
随着组件的细化,就会遇到多组件状态共享的情况,Vuex当然可以解决这类问题,不过就像Vuex官方文档所说的,如果应用不够大,为避免代码繁琐冗余,最好不要使用它,今天我们介绍的是vue.js 2.6新增加的Observable API ,通过使用这个api我们可以应对一些简单的跨组件数据状态共享的情况。
如下这个例子,我们将在组件外创建一个store,然后在App.vue组件里面使用store.js提供的store和mutation方法,同理其它组件也可以这样使用,从而实现多个组件共享数据状态。
首先创建一个store.js,包含一个store和一个mutations,分别用来指向数据和处理方法。
import Vue from "vue";
export const store = Vue.observable({ count: 0 });
export const mutations = {
setCount(count) {
store.count = count;
}
};
然后在组件内里面引入这个store.js,在组件里面使用引入的数据和方法
<template>
<div id="app">
<img width="25%" src="./assets/logo.png">
<p>count:{{count}}</p>
<button @click="setCount(count+1)">+1</button>
<button @click="setCount(count-1)">-1</button>
</div>
</template>
<script>
import { store, mutations } from "./store";
export default {
name: "App",
computed: {
count() {
return store.count;
}
},
methods: {
setCount: mutations.setCount
}
};
</script>
2、长列表性能优化
我们应该都知道vue会通过object.defineProperty对数据进行劫持,来实现视图响应数据的变化,然而有些时候我们的组件就是纯粹的数据展示,不会有任何改变,我们就不需要vue来劫持我们的数据,在大量数据展示的情况下,这能够很明显的减少组件初始化的时间,那如何禁止vue劫持我们的数据呢?可以通过object.freeze方法来冻结一个对象,一旦被冻结的对象就再也不能被修改了。
export default {
data: () => ({
users: {}
}),
async created() {
const users = await axios.get("/api/users");
this.users = Object.freeze(users);
}
};
3、监听组件的生命周期
比如有父组件Parent和子组件Child,如果父组件监听到子组件挂载mounted就做一些逻辑处理,常规的写法可能如下:
// Parent.vue
<Child @mounted="doSomething"/>
// Child.vue
mounted() {
this.$emit("mounted");
}
这里提供一种特别简单的方式,子组件不需要任何处理,只需要在父组件引用的时候通过@hook来监听即可,代码重写如下:
<Child @hook:mounted="doSomething"/>
当然这里不仅仅是可以监听mounted,其它的生命周期事件,例如:created,updated等都可以
4、优雅的处理vue项目异常
- Vue.config.errorHandler
Vue.config.errorHandler = function (err, vm, info) {
// 指定组件的渲染和观察期间未捕获错误的处理函数。这个处理函数被调用时,可获取错误信息和 Vue 实例。
// handle error
// `info` 是 Vue 特定的错误信息,比如错误所在的生命周期钩子
// 只在 2.2.0+ 可用
}
全局处理异常的完整代码:
errorPlugin.js
/**
* 全局异常处理
* @param {
* } error
* @param {*} vm
*/
const errorHandler = (error, vm, info) => {
console.error('抛出全局异常')
console.error(vm)
console.error(error)
console.error(info)
}
let GlobalError = {
install: (Vue, options) => {
/**
* 全局异常处理
* @param {
* } error
* @param {*} vm
*/
Vue.config.errorHandler = errorHandler
Vue.mixin({
beforeCreate() {
const methods = this.$options.methods || {}
Object.keys(methods).forEach(key => {
let fn = methods[key]
this.$options.methods[key] = function (...args) {
let ret = fn.apply(this, args)
if (ret && typeof ret.then === 'function' && typeof ret.catch === "function") {
return ret.catch(errorHandler)
} else { // 默认错误处理
return ret
}
}
})
}
})
Vue.prototype.$throw = errorHandler
}
}
export default GlobalError
使用
// 在入口文件中引入
import ErrorPlugin from './errorPlugin'
import Vue from 'vue'
Vue.use(ErrorPlugin)
5、移动端调试工具
1)vConsole
使用方法:
- a)多页面应用:
<script type="text/javascript” src="https://res.wx.qq.com/mmbizwap/zh_CN/htmledition/js/vconsole/3.0.0/vconsole.min.js"></script>
<script>
//init vConsole
new VConsole();
</script>
//<script>
//var vconsole = new VConsole({
// defaultPlugins: ['system', 'network', 'element', 'storage'], // 可以在此设定要默认加载的面板
//});
//</script>
- b)单页应用
case1:
utils.js
// 加载控制台
export const loadScript = (url, callback) => {
const script = document.createElement('script')
script.onload = () => callback()
script.src = url
document.body.appendChild(script)
}
main.js
import { loadScript } from '@/assets/js/utils'
loadScript(
'https://res.wx.qq.com/mmbizwap/zh_CN/htmledition/js/vconsole/3.0.0/vconsole.min.js',
() => {
// eslint-disable-next-line
new VConsole()
})
case2:
npm install vconsole
main.js
import VConsole from 'vconsole'
new VConsole();
2)eruda
- a)多页面应用:
<script type="text/javascript" src="https://cdn.bootcss.com/eruda/1.2.6/eruda.min.js"></script>
<script>
//直接使用不带任何参数的初始化方法init()会加载Eruda提供的全部面板,如果只需要部
//分面板需要在init()中带上配置参数。
eruda.init();
//eruda.init({
// tool: ['console', 'elements']
//});
</script>
- b)单页应用
npm install --save-dev eruda
eruda.js
;(function () {
if (!/mdebug=true/.test(window.location.href)) return;
var script = document.createElement('script')
script.src = "https://cdn.bootcss.com/eruda/1.2.6/eruda.min.js"
script.async = true
document.getElementsByTagName('head')[0].appendChild(script)
script.onload = function () {
eruda.init()
}
})()
main.js
import from './eruda.js'
在需要调试的页面地址栏加上mdebug=true,即可开启