在vue里,props是个好东西。使用它,可以从父组件中,继承到数据。
但有时候,props,本身也不是那么好使。
正常情况下,使用props拿到的属性,直接就可以在模板当中使用。
非正常情况下,因为一些特殊需求,我们需要将props的属性,先存入data,然后再到模板当中使用。
举个例子,为模板中某个dom设置背景图。这时候,可以直接在该dom中用:
:style="{'background: 'url(' + props接收到的属性 + ')'}"
但本着js与模板分离的原则,这里拼接的字符串,还是放到js当中为妙。
这时候,props本身的局限性,就体现出来了。如果直接使用this.dataXXX = this.propsXXX,这时候,当页面首次加载的时候,是拿不到这个this.propsXXX的,只有当页面重新渲染时,才能拿到这个this.propsXXX。
那么如何解决这个问题呢? 我一开始使用了watch。 watch是个好东西,其作用是当数据发生改变时,取到改变之后的值和改变前的。
大概用法:
watch: { propsXXX (newContent, oldContent) { //注意,函数名必须与props所接收到的变量名一样。 //这时候,watch就会侦听这个变量的数据变化了,其中newContent存的是新数据,而old存的是老数据 //我们第一次加载,显然是没有新数据的,因此props的数据,就会存到newContent之中 //因此,只需要this.dataXXX.backgroundImage = 'url(' + newContent + ')',就能拿到实时数据了 } }
为了便于阅读,写一下data里的内容
data () { return { dataXXX: { backgroundImage: '' } } }
第一次加载,便能拿到最新数据,并存入到dataXXX当中,然后到dom上使用,比如<div :style="dataXXX"></div>这样。
不过,watch是一种对性能消耗相当严重的方法。 正常情况下,可以使用computed计算属性,将watch给替换掉。 这个computed,也是一个非常强大的东西。
computed: { var1 () { return 'url(' + this.propsXXX + ')' } }
这样也能第一次加载,就拿到props的属性,只是不需要再存到data当中了。
<div :style="{'background': var1}"></div>
看到这里,也许有的人会疑惑,既然不存到data中,那直接使用propsXXX不就可以了,何必再用computed?那么问题来了,现在我的目的,是将'url()'从dom当中挪出来,如果直接用propsXXX,不等于还得去dom中拼写字符串么? 再说个其它的。
v-for如何与computed进行配合? 假设有个数据:
'module_list': [{ 'title': '重磅推荐', 'templet_id': 1, 'book_list': [{ 'book_id': 1, 'book_name': '我是哭鬼师' }] }, { 'title': '精品推荐', 'templet_id': 2, 'book_list': [{ 'book_id': 1, 'book_name': '渡灵大师在咆哮啊咆哮' }, { 'book_id': 2, 'book_name': '倒卖凶宅那几年' }] }
当templet_id为1时,每行只输出一组数据,当为2时,输出两组。 原生js,肯定就是循环一遍,然后用if去判断module_list[i].templet_id == 1,然后怎样怎样。
在vue中,也是如此。
在外层div上使用v-for,比如:
<div v-for="item in data"> <div v-if="item.templet_id === 1"></div> <div v-if="item.templet_id === 2"></div> </div>
这样就可以输出不同的内容。
但正如上面说的,表达式尽量写在js里。
那么问题来了,这时候或许可以使用methods来写个函数来调用,但据说这样对性能消耗也大,因此使用computed是最划算的。
先写个methods的 比如:
isTmp (item) { return item.templet_id === 1 }
这时候,在模板里,就写成<div v-if="isTmp(item)"></div>即可,至于为何要将item传进来,这个就不用解释了吧。
那么computed怎么写呢? 如果直接:
computed: { isTmp () { return item.templet_id === 1 } }
这个item是读取不到的。
而computed里的函数是不能传参的。
这时候,就得对组件本身下手了。
假设这个子组件名叫<abc></abc> 直接到最外层做循环:
<abc v-for="item in data"></abc>
然后将item的数据以props的形式传进去:
<abc v-for="item in data" :item="item"></abc>
进入子组件,用props进行一下接收。 这时候就可以在computed里这么写了:
computed: { isTmp () { return this.item.templet_id === 1 } }
this.item,就是循环中的每个item。
使用:<div v-if="isTmp"></div>