关于vue.js:我不知道的Vuejs

41次阅读

共计 4531 个字符,预计需要花费 12 分钟才能阅读完成。

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}”,是无奈失常工作的,因为在解析一个像这样的简单表达式的时候,有很多边缘状况须要思考。

正文完
 0