当前位置: 首页 > 文档资料 > Vue.js 教程 >

3.3.4 使用 JavaScript 代替模板功能

优质
小牛编辑
124浏览
2023-12-01

v-ifv-for

由于使用原生的 JavaScript 来实现某些东西很简单,Vue 的 render 函数没有提供专用的 API。比如,template 中的v-ifv-for

<ul v-if="items.length">
  <li v-for="item in items">{{ item.name }}</li>
</ul>
<p v-else>No items found.</p>

这些都会在 render 函数中被 JavaScript 的if/elsemap重写:

props: ['items'],
render: function (createElement) {
  if (this.items.length) {
    return createElement('ul', this.items.map(function (item) {
      return createElement('li', item.name)
    }))
  } else {
    return createElement('p', 'No items found.')
  }
}

v-model

render 函数中没有与v-model相应的 api - 你必须自己来实现相应的逻辑:

props: ['value'],
render: function (createElement) {
  var self = this
  return createElement('input', {
    domProps: {
      value: self.value
    },
    on: {
      input: function (event) {
        self.$emit('input', event.target.value)
      }
    }
  })
}

这就是深入底层要付出的,尽管麻烦了一些,但相对于v-model来说,你可以更灵活地控制。

事件 & 按键修饰符

对于.passive.capture.once事件修饰符, Vue 提供了相应的前缀可以用于on

Modifier(s)Prefix
.passive&
.capture!
.once~
.capture.onceor.once.capture~!

例如:

on: {
  '!click': this.doThisInCapturingMode,
  '~keyup': this.doThisOnce,
  '~!mouseover': this.doThisOnceInCapturingMode
}

对于其他的修饰符,前缀不是很重要,因为你可以在事件处理函数中使用事件方法:

Modifier(s)Equivalent in Handler
.stopevent.stopPropagation()
.preventevent.preventDefault()
.selfif (event.target !== event.currentTarget) return
Keys: .enter,.13if (event.keyCode !== 13) return(change13toanother key codefor other key modifiers)
Modifiers Keys:.ctrl,.alt,.shift,.metaif (!event.ctrlKey) return(changectrlKeytoaltKey,shiftKey,ormetaKey, respectively)

这里是一个使用所有修饰符的例子:

on: {
  keyup: function (event) {
  // 如果触发事件的元素不是事件绑定的元素
  // 则返回
  if (event.target !== event.currentTarget) return
  // 如果按下去的不是 enter 键或者
  // 没有同时按下 shift 键
  // 则返回
  if (!event.shiftKey || event.keyCode !== 13) return
  // 阻止事件冒泡
   event.stopPropagation()
  // 阻止该元素默认的 keyup 事件
  event.preventDefault()
    // ...
  }
}

插槽

你可以从this.$slots获取 VNodes 列表中的静态内容:

render: function (createElement) {
  // `<div><slot></slot></div>`
  return createElement('div', this.$slots.default)
}

还可以从this.$scopedSlots中获得能用作函数的作用域插槽,这个函数返回 VNodes:

props: ['message'],
render: function (createElement) {
  // `<div><slot :text="message"></slot></div>`
  return createElement('div', [
    this.$scopedSlots.default({
      text: this.message
    })
  ])
}

如果要用渲染函数向子组件中传递作用域插槽,可以利用 VNode 数据中的scopedSlots域:

render: function (createElement) {
  return createElement('div', [
    createElement('child', {
      // pass `scopedSlots` in the data object
      // in the form of { name: props => VNode | Array<VNode> }
      scopedSlots: {
        default: function (props) {
          return createElement('span', props.text)
        }
      }
    })
  ])
}