你的站點上動態渲染的任意 HTML 可能會很是危險,由於它很容易致使 XSS 攻擊。請只對可信內容使用 HTML 插值,毫不要對用戶提供的內容插值。html
利用標籤模板,過濾 HTML 字符串,防止用戶輸入惡意內容。vue
function SaferHTML(templateData) { let s = templateData[0]; console.log(s); for (let i = 1; i < arguments.length; i++) { let arg = String(arguments[i]); // Escape special characters in the substitution. s += arg.replace(/&/g, "&") .replace(/</g, "<") .replace(/>/g, ">"); // Don't escape special characters in the template. s += templateData[i]; } return s; }
template不支持v-showes6
默認狀況下在切換dom時相同的結構會被複用,若是不須要複用,須要添加key數組
<template v-if="loginType === 'username'"> <label>Username</label> <input placeholder="Enter your username" key="1"> </template> <template v-else> <label>Email</label> <input placeholder="Enter your email address" key="2"> </template>
多個複選框。v-model須要綁定到一個數組app
//html <div id='example-3'> <input type="checkbox" id="jack" value="Jack" v-model="checkedNames"> <label for="jack">Jack</label> <input type="checkbox" id="john" value="John" v-model="checkedNames"> <label for="john">John</label> <input type="checkbox" id="mike" value="Mike" v-model="checkedNames"> <label for="mike">Mike</label> <br> <span>Checked names: {{ checkedNames }}</span> </div> //js new Vue({ el: '#example-3', data: { checkedNames: [] } })
多選時的select框同理dom
不要在選項屬性或回調上使用箭頭函數,好比 created: () => console.log(this.a) 或
vm.$watch('a', newValue => this.myMethod())。由於箭頭函數是和父級上下文綁定在一塊兒的,this 不會是如你所預期的 Vue 實例,常常致使 Uncaught TypeError: Cannot read property of undefined 或
Uncaught TypeError: this.myMethod is not a function 之類的錯誤。ide
Vue 包含一組觀察數組的變異方法,因此它們也將會觸發視圖更新。這些方法以下:push()、pop()、shift()、unshift()、splice()、sort()、reverse()。函數
變異方法 (mutation method),顧名思義,會改變被這些方法調用的原始數組。相比之下,也有非變異 (non-mutating method) 方法,例如:filter(), concat() 和 slice() 。這些不會改變原始數組,但老是返回一個新數組。當使用非變異方法時,能夠用新數組替換舊數組:post
example1.items = example1.items.filter(function (item) { return item.message.match(/Foo/) })
因爲 JavaScript 的限制,Vue 不能檢測如下變更的數組:性能
var vm = new Vue({ data: { items: ['a', 'b', 'c'] } }) vm.items[1] = 'x' // 不是響應性的 vm.items.length = 2 // 不是響應性的
爲了解決第一類問題,如下兩種方式均可以實現和 vm.items[indexOfItem] = newValue 相同的效果,同時也將觸發狀態更新:
// Vue.set Vue.set(vm.items, indexOfItem, newValue) // Array.prototype.splice vm.items.splice(indexOfItem, 1, newValue)
你也可使用 vm.$set 實例方法,該方法是全局方法 Vue.set 的一個別名:
vm.$set(vm.items, indexOfItem, newValue)
爲了解決第二類問題,你可使用 splice:
vm.items.splice(newLength)
==Vue.set可改成vm.$set==
仍是因爲 JavaScript 的限制,Vue 不能檢測對象屬性的添加或刪除:
var vm = new Vue({ data: { a: 1 } }) // `vm.a` 如今是響應式的 vm.b = 2 // `vm.b` 不是響應式的
對於已經建立的實例,Vue 不能動態添加根級別的響應式屬性。可是,可使用 Vue.set(object, key, value) 方法向嵌套對象添加響應式屬性。例如,對於:
var vm = new Vue({ data: { userProfile: { name: 'Anika' } } })
你能夠添加一個新的 age 屬性到嵌套的 userProfile 對象:
Vue.set(vm.userProfile, 'age', 27)
若是須要爲已有對象賦予多個屬性:
vm.userProfile = Object.assign({}, vm.userProfile, { age: 27, favoriteColor: 'Vue Green' })
刪除屬性用Vue.delete或者vm.$delete。
Vue.delete(vm.items,0); //或者 vm.$delete(vm.items,0);
有些 HTML 元素,諸如 <ul>、<ol>、<table> 和 <select>,對於哪些元素能夠出如今其內部是有嚴格限制的。而有些元素,諸如 <li>、<tr> 和 <option>,只能出如今其它某些特定的元素內部。
這會致使咱們使用這些有約束條件的元素時遇到一些問題。例如:
<table> <blog-post-row></blog-post-row> </table>
這個自定義組件
<table> <tr is="blog-post-row"></tr> </table>
須要注意的是若是咱們從如下來源使用模板的話,這條限制是不存在的:
每一個組件必須只有一個根元素
<h3>{{ title }}</h3> <div v-html="content"></div>
以上模板會報錯,將其包裹在一個父元素內便可解決
<div class="blog-post"> <h3>{{ title }}</h3> <div v-html="content"></div> </div>
當組件名使用 kebab-case方式時,在引用這個自定義元素時必須使用 kebab-case
當組件名使用 PascalCase方式時,引用這個自定義元素時可以使用 kebab-case 或者 PascalCase
可是,直接在 DOM (即非字符串的模板) 中使用時只有 kebab-case 是有效的
跟組件和 prop 不一樣,事件名不存在任何自動化的大小寫轉換。而是觸發的事件名須要徹底匹配監聽這個事件所用的名稱。
this.$emit('myEvent') <my-component v-on:my-event="doSomething"></my-component>
以上監聽是沒法生效的,v-on 事件監聽器在 DOM 模板中會被自動轉換爲全小寫 (由於 HTML 是大小寫不敏感的)。所以,推薦始終使用 kebab-case 的事件名
常規綁定方法
//html <div id="example-2"> <!-- `greet` 是在下面定義的方法名 --> <button v-on:click="greet">Greet</button> </div> //js var example2 = new Vue({ el: '#example-2', data: { name: 'Vue.js' }, // 在 `methods` 對象中定義方法 methods: { greet: function (event) { // `this` 在方法裏指向當前 Vue 實例 alert('Hello ' + this.name + '!') // `event` 是原生 DOM 事件 if (event) { alert(event.target.tagName) } } } })
內聯 JavaScript 語句中調用方法
//html <div id="example-3"> <button v-on:click="say('hi', $event)">Say hi</button> <button v-on:click="say('what', $event)">Say what</button> </div> //js new Vue({ el: '#example-3', methods: { say: function (message, event) { alert(message) } } })
<input v-model="searchText"> //等價於 <input v-bind:value="searchText" v-on:input="searchText = $event.target.value" >
給組件添加 v-model 屬性時,==默認會把 value 做爲組件的屬性,而後把 'input' 值做爲給組件綁定事件時的事件名==
可是在單選框、複選框等類型的輸入控件,須要的就不是默認的value特性以及input事件了,有兩種方法進行修改
html
<base-checkbox v-model="lovingVue"></base-checkbox>
Vue.component('base-checkbox', { props:['value'] template: ` <input type="checkbox" v-bind:checked="value" v-on:change="$emit('change', $event.target.checked)" > ` })
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-on添加.native修飾符便可
<base-input v-on:focus.native="onFocus"></base-input>
特殊狀況: 若是使用focus監聽input元素,而且input元素被包裹在一個父元素中,.native監聽器將默認失敗
名詞解釋
$attrs--繼承全部的父組件屬性(除了prop傳遞的屬性、class 和 style )
inheritAttrs:默認值true,繼承全部的父組件屬性(除props的特定綁定)做爲普通的HTML特性應用在子組件的根元素上,若是你不但願組件的根元素繼承特性設置inheritAttrs: false,可是class屬性和style會繼承。
$listeners--屬性,它是一個對象,裏面包含了做用在這個組件上的全部監聽器,你就能夠配合 v-on="$listeners" 將全部的事件監聽器指向這個組件的某個特定的子元素。
代碼演示:
//HTML <div id="app"> <base-input v-model="a" placeholder="tip" label="name" class="a" :style="{color: 'red'}"></base-input> </div> //JS Vue.component('base-input', { props: ['value'], template: ` <label> {{$attrs.placeholder}} {{$attrs.label}} <input v-bind:value="value" v-on:input="$emit('input', $event.target.value)" v-bind="$attrs"> </label> ` }); var v = new Vue({ el: '#app', data: { a: '123', } });
由於inheritAttrs的默認值爲ture,因此組件的根元素label將繼承父組件的全部屬性(除了class、style和props傳遞的屬性);組件內的input則經過v-on="$attrs"綁定了父組件的屬性。
渲染結果爲:
<label placeholder="tip" label="name" class="a" style="color: red;"> tip name <input placeholder="tip" label="name"> </label>
若將inheriAttrs值設爲false,
根元素label將不會繼承父組件的屬性。
<label class="a" style="color: red;"> tip name <input placeholder="tip" label="name"> </label>
$attrs能夠打包父組件的屬性,一樣的,$listeners則打包父組件的事件
//html <div id="app"> <base-input @click="func" @focus="funf" v-model="a" placeholder="tip" label="name" class="a" :style="{color: 'red'}"></base-input> </div> //js Vue.component('base-input', { // inheritAttrs: false, props: ['value'], template: ` <label> {{$attrs.placeholder}} {{$attrs.label}} <input v-bind:value="value" v-on:input="$emit('input', $event.target.value)" v-bind="$attrs" v-on="$listeners"> </label> ` }); var v = new Vue({ el: '#app', data: { a: '123', }, methods: { func: function(){ console.log('被點擊了'); }, funf: function(){ console.log('得到焦點'); } }, });
若是組件沒有包含一個
若是數據變化後想獲取真實dom中的內容,須要等待頁面渲染完畢後再去獲取全部的dom操做最好放在nextTick中
若是組件模板沒有包含一個
<my-component> Your Profile </my-component>
當有多個內容須要分配至相應插槽中,能夠將內容包裹在設置了slot特性的 中
//html <my-component> <template slot="header"> <h1 slot="header">這是標題</h1> <p slot="test">這是段落</p> <a href="baidu.com">百度</a> </template> <div>盒子</div> </my-component> <template id="my"> <header> <slot name="header"></slot> </header> <slot></slot> </template> //js my-component{ template:'#my' }
若是
//html <my-component> <h1 slot="header">這是標題</h1> <p slot="test">這是段落</p> <a href="baidu.com">百度</a> </my-component> <template id="my"> <slot name="header"></slot> <slot></slot> </template> //js my-component{ template:'#my' }
上面代碼中,h1會被保存在name爲header的slot中,而p、a標籤將會被保存在默認插槽中。
插槽標籤內部加入內容能夠起到默認值效果,
<button type="submit"> <slot>Submit</slot> </button>
若是父組件爲這個插槽提供了內容,則默認的內容會被替換掉。
//todo-list模板 <ul> <li v-for="todo in todos" v-bind:key="todo.id" > {{ todo.text }} </li> </ul>
假設咱們的todo-list組件被多個地方調用,而咱們但願能在不一樣的地方調用組件的時候,組件的todo.text不只限於以li的形式渲染,而是能以自定義的形式渲染,這時,做用域插槽能夠知足:
//html <todo-list :todos="todos"> <!-- 將 `slotProps` 定義爲插槽做用域的名字 --> <template slot-scope="slotProps"> <li>{{slotProps.text}}</li> </template> </todo-list> //js //todo-list模板 <ul> <slot v-for="todo in todos" :todo="todo" :key="todo.id"> {{ todo.text }} </slot> </ul>
首先,在todo-list模板中,將li替換爲slot,意味着slot具體被渲染成什麼將由html中的todo-list組件的內容決定;接下來,在todo-list組件內添加template標籤並設置slot-scope屬性來接收slot所綁定的todo屬性。就此,todo對象傳遞給了slotProps,todo-list組件內的li能夠隨意替代爲其餘標籤。
咱們以前曾經在一個多標籤的界面中使用 is 特性來切換不一樣的組件:
<component :is="currentTabComponent"></component>
當在這些組件之間切換的時候,你有時會想保持這些組件的狀態,以免反覆重渲染致使的性能問題。這時,咱們在外圍包裹keep-alive便可
<keep-alive> <component v-bind:is="currentTabComponent"></component> </keep-alive>