前言
最近太忙了,博客好久没有更新了。今天忙里偷闲,简单总结一下最近vue项目重构的一些技术要点。
vue数据更新, 视图未更新
这个问题我们经常会遇到,一般是vue数据赋值的时候,vue数据变化了,但是视图没有更新。这个不算是项目重构的技术要点,也和大家分享一下vue2.0通常的解决方案吧!
解决方案如下:
1、通过vue.set方式赋值
Vue.set(数据源, key, newValue)
2、 通过Array.prototype.splice方法
数据源.splice(indexOfItem, 1, newValue)
3、修改数据的长度
数据源.splice(newLength)
4、变异方法
Vue.js 包装了被观察数组的变异方法,故它们能触发视图更新。被包装的方法有:
push()
pop()
shift()
unshift()
splice()
sort()
reverse()
prop 对象数组应用
在 JavaScript 中对象和数组是引用类型,指向同一个内存空间,如果 prop 是一个对象或数组,在子组件内部改变它会影响父组件的状态。利用这一点,我们在子组件中改变prop数组或者对象,父组件以及所有应用到prop中数据的地方都会变化。我之前写过一篇js深拷贝和浅拷贝的文章,感兴趣的去看下,其实,原理是一致的。
案例如下:
<input class="pinput max" type="text" v-model="itemData.data.did">
<script>
export default {
components: {
},
data() {
},
props: {
itemData: Object
},
methods: {
}
};
</script>
所有应用到itemData的地方都会变化!
上面这种改变prop,Vue 不会在控制台给出警告,假如我们完全改变或者赋值prop,控制台会发出警告!引用官方给出的解决方案如下:
1、定义一个局部变量,并用 prop 的值初始化它:
props: ['initialCounter'],
data: function () {
return { counter: this.initialCounter }
}
2、定义一个计算属性,处理 prop 的值并返回:
props: ['size'],
computed: {
normalizedSize: function () {
return this.size.trim().toLowerCase()
}
}
v-model 的一些坑
其实v-model和sync都是一些语法糖,我之前有文章介绍过,官网也能找到类似的案例!
v-model 数据有时候是undefined的时候,不会报错,所以,一定要注意,v-model不能是undefined,否则有些莫名的问题!
重构-动态组件的创建
有时候我们有很多类似的组件,只有一点点地方不一样,我们可以把这样的类似组件写到配置文件中,动态创建和引用组件
方法一:component 和is配合使用
通过使用保留的
var vm = new Vue({
el: '#example',
data: {
currentView: 'home'
},
components: {
home: { /* ... */ },
posts: { /* ... */ },
archive: { /* ... */ }
}
})
<component v-bind:is="currentView">
<!-- 组件在 vm.currentview 变化时改变! -->
</component>
方法二:通过render方法创建
<script>
export default {
data() {
return {
};
},
render: function(createElement) {
let _type = bi.chart.data.type;
let _attr = bi.chart.components[_type]["attr"];
return createElement(_attr, {
props: {
}
});
}
};
</script>
bi.chart.components[_type]["attr"]这个是在配置文件中动态配置的,type点击的时候会改变,会取不同type下面的attr属性!
公共属性抽离
我们在项目中,经常会用很多状态或者数据,我们可以把很多公共数据抽离出来,放到一个对象中,后面我们可以监听这个数据对象变化。进行数据保存或者获取。
c: {
handler: function (val, oldVal) { /* ... */ },
deep: true
},
// 该回调将会在侦听开始之后被立即调用
d: {
handler: function (val, oldVal) { /* ... */ },
immediate: true
},
可以利用上面深度监听。假如初始化的时候要立即执行,我们可以用立即执行监听!
动态加载依赖
import命令会被 JavaScript 引擎静态分析
// 报错
if (x === 2) {
import Haorooms from './Haorooms';
}
解决方案一:require加载
因为require是运行时加载模块,import命令无法取代require的动态加载功能。
在代码中动态加载依赖,例如下面echart主题,我们可以点击切换的时候,动态加载!
require("echarts/theme/"+ data.theme);
解决方法二:import()函数
例如:
const main = document.querySelector('main');
import(`./section-modules/${someVariable}.js`)
.then(module => {
module.loadPageInto(main);
})
.catch(err => {
main.textContent = err.message;
});
按需加载。
button.addEventListener('click', event => {
import('./dialogBox.js')
.then(dialogBox => {
dialogBox.open();
})
.catch(error => {
/* Error handling */
})
});
条件加载
if (condition) {
import('moduleA').then(...);
} else {
import('moduleB').then(...);
}
动态的模块路径
import(f())
.then(...);
上面代码中,根据函数f的返回结果,加载不同的模块。
$destroy()销毁组件,没有销毁slot
可以用v-if判断slot,如下:
<comp-b @close-a="showA = false">
<comp-a v-if="showA"/>
</comp-b>
另外可以用v-if指定组件渲染循序,例如,某个组件要在ajax请求返回数据之后再渲染,我们可以给组件一个状态,默认是false,当ajax请求返回数据之后,状态改成true。