Vue的data疑问,这样数据写在return中和不写在return中有什么区别

发布网友 发布时间:2022-04-21 02:52

我来回答

1个回答

热心网友 时间:2023-11-04 17:34

一段app.vue
<template>
<div class="tree-menu">
<ul v-for="item in theModel">
<my-tree :model="item"></my-tree>
</ul>
<div @click="change">
change the model </div>
</div></template><script>import myTree from './components/treeMenu.vue'import axios from 'axios'export default {
name: 'app',
components: {
myTree
},
data() { return {
theModel:[]
}
},
methods:{
change(){ this.theModel[0].menuName = '12312312'
console.log(this.theModel)
},
init() { var Json = [] for(var i = 0; i<10 ;i++){ var children1 = [] for(var j = 0;j<10;j++){ var row1 = []
row1.menuName = '哈哈'
children1.push(row1)
} var row2 = [];
row2.menuName = '呵呵'
row2.children = children1
Json.push(row2)
} this.theModel = Json
console.log(this.theModel)
}
},
mounted() { this.init();
}
}</script>1234567101112131415161718192021222324252627282930313233343536373839404142434445474849505152

第二段 treeMenu.vue
<template>
<li>
<span @click="toggle">
<i v-if="isFolder" class="icon" :class="[open ? 'folder-open': 'folder']"></i>
<i v-if="!isFolder" class="icon file-text"></i>
{{ model.menuName }}
</span>
<ul v-show="open" v-if="isFolder">
<tree-menu v-for="item in model.children" :key="item.id" :model="item"></tree-menu>
</ul>
</li></template><script>export default {
name: 'treeMenu',
props: ['model'],
data() { return {
open: false
}
},
computed: {
isFolder() { return this.model.children && this.model.children.length
}
},
methods: {
toggle: function() {
if (this.isFolder) { this.open = !this.open
}
}
}
}12345671011121314151617181920212223242526272829303132333435

代码省略掉了css部分,初始化数据也是随便写的。代码很简单,app.vue调用treeMenu组件,然后treeMenu组件进行递归,从而形成一个动态树级菜单,效果如下。

我的项目里需要我触发一个事件的时候对theModel里的某个属性值做修改,这里我写了一个change方法,用@click绑定在了change the model上,希望点击的时候把第一行的‘呵呵’给改掉。可是在我点击后,console.log中,theModel打印出来的值中第一行的‘呵呵’已经改变,可在列表中并没有重新渲染,既然vue实现的时数据双向绑定,那么在model层发生了变化之后为什么就没有在view层更新呢?
经过几天的探索,终于找到了原因所在:
项目里的数据是从API拿的,但是格式和我需要的不一样,于是我用以下方法重新拼接除了我需要的格式
var json = [];var row1 = {};

row1.id= "1";

row1.name = "jyy";

或者var row2 = {id:'2',name:'abc'}

json.push(row1);

json.push(row2);123456710111213

结果好死不死,我粗心的把row1定义为数组了,即row1 = [];
于是我的Json对象被定义为了‘关联数组’
这有什么区别?
数组和对象的一个区别是,数组中的数据没有“名称”(name),对象中的数据有“名称”(name)。但很多编程语言中,都有一种叫做“关联数组”(associativearray)的东西。这种数组中的数据是有名称的。比如在javascript中,可以这样定义一个对象:
var a={“城市”:”北京”,”面积”:16800,有趣,”人口”:1600};
但是,也可以定义成一个关联数组:
var a = new Array();
a[“城市”]=”北京”;
a[“面积”]=16800;
a[“人口”]=1600;
这样一来好像数组和集合就没有区别了,在Javascript语言中,关联数组就是对象,对象就是关联数组,唯一的区别在于,第二种方式创建的关联数组是有length属性的。
但是在Vue中,这种关联数组与对象集合的区别就有些明显了。

Vue在我们的data对象上都会定义一个ob属性指向新创建的Observer对象,以此对数据设置的监控器,一般都是不可枚举的。但由于JavaScript*(底层原理不明),Vue无法对关联数组进行Observer对象创建,因此不能检测到数组对象的变化。
观察控制台打印的数据,也可发现关联数组和对象在Vue中的区别:

上半部分为对象,下半部分为关联数组
那么回到正题,我在项目中遇到的问题该怎么解决?
第一种方案:将自己拼接的Json改为对象集合的格式。
但是,当你命不好不小心碰到了这种关联数组结构的数据,又不好拼接的时候怎么办,这里提供第二种方案:
使用 Vue.set(array, indexOfArray,value)
三个值分别是,要修改的数组,数组的下表,和新的值
当然也可以用 `this.$set(array, indexOfArray,value)
你以为这就完了?由于我的代码是递归组件,当我把Data绑定到theModel后,用 v-for=‘item in theModel’遍历,再把item通过v-bind绑定到子组件,但是由于item我没有在组件中使用过,即使Vue检测到theModel数组的变化,也不能检测到item中数组的变化,所以这里强制你需要在代码中加入使用item,类似<my-tree :model="item">{{item}}</my-tree>,
或者用<div v-if = 'false'>{{item}}<div>
这是我误打误撞发现的,当然,这很蠢。
所以你知道用vue.set的方法修改数组可以让vue检测到就行,不要使用第二种方法。

声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com