vue 中经常定义很多data ,在用户进行一些操作后,需要将data中的某个对象定义为初始值,最常见的为表单数据
初始化指定对象form: {
title: '',
desc: '',
url: ''
}
大众都会选择以下方法进行初始化值
this.form = {
title: '',
desc: '',
url: ''
}
其实还可以这样
// Object.assign(this.form, this.$options.data().form)
this.form = this.$options.data().form
示例代码
setData
title:
desc:
url:
初始化方法1
初始化方法2
export default {
name: 't3',
data() {
return {
form: {
title: '',
desc: '',
url: ''
}
}
},
methods: {
setData(){
this.form = {
title: '零三的笔记',
desc: 'web03',
url: 'web03.cn'
}
},
initFn1(){
this.form = {
title: '',
desc: '',
url: ''
}
},
initFn2(){
//Object.assign(this.form, this.$options.data().form)
this.form = this.$options.data().form
}
}
}
div{
padding: 5px 20px;
}
对于初始化整个data,如果还是一个一个data属性进行赋值,那这难免太low了,可以直接使用Object.assign进行初始化整个data
关键代码
Object.assign(this.$data, this.$options.data())
示例
setData
title:
desc:
url:
msg: {{otherData.msg}}
初始化data
export default {
name: 't3',
data() {
return {
form: {
title: '',
desc: '',
url: ''
},
otherData: {
msg: ''
}
}
},
methods: {
setData(){
this.form = {
title: '零三的笔记',
desc: 'web03',
url: 'web03.cn'
}
this.otherData.msg = 'msg data'
},
initFn(){
Object.assign(this.$data, this.$options.data())
}
}
}
div{
padding: 5px 20px;
}
同样支持初始化form新增的属性
Objeact.assign初始化form的弊端个人发现Objeact.assign在原data数据进行增删新属性之后,会出现数据遗留现象,以下案例
setData
title:
desc:
url:
attr:{{form.attr}}
set attribute
初始化data
export default {
name: 't3',
data() {
return {
form: {
title: '',
desc: '',
url: ''
},
otherData: {
msg: ''
}
}
},
methods: {
setData(){
this.form = {
title: '零三的笔记',
desc: 'web03',
url: 'web03.cn'
}
this.otherData.msg = "msg data"
},
setAttribute(){
//this.form.attr = "我是动态的属性"
// 或者
this.$set(this.form, 'attr', "我是动态的属性")
},
initFn(){
Object.assign(this.form, this.$options.data().form)
}
}
}
div{
padding: 5px 20px;
}
以上demo出现了attr遗留的问题,而我们并不希望让他存在
进行优化
- Object.assign(this.form, this.$options.data().form)
+ this.form = this.$options.data().form
Object.assign(this. d a t a , t h i s . data, this. data,this.options.data())支持初始化form新增的属性,且不支持this. d a t a = t h i s . data=this. data=this.options.data()
Objeact.assign初始化整个data弊端发现在子组件使用Object.assign(this. d a t a , t h i s . data, this. data,this.options.data()),会将props的值清空,查看以下案例 // t3.vue
import child from './child'
export default {
name: 't3',
components: {
child
},
data(){
return {
parentDataObj: {
name: '零三'
},
parentDataStr: '我是零三'
}
}
}
// child.vue
setData
title:
desc:
url:
myDataStr: {{myDataStr}}
myDataObj.name: {{myDataObj.name}}
初始化data
export default {
name: 'child',
props: ['parentDataStr', 'parentDataObj'],
data() {
return {
form: {
title: '',
desc: '',
url: ''
},
myDataStr: this.parentDataStr,
myDataObj: this.parentDataObj
}
},
methods: {
setData() {
this.form = {
title: '零三的笔记',
desc: 'web03',
url: 'web03.cn'
}
},
initFn() {
Object.assign(this.$data, this.$options.data())
}
}
}
div {
padding: 5px 20px;
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oaNlHfpf-1613983980768)(https://yuan30-1304488464.cos.ap-guangzhou.myqcloud.com/blog/images/63eb4c91d4aa4323b664348a194ec577.gif)]
解决
- Object.assign(this.$data, this.$options.data())
+ Object.assign(this.$data, this.$options.data.call(this))
分析问题原因
分析Vue实例的初始化逻辑源码, new Vue的时候传了一个对象,把该对象记为options,Vue将options中自定义的属性和Vue构造函数中定义的属性合并为vm. o p t i o n s , v m . options,vm. options,vm.options.data()中的this指向vm. o p t i o n s , 而 m y D a t a S t r 和 B 并 没 有 直 接 挂 在 v m . options,而myDataStr和B并没有直接挂在vm. options,而myDataStr和B并没有直接挂在vm.options下,所以this.myDataStr和this.myDataObj为undefined。
initMixin (Vue: Class) {
const vm: Component = this
// ...
vm.$options = mergeOptions(
resolveConstructorOptions(vm.constructor),
options || {},
vm
)
// ...
}
将vm.$options.data映射到vm._data,使得可以通过vm._data访问数据,在映射过程中,通过call将data()的this指向当前的实例vm,并将data()的执行结果返回,因为prop和methods的初始化在data之前,所以这时vm上已有_props和_methods,可以拿到this.myDataObj和this.myDataStr。
initState (vm: Component) {
// ...
const opts = vm.$options
if (opts.props) initProps(vm, opts.props)
if (opts.methods) initMethods(vm, opts.methods)
if (opts.data) {
initData(vm) // 里面通过getData(data, vm)改变this
}
// ...
}
getData (data: Function, vm: Component): any {
// ...
try {
return data.call(vm, vm) // this替换为vm
}
// ...
}
上面把属性映射到了vm._data里,可以通过vm._data.A访问数据,Vue再通过一个代理方法使得vm.A可以直接访问A
proxy(vm, `_data`, key);
proxy (target: Object, sourceKey: string, key: string) {
sharedPropertyDefinition.proxyget = function proxyGetter () {
return this[sourceKey][key]
}
sharedPropertyDefinition.set = function proxySetter (val) {
this[sourceKey][key] = val
}
Object.defineProperty(target, key, sharedPropertyDefinition)
}
总结
-
初始化没有动态属性的对象,可采用 Object.assign(this.form, this.$options.data().form)
-
初始化有动态属性的对象一定要使用this.form = this.$options.data().form 【推荐】
-
初始化data,data()中没有用this来访问props或methods,可不绑定this,使用Object.assign(this. d a t a , t h i s . data, this. data,this.options.data())
-
初始化data,data()中若用了this来访问props或methods,一定要绑定this,使用Object.assign(this. d a t a , t h i s . data, this. data,this.options.data.call(this)) 【推荐】