vue 語法基礎(chǔ)
- 插值之剧、表達式 2.指令宾毒、動態(tài)屬性 3. v-html: 會有xss風險咽块,會覆蓋子組件
<template>
<div>
<p>文本插值 {{message}}</p>
<p>JS 表達式 {{ flag ? 'yes' : 'no' }} (只能是表達式纪蜒,不能是 js 語句)</p>
<p :id="dynamicId">動態(tài)屬性 id</p>
<hr/>
<p v-html="rawHtml">
<span>有 xss 風險</span>
<span>【注意】使用 v-html 之后瓤漏,將會覆蓋子元素</span>
</p>
</div>
</template>
<script>
export default {
data() {
return {
message: 'hello vue',
flag: true,
rawHtml: '指令 - 原始 html <b>加粗</b> <i>斜體</i>',
dynamicId: `id-${Date.now()}`
}
}
}
</script>
- computed
<template>
<div>
<p>num {{num}}</p>
<p>double1 {{double1}}</p>
<input v-model="double2"/>
</div>
</template>
<script>
export default {
data() {
return {
num: 20
}
},
computed: {
double1() {
return this.num * 2
},
double2: {
get() {
return this.num * 2
},
set(val) {
this.num = val/2
}
}
}
}
</script>
- watch
<template>
<div>
<input v-model="name"/>
<input v-model="info.city"/>
</div>
</template>
<script>
export default {
data() {
return {
name: '雙越',
info: {
city: '北京'
}
}
},
watch: {
name(oldVal, val) {
// eslint-disable-next-line
console.log('watch name', oldVal, val) // 值類型,可正常拿到 oldVal 和 val
},
info: {
handler(oldVal, val) {
// eslint-disable-next-line
console.log('watch info', oldVal, val) // 引用類型校套,拿不到 oldVal 价脾。因為指針相同,此時已經(jīng)指向了新的 val
},
deep: true // 深度監(jiān)聽
}
}
}
</script>
- class 和 style
<template>
<div>
<p :class="{ black: isBlack, yellow: isYellow }">使用 class</p>
<p :class="[black, yellow]">使用 class (數(shù)組)</p>
<p :style="styleData">使用 style</p>
</div>
</template>
<script>
export default {
data() {
return {
isBlack: true,
isYellow: true,
black: 'black',
yellow: 'yellow',
styleData: {
fontSize: '40px', // 轉(zhuǎn)換為駝峰式
color: 'red',
backgroundColor: '#ccc' // 轉(zhuǎn)換為駝峰式
}
}
}
}
</script>
<style scoped>
.black {
background-color: #999;
}
.yellow {
color: yellow;
}
</style>
- 條件渲染 v-if v-show(display:none)
<template>
<div>
<p v-if="type === 'a'">A</p>
<p v-else-if="type === 'b'">B</p>
<p v-else>other</p>
<p v-show="type === 'a'">A by v-show</p>
<p v-show="type === 'b'">B by v-show</p>
</div>
</template>
<script>
export default {
data() {
return {
type: 'a'
}
}
}
</script>
- 循環(huán)(列表)渲染
<template>
<div>
<p>遍歷數(shù)組</p>
<ul>
<li v-for="(item, index) in listArr" :key="item.id">
{{index}} - {{item.id}} - {{item.title}}
</li>
</ul>
<p>遍歷對象</p>
<ul >
<li v-for="(val, key, index) in listObj" :key="key">
{{index}} - {{key}} - {{val.title}}
</li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
flag: false,
listArr: [
{ id: 'a', title: '標題1' }, // 數(shù)據(jù)結(jié)構(gòu)中笛匙,最好有 id 侨把,方便使用 key
{ id: 'b', title: '標題2' },
{ id: 'c', title: '標題3' }
],
listObj: {
a: { title: '標題1' },
b: { title: '標題2' },
c: { title: '標題3' },
}
}
}
}
</script>
// v-for 和 v-if 不建議放在一起,會在循環(huán)中重復(fù)判斷
- 事件
-> event事件膳算,自定義參數(shù)
-> 事件修飾符座硕,按鍵修飾符
-> 觀察事件被綁定到哪里?
<template>
<div>
<p>{{num}}</p>
<button @click="increment1">+1</button>
<button @click="increment2(2, $event)">+2</button>
</div>
</template>
<script>
export default {
data() {
return {
num: 0
}
},
methods: {
increment1(event) {
// eslint-disable-next-line
console.log('event', event, event.__proto__.constructor) // 是原生的 event 對象
// eslint-disable-next-line
console.log(event.target)
// eslint-disable-next-line
console.log(event.currentTarget) // 注意涕蜂,事件是被注冊到當前元素的华匾,和 React 不一樣
this.num++
// 1. event 是原生的
// 2. 事件被掛載到當前元素,并在當前元素被觸發(fā)
// 和 DOM 事件一樣
},
increment2(val, event) {
// eslint-disable-next-line
console.log(event.target)
this.num = this.num + val
},
loadHandler() {
// do some thing
}
},
mounted() {
window.addEventListener('load', this.loadHandler)
},
beforeDestroy() {
//【注意】用 vue 綁定的事件,組建銷毀時會自動被解綁
// 自己綁定的事件机隙,需要自己銷毀V├!有鹿!
window.removeEventListener('load', this.loadHandler)
}
}
</script>
-
事件修飾符
image.png -
按鍵修飾符
image.png 表單
v-model
常見的表單項 textarea checkbox radio select
修飾符 lazy number trim
<template>
<div>
<p>輸入框: {{name}}</p>
// 截取前后空格
<input type="text" v-model.trim="name"/>
// 防抖的效果
<input type="text" v-model.lazy="name"/>
<input type="text" v-model.number="age"/>
<p>多行文本: {{desc}}</p>
<textarea v-model="desc"></textarea>
<!-- 注意旭旭,<textarea>{{desc}}</textarea> 是不允許的!4邪稀持寄! -->
<p>復(fù)選框 {{checked}}</p>
<input type="checkbox" v-model="checked"/>
<p>多個復(fù)選框 {{checkedNames}}</p>
<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>
<p>單選 {{gender}}</p>
<input type="radio" id="male" value="male" v-model="gender"/>
<label for="male">男</label>
<input type="radio" id="female" value="female" v-model="gender"/>
<label for="female">女</label>
<p>下拉列表選擇 {{selected}}</p>
<select v-model="selected">
<option disabled value="">請選擇</option>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
<p>下拉列表選擇(多選) {{selectedList}}</p>
<select v-model="selectedList" multiple>
<option disabled value="">請選擇</option>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
</div>
</template>
<script>
export default {
data() {
return {
name: '雙越',
age: 18,
desc: '自我介紹',
checked: true,
checkedNames: [],
gender: 'male',
selected: '',
selectedList: []
}
}
}
</script>
父子組件如何通訊-props 和 emit
off
- 組件生命周期
單個組件
掛載 mounted
更新 updated
銷毀 destoryed
created 之前 new Vue 的實例還沒有生成,只存在于 js 內(nèi)存模型中
mounted 組件還沒有渲染在頁面上娱俺,網(wǎng)頁繪制完成
beforeDestory 里面需要解除綁定稍味,銷毀子組件以及事件監(jiān)聽器
父子組件生命周期
父組件 created
子組件 created
子組件 mounted
父組件 mounted
父組件 beforeUpdated
子組件 beforeUpdated
子組件 updated
父組件 updated
vue 高級特性
- 自定義 v-model
<template>
<!-- 例如:vue 顏色選擇 -->
<input type="text"
:value="text1"
@input="$emit('change1', $event.target.value)"
>
<!--
1. 上面的 input 使用了 :value 而不是 v-model
2. 上面的 change1 和 model.event1 要對應(yīng)起來
3. text1 屬性對應(yīng)起來
-->
</template>
<script>
export default {
model: {
prop: 'text1', // 對應(yīng) props text1
event: 'change1'
},
props: {
text1: String,
default() {
return ''
}
}
}
</script>
- $nextTick refs (組件更新之后如何獲取最新DOM)
vue是異步渲染
data 改變之后,DOM不會立刻渲染
$nextTick 會在 DOM 渲染之后被觸發(fā)荠卷,以獲取最新的DOM節(jié)點
<template>
<div id="app">
<ul ref="ul1">
<li v-for="(item, index) in list" :key="index">
{{item}}
</li>
</ul>
<button @click="addItem">添加一項</button>
</div>
</template>
<script>
export default {
name: 'app',
data() {
return {
list: ['a', 'b', 'c']
}
},
methods: {
addItem() {
this.list.push(`${Date.now()}`)
this.list.push(`${Date.now()}`)
this.list.push(`${Date.now()}`)
// 1. 異步渲染模庐,$nextTick 待 DOM 渲染完再回調(diào)
// 3. 頁面渲染時會將 data 的修改做整合,多次 data 修改只會渲染一次
this.$nextTick(() => {
// 獲取 DOM 元素
const ulElem = this.$refs.ul1
// eslint-disable-next-line
console.log( ulElem.childNodes.length )
})
}
}
}
</script>
- slot 父組件想向子組件中插入一部分內(nèi)容
<!-- slot -->
<!-- <SlotDemo :url="website.url">
{{website.title}}
</SlotDemo> -->
<!-- <ScopedSlotDemo :url="website.url">
<template v-slot="slotProps">
{{slotProps.slotData.title}}
</template>
</ScopedSlotDemo> -->
// 基本使用
// SlotDemo
<template>
<a :href="url">
<slot>
默認內(nèi)容油宜,即父組件沒設(shè)置內(nèi)容時掂碱,這里顯示
</slot>
</a>
</template>
<script>
export default {
props: ['url'],
data() {
return {}
}
}
</script>
// 作用域插槽
// ScopedSlotDemo
<template>
<a :href="url">
<slot :slotData="website">
{{website.subTitle}} <!-- 默認值顯示 subTitle ,即父組件不傳內(nèi)容時 -->
</slot>
</a>
</template>
<script>
export default {
props: ['url'],
data() {
return {
website: {
url: 'http://wangEditor.com/',
title: 'wangEditor',
subTitle: '輕量級富文本編輯器'
}
}
}
}
</script>
// 具名插槽
image.png
- 異步組件
<!-- 動態(tài)組件 --> 根據(jù)數(shù)據(jù)慎冤,動態(tài)渲染的場景疼燥,即組件類型不確定
語法: :is="xxx" xxx 組件的名字
<component :is="NextTickName"/>
- 異步組件
* import() 函數(shù)
* 按需加載,異步加載大組件
<!-- 異步組件 -->
<FormDemo v-if="showFormDemo"/>
<button @click="showFormDemo = true">show form demo</button>
export default {
components: {
FormDemo: () => import('../BaseUse/FormDemo')
}
}
- keep-alive (vue 如何緩存組件)適用場景:需要頻繁切換的組件
* activated
<keep-alive> <!-- tab 切換 -->
<KeepAliveStageA v-if="state === 'A'"/>
<KeepAliveStageB v-if="state === 'B'"/>
<KeepAliveStageC v-if="state === 'C'"/>
</keep-alive>
- mixin (vue組件代碼抽取蚁堤,多個組件有相同的邏輯醉者,抽離出來)
* 變量來源不明確;
* mixin抽離的代碼 data 里面的命名變量不能相同,會存在覆蓋的問題湃交;命名沖突;
* mixin 和 組件可能出現(xiàn)多對多的關(guān)系藤巢,復(fù)雜度比較高搞莺;