watch、computed、v-for、computed 2018-06-20 12:05:31

在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>

  1. Laravel5.7
  2. 微信相关
  3. Mysql
  4. 前端开发
  5. 随记
  6. 写作素材
  7. 开发工具
  8. 互联网