自定义vue指令仅在存在时呈现

时间:2018-02-01 15:56:36

标签: vue.js

通常,我只想在有内容的情况下渲染div(或其他元素)。这意味着重复对标签中内容的引用,以及v-if,像这样...

<div v-if="store.sometimesIWillBeEmpty">{{store.sometimesIWillBeEmpty}}</div>

使用自定义指令,我想创建一个指令v-fill,其行为与上面的代码相似,但语法简化......

<div v-fill="store.sometimesIWillBeEmpty"></div>

已更新当邮件不为空时,以下内容有效。当消息为空时,我设置或清除什么不呈现?

var store = {message: "hello cobber"}
Vue.directive('fill', 
  function (el, binding, vnode) {
    if(binding.value)
      el.innerHTML = binding.value
    else
      el = null
  }
);

new Vue({
  el: '#fill-example',
  data: {
    store: store
  }
})

我离开了一行。 Here's my fiddle.任何人有任何想法吗?

1 个答案:

答案 0 :(得分:1)

可以制作一个简单的组件来做你想做的事情。指令需要更多的操作才能删除元素并将其放回正确的位置。

&#13;
&#13;
const vm = new Vue({
  el: '#fill-example',
  data: {
    empty: '',
    notEmpty: 'I have content'
  },
  components: {
    renderMaybe: {
      props: ['value'],
      template: `<div v-if="value" class="boxy">{{value}}</div>`
    }
  },
  directives: {
    fill: {
      bind(el, binding) {
        Vue.nextTick(() => {
          el.vFillMarkerNode = document.createComment('');
          el.parentNode.insertBefore(el.vFillMarkerNode, el.nextSibling);
          if (binding.value) {
            el.textContent = binding.value;
          } else {
            el.parentNode.removeChild(el);
          }
        });
      },
      update(el, binding) {
        if (binding.value) {
          el.vFillMarkerNode.parentNode.insertBefore(el, el.vFillMarkerNode);
          el.textContent = binding.value;
        } else {
          if (el.parentNode) {
            el.parentNode.removeChild(el);
          }
        }
      }
    }
  }
});

setTimeout(() => {
  vm.empty = "Now I have content, too.";
}, 1500);
&#13;
.boxy {
  border: thin solid black;
  padding: 1em;
}
&#13;
<script src="//unpkg.com/vue@latest/dist/vue.js"></script>
<div id="fill-example">
  Components:
  <render-maybe :value="empty"></render-maybe>
  <render-maybe :value="notEmpty"></render-maybe>
  Directives:
  <div class="boxy" v-fill="empty"></div>
  <div class="boxy" v-fill="notEmpty"></div>
</div>
&#13;
&#13;
&#13;