1. v-if之key

应用场景:在咱们登录的时候,用户能够应用用户账号以及用户电子邮箱进行登录,后盾接管账号及邮箱的参数都是同一个参数。

html局部

 <template v-if="loginType">    <label>Username</label>    <input ref="input" placeholder="Enter your username"> </template> <template v-else>    <label>Email</label>    <input ref="input" placeholder="Enter your email address"> </template> <button @click="chage">切换</button><div>   <button @click="submit">提交</button></div> 

js局部

 chage(){      let self = this;      self.loginType = !self.loginType; }, submit(){      let self = this;      alert(self.$refs.input.value)      console.log(self.$refs.input.value); }

这样,简略的业务就实现了。可是这样就会呈现一些待优化的问题(当咱们切换输入框时,之前输出的内容还保留着)
产生这个问题的起因:Vue 会尽可能高效地渲染元素,通常会复用已有元素而不是从头开始渲染。
有时候这样也不总是符合实际需要,所以 Vue 为你提供了一种形式来表白“这两个元素是齐全独立的,不要复用它们”。只需增加一个具备惟一值的 key attribute 即可:

 <template v-if="loginType">     <label>Username</label>     <input ref="input" placeholder="Enter your username" key="username"> </template> <template v-else>     <label>Email</label>     <input ref="input" placeholder="Enter your email address" key="email"> </template> <button @click="chage">切换</button>  <div>      <button @click="submit">提交</button>  </div>

2. 解析 DOM 模板之is

有些 HTML 元素,诸如 <ul>、<ol>、<table> 和 <select>,对于哪些元素能够呈现在其外部是有严格限度的。而有些元素,诸如 <li>、<tr> 和 <option>,只能呈现在其它某些特定的元素外部。
这会导致咱们应用这些有约束条件的元素时遇到一些问题。例如:

<table>  <blog-post-row></blog-post-row></table>

这个自定义组件 <blog-post-row> 会被作为有效的内容晋升到内部,并导致最终渲染后果出错。幸好这个非凡的 is attribute 给了咱们一个变通的方法:

<table>  <tr is="blog-post-row"></tr></table>

须要留神的是如果咱们从以下起源应用模板的话,这条限度是不存在的:

  • 字符串 (例如:template: '...')
  • 单文件组件 (.vue)
  • <script type="text/x-template">

3. 组件之v-model,.native和$listeners,.sync

* 在组件上应用 v-model

自定义事件也能够用于创立反对 v-model 的自定义输出组件。记住:

<input v-model="searchText">

等价于:

<input  v-bind:value="searchText"  v-on:input="searchText = $event.target.value">

当用在组件上时,v-model 则会这样:

<custom-input  v-bind:value="searchText"  v-on:input="searchText = $event"></custom-input>

为了让它失常工作,这个组件内的 <input> 必须:

  • 将其 value attribute 绑定到一个名叫 value 的 prop 上
  • 在其 input 事件被触发时,将新的值通过自定义的 input 事件抛出

写成代码之后是这样的:

Vue.component('custom-input', {  props: ['value'],  template: `    <input      v-bind:value="value"      v-on:input="$emit('input', $event.target.value)"    >  `})

当初 v-model 就应该能够在这个组件上完满地工作起来了:

<custom-input v-model="searchText"></custom-input>

* 自定义组件的 v-model
一个组件上的 v-model 默认会利用名为 value 的 prop 和名为 input 的事件,然而像单选框、复选框等类型的输出控件可能会将 value attribute 用于不同的目标。model 选项能够用来防止这样的抵触:

Vue.component('base-checkbox', {  model: {    prop: 'checked',    event: 'change'  },  props: {    checked: Boolean  },  template: `    <input      type="checkbox"      v-bind:checked="checked"      v-on:change="$emit('change', $event.target.checked)"    >  `})

当初在这个组件上应用 v-model 的时候:

<base-checkbox v-model="lovingVue"></base-checkbox>

这里的 lovingVue 的值将会传入这个名为 checked 的 prop。同时当 <base-checkbox> 触发一个 change 事件并附带一个新的值的时候,这个 lovingVue 的 property 将会被更新。

* 留神你依然须要在组件的 props 选项里申明 checked 这个 prop。

* 将原生事件绑定到组件
你可能有很屡次想要在一个组件的根元素上间接监听一个原生事件。这时,你能够应用 v-on 的 .native 修饰符:

<base-input v-on:focus.native="onFocus"></base-input>

在有的时候这是很有用的,不过在你尝试监听一个相似 <input> 的十分特定的元素时,这并不是个好主见。比方上述 <base-input> 组件可能做了如下重构,所以根元素实际上是一个 <label> 元素:

<label>  {{ label }}  <input    v-bind="$attrs"    v-bind:value="value"    v-on:input="$emit('input', $event.target.value)"  ></label>

这时,父级的 .native 监听器将静默失败。它不会产生任何报错,然而 onFocus 处理函数不会如你预期地被调用。

为了解决这个问题,Vue 提供了一个 $listeners property,它是一个对象,外面蕴含了作用在这个组件上的所有监听器。例如:

{  focus: function (event) { /* ... */ }  input: function (value) { /* ... */ },}

有了这个 $listeners property,你就能够配合 v-on="$listeners" 将所有的事件监听器指向这个组件的某个特定的子元素。对于相似 <input> 的你心愿它也能够配合 v-model 工作的组件来说,为这些监听器创立一个相似下述 inputListeners 的计算属性通常是十分有用的:

Vue.component('base-input', {  inheritAttrs: false,  props: ['label', 'value'],  computed: {    inputListeners: function () {      var vm = this      // `Object.assign` 将所有的对象合并为一个新对象      return Object.assign({},        // 咱们从父级增加所有的监听器        this.$listeners,        // 而后咱们增加自定义监听器,        // 或覆写一些监听器的行为        {          // 这里确保组件配合 `v-model` 的工作          input: function (event) {            vm.$emit('input', event.target.value)          }        }      )    }  },  template: `    <label>      {{ label }}      <input        v-bind="$attrs"        v-bind:value="value"        v-on="inputListeners"      >    </label>  `})

当初 <base-input> 组件是一个齐全通明的包裹器了,也就是说它能够齐全像一个一般的 <input> 元素一样应用了:所有跟它雷同的 attribute 和监听器都能够工作,不用再应用 .native 监听器。

* .sync 修饰符
在有些状况下,咱们可能须要对一个 prop 进行“双向绑定”。可怜的是,真正的双向绑定会带来保护上的问题,因为子组件能够变更父组件,且在父组件和子组件两侧都没有显著的变更起源。

这也是为什么咱们举荐以 update:myPropName 的模式触发事件取而代之。举个例子,在一个蕴含 title prop 的假如的组件中,咱们能够用以下办法表白对其赋新值的用意:

this.$emit('update:title', newTitle)

而后父组件能够监听那个事件并依据须要更新一个本地的数据 property。例如:

<text-document  v-bind:title="doc.title"  v-on:update:title="doc.title = $event"></text-document>

为了不便起见,咱们为这种模式提供一个缩写,即 .sync 修饰符:

<text-document v-bind:title.sync="doc.title"></text-document>

* 留神带有 .sync 修饰符的 v-bind 不能和表达式一起应用 (例如 v-bind:title.sync=”doc.title + ‘!’” 是有效的)。取而代之的是,你只能提供你想要绑定的 property 名,相似 v-model。

当咱们用一个对象同时设置多个 prop 的时候,也能够将这个 .sync 修饰符和 v-bind 配合应用:

<text-document v-bind.sync="doc"></text-document>

这样会把 doc 对象中的每一个 property (如 title) 都作为一个独立的 prop 传进去,而后各自增加用于更新的 v-on 监听器。

* 将 v-bind.sync 用在一个字面量的对象上,例如 v-bind.sync=”{ title: doc.title }”,是无奈失常工作的,因为在解析一个像这样的简单表达式的时候,有很多边缘状况须要思考。