Vue3-組件化-Vue核心思想之一

一.組件及組件化

1.組件化的作用

由于之前的代碼全寫在一個App.vue這個文件里面,會到導致一個文件代碼過于多而且不易復用,所以有組件化的思想。

2.組件的使用

①創建

創建一個.vue文件,使用setup的簡寫方式會自動導出.vue文件

②導入
import 組件對象 from '相對路徑'// eg
import MyPanel from './components/MyPanel.vue'
③使用

把組件當做?定義標簽使?(單雙標簽均可)

<組件名></組件名>
<組件名 />// eg
<!-- ?駝峰標 雙標簽 -->
<MyPanel></MyPanel>
<!-- ?駝峰 ?閉合的單標簽 -->
<MyPanel />
<!-- 烤串法 雙標簽 -->
<my-panel></my-panel>
<!-- 烤串法 ?閉合的單標簽 -->
<my-panel />

3.組件的全局注冊

①特點

全局注冊的組件,在項?的任何組件中都能使?

②步驟

1. 創建.vue組件(三個組成部分)

2. main.js 中進?全局注冊

③使用方式

當成HTML標簽直接使?:

? 雙標簽: <組件名></組件名>

? ?閉合的單標簽: <組件名 />

④在main.js中注冊的寫法
import MyPanel from './components/MyPanel.vue'
const app = createApp(App)
// 注冊全局組件
// app.component('組件名', 組件對象)eg:
// ?駝峰組件名
app.component('MyPanel', MyPanel)
// 烤串法組件名
app.component('my-panel', MyPanel)

二.組件生命周期

1.生命周期的介紹

組件的生命周期的四個階段:

1. 創建階段:創建響應式數據

2. 掛載階段:渲染模板
3. 更新階段:修改數據,更新視圖

4. 卸載階段:卸載組件

2.組件生命周期的鉤子

介紹:

? ? ? ?每個 Vue 組件實例在創建時都需要經歷?系列的初始化步驟,?如設置好數據監聽,編譯模板,掛載實例到真實 DOM 樹上,以及在數據改變時更新 DOM。在此過程中,會 ?動運??些函數,這些函數被稱為【Vue?命周期鉤?】
鉤子的本質就是函數,只不過這些函數比較特殊,無需程序員調用,而是有vue3內部的執行機制自己調用。鉤子函數存在的意義就是給了程序員在特定的時機添加自己的代碼的機會,比如組件創建完畢了,就想發送ajax請求,那么可以在創建后的鉤子函數中編寫相關代碼;還比如頁面渲染完畢后,立刻讓輸入框自動聚焦,那么可以在掛載后的鉤子函數中編寫相關代碼

生命周期的八個鉤子:

分別是:
1. 創建階段: 1. beforeCreate (): 創建前 2. created (): 創建后
2. 掛載階段: 1. beforeMount (): 掛載前 2. mounted (): 掛載后
3. 更新階段: 1. beforeUpdate (): 更新前 2. updated (): 更新后
4. 卸載階段: 1. beforeUnmount (): 卸載前 2. unmounted (): 卸載后?

vue生命周期與鉤子的關系圖:

3.選項式API生命周期的鉤子寫法(vue2的寫法)

代碼示例:

App.vue 文件代碼

<script setup>
import LifeCycle from './components/LifeCycle.vue'
import { ref } from 'vue'
const isLive = ref(true)
</script>
<template><LifeCycle v-if="isLive" />
</template>
<style scoped></style>

LifeCycle.vue 文件代碼

<script>
export default {// 提供響應式數據data() {return {count: 0,}},// 提供?法/函數methods: {fn() {console.log('fn 函數執?了')},},setup() {console.log('0-setup')},// 創建階段(第?階段):Vue組件創建/出?階段:// 創建前:此時?法訪問 data 數據,也?法調? methods ?法beforeCreate() {console.log('1-beforeCreate')// console.log(this.count) // undefined// console.log(this.fn) // undefined},// 創建后:此時可以訪問 data 數據,也可以調? methods ?法created() {console.log('2-created')// console.log(this.count) // 0// console.log(this.fn)// 訪問到函數// this.fn()// 開啟定時器// 給當前組件實例新增了?個 timerId 屬性,保存了當前定時器的 id 值// this.timerId = setInterval(() => {//     console.log(this.count)//     }, 1000)// },},// 掛載階段(第?階段):模版渲染階段// 掛載前:此時寫在 template 下的標簽還沒有變成真實DOM,故??法獲取DOMbeforeMount() {console.log('3-beforeMount')// console.log(document.querySelector('p')) // null},// 掛載后:此時寫在 template 下的標簽已經變成了真實DOM,故?可以獲取DOM(是最早可以操作DOM的時機)mounted() {console.log('4-mounted')// console.log(document.querySelector('p')) // <p>0</p>// document.querySelector('p').style.color = 'red'},// 更新階段(第三階段):數據變了,組件重新渲染的過程// 更新前beforeUpdate() {console.log('5-beforeUpdate')// console.log(this.count)// console.log(document.querySelector('p').innerText) // 舊內容(以前的內容)},// 更新后updated() {console.log('6-updated')// console.log(this.count)// console.log(document.querySelector('p').innerText) // 新內容},// 卸載階段(第四階段):組件移除階段beforeUnmount() {console.log('7-beforeUnmount')},unmounted() {console.log('8-mounted')//關閉定時器// clearInterval(this.timerId)},
}
</script>
<template><div><p>{{ count }}</p><button @click="count++">+1</button></div>
</template><style scoped></style>

比較實用的應該就只有:created,mounted,unmounted 這三個鉤子。

4.組合式API生命周期鉤子

創建階段掛載階段更新階段銷毀階段
Vue2beforeCreate createdbeforeMount mountedbeforeUpdate updatedbeforeUnmount unmounted
Vue3setup (網絡請求)onBeforeMount onMounted (操作 DOM)onBeforeUpdate onUpdatedonBeforeUnmount onUnmounted (清理工作)
代碼示例:

App.vue 文件代碼

<script setup>
import LifeCycle from './components/LifeCycle.vue'
import { ref } from 'vue'
const isLive = ref(true)
</script>
<template><LifeCycle v-if="isLive" />
</template>
<style scoped></style>

LifeCycle.vue 文件代碼

<script setup>
import { onMounted, ref } from 'vue'
onMounted(() => {console.log('渲染之后')document.querySelector('p').style.color = 'green'
})
let count = ref(0)
</script><template><div><p>{{ count }}</p><button @click="count++">+1</button></div>
</template><style scoped></style>

三.scoped

1.scoped作用

寫在組件中的樣式會 全局?效, 因此很容易造成多個組件之間的樣式沖突問題。

1. 全局樣式: 默認組件中的樣式會作?到全局,任何?個組件中都會受到此樣式的影響

2. 局部樣式: 可以給組件加上scoped 屬性,可以讓樣式只作?于當前組件的標簽

2.scoped原理

1. 組件內所有標簽都被添加data-v-hash值 的?定義屬性

2. css選擇器都被添加 [data-v-hash值] 的屬性選擇器

最終效果: 必須是當前組件的元素, 才會有這個?定義屬性, 從?保證了樣式只能作?到當前組件。

四.組件通信

1.介紹

作用:

之前把代碼寫在?起的,數據直接使?即可;現在是組件化開發,通過代碼拆分和組合的?式進?開發,這種情況下,還要達到和不拆分之前?樣的效果,這時組件之間難免需要數據傳遞,這就需要組件之間進?通信。

組件之間的關系:

1、??關系:誰被使?, 誰就是?組件, 當前組件就是?組件

2、???關系

2.父傳子(defineProps)

傳數據步驟:

1. ?組件通過 defineProps 接收數據(?接)

2. ?組件通過 ?定義屬性 傳遞數據 (?傳)

流程圖:

代碼案例:

App.vue 文件代碼

<script setup>
import MyGoods from './components/MyGoods.vue'
// 商品列表
const goodsList = [{id: '4001172',name: '稱?如意?搖咖啡磨?機咖啡?研磨機',price: 289,picture: 'https://cxk-1305128831.cos.ap-beijing.myqcloud.com/11-00.gif',},{id: '4001594',name: '?式?陶功夫茶組雙側把茶具禮盒裝',price: 288,picture: 'https://cxk-1305128831.cos.ap-beijing.myqcloud.com/11-00.gif',},{id: '4001009',name: '?制?泡茶盤正?形瀝?茶臺品茶盤',price: 109,picture: 'https://cxk-1305128831.cos.ap-beijing.myqcloud.com/11-00.gif',},{id: '4001874',name: '古法溫酒汝瓷酒具套裝?酒杯蓮花溫酒器',price: 488,picture: 'https://cxk-1305128831.cos.ap-beijing.myqcloud.com/11-00.gif',},{id: '4001649',name: '?師監制?泉?瓷茶葉罐',price: 139,picture: 'https://cxk-1305128831.cos.ap-beijing.myqcloud.com/11-00.gif',},{id: '3997185',name: '與眾不同的?感汝瓷?酒杯套組1壺4杯',price: 108,picture: 'https://cxk-1305128831.cos.ap-beijing.myqcloud.com/11-00.gif',},{id: '3997403',name: '??吹制更厚實?酒杯壺套裝6壺6杯',price: 100,picture: 'https://cxk-1305128831.cos.ap-beijing.myqcloud.com/11-00.gif',},{id: '3998274',name: '德國百年?藝?端?晶玻璃紅酒杯2?裝',price: 139,picture: 'https://cxk-1305128831.cos.ap-beijing.myqcloud.com/11-00.gif',},
]
</script>
<template><div class="list"><!-- 循環遍歷、獨?傳值--><MyGoodsv-for="item in goodsList":key="item.id":imgUrl="item.picture":title="item.name":price="item.price"/></div>
</template>
<style lang="scss">
* {margin: 0;padding: 0;box-sizing: border-box;
}
.list {width: 1000px;margin: 0 auto;display: flex;flex-wrap: wrap;
}
</style>

MyGoods.vue 文件代碼

<script setup>
// 接受數據
defineProps(['imgUrl', 'title', 'price'])
</script>
<template><div class="item"><img :src="imgUrl" :alt="title" /><p class="name">{{ title }}</p><p class="price">{{ price }}.00</p></div>
</template>
<style lang="scss" scoped>
.item {width: 240px;margin-left: 10px;padding: 20px 30px;transition: all 0.5s;margin-bottom: 20px;.item:nth-child(4n) {margin-left: 0;}&:hover {box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.2);transform: translate3d(0, -4px, 0);cursor: pointer;}img {width: 100%;}.name {font-size: 18px;margin-bottom: 10px;color: #666;}.price {display: flex;align-items: center;font-size: 22px;color: firebrick;button {margin-left: 48px;font-size: 14px;outline: none;}}.price::before {content: '¥';font-size: 22px;}
}
</style>

3.子傳父(defineEmits)

數據傳輸步驟:

1. ?組件內,?組件上,綁定?定義事件,@?定義事件="?修改數據的函數" (?綁定)

2. ?組件恰當時機, 觸發?組件的?定義事件 , emit('?定義事件', 攜帶的參數...), 從?導致?組件修改函數的時候(?觸發)前提還需要拿到自定義事件的函數 emit? ?
const emit = defineEmits()
代碼案例:

App.vue

<script setup>
import { ref } from 'vue'
// 導? MyGoods 商品組件
import MyGoods from './components/MyGoods2.vue'
// 商品列表
const goodsList = ref([{id: '4001172',name: '稱?如意?搖咖啡磨?機咖啡?研磨機',price: 289,picture: 'https://cxk-1305128831.cos.ap-beijing.myqcloud.com/11-00.gif',},{id: '4001594',name: '?式?陶功夫茶組雙側把茶具禮盒裝',price: 288,picture: 'https://cxk-1305128831.cos.ap-beijing.myqcloud.com/11-00.gif',},{id: '4001009',name: '?制?泡茶盤正?形瀝?茶臺品茶盤',price: 109,picture: 'https://cxk-1305128831.cos.ap-beijing.myqcloud.com/11-00.gif',},{id: '4001874',name: '古法溫酒汝瓷酒具套裝?酒杯蓮花溫酒器',price: 488,picture: 'https://cxk-1305128831.cos.ap-beijing.myqcloud.com/11-00.gif',},{id: '4001649',name: '?師監制?泉?瓷茶葉罐',price: 139,picture: 'https://cxk-1305128831.cos.ap-beijing.myqcloud.com/11-00.gif',},{id: '3997185',name: '與眾不同的?感汝瓷?酒杯套組1壺4杯',price: 108,picture: 'https://cxk-1305128831.cos.ap-beijing.myqcloud.com/11-00.gif',},{id: '3997403',name: '??吹制更厚實?酒杯壺套裝6壺6杯',price: 100,picture: 'https://cxk-1305128831.cos.ap-beijing.myqcloud.com/11-00.gif',},{id: '3998274',name: '德國百年?藝?端?晶玻璃紅酒杯2?裝',price: 139,picture: 'https://cxk-1305128831.cos.ap-beijing.myqcloud.com/11-00.gif',},
])
// i: 下標,讓哪個對象的 price 減少
// price: 每次減少的價格
//提供修改的函數
const subPrice = (i, price) => {goodsList.value[i].price -= price
}
</script>
<template><div class="list"><MyGoodsv-for="(item, index) in goodsList":key="item.id":imgUrl="item.picture":title="item.name":price="item.price":idx="index"@ccc="subPrice"/></div>
</template>
<style lang="scss">
* {margin: 0;padding: 0;box-sizing: border-box;
}
.list {width: 1000px;margin: 0 auto;display: flex;flex-wrap: wrap;
}
</style>

MyGoods.vue

<script setup>
import { ref } from 'vue'
// 導? MyGoods 商品組件
import MyGoods from './components/MyGoods2.vue'
// 商品列表
const goodsList = ref([{id: '4001172',name: '稱?如意?搖咖啡磨?機咖啡?研磨機',price: 289,picture: 'https://cxk-1305128831.cos.ap-beijing.myqcloud.com/11-00.gif',},{id: '4001594',name: '?式?陶功夫茶組雙側把茶具禮盒裝',price: 288,picture: 'https://cxk-1305128831.cos.ap-beijing.myqcloud.com/11-00.gif',},{id: '4001009',name: '?制?泡茶盤正?形瀝?茶臺品茶盤',price: 109,picture: 'https://cxk-1305128831.cos.ap-beijing.myqcloud.com/11-00.gif',},{id: '4001874',name: '古法溫酒汝瓷酒具套裝?酒杯蓮花溫酒器',price: 488,picture: 'https://cxk-1305128831.cos.ap-beijing.myqcloud.com/11-00.gif',},{id: '4001649',name: '?師監制?泉?瓷茶葉罐',price: 139,picture: 'https://cxk-1305128831.cos.ap-beijing.myqcloud.com/11-00.gif',},{id: '3997185',name: '與眾不同的?感汝瓷?酒杯套組1壺4杯',price: 108,picture: 'https://cxk-1305128831.cos.ap-beijing.myqcloud.com/11-00.gif',},{id: '3997403',name: '??吹制更厚實?酒杯壺套裝6壺6杯',price: 100,picture: 'https://cxk-1305128831.cos.ap-beijing.myqcloud.com/11-00.gif',},{id: '3998274',name: '德國百年?藝?端?晶玻璃紅酒杯2?裝',price: 139,picture: 'https://cxk-1305128831.cos.ap-beijing.myqcloud.com/11-00.gif',},
])
// i: 下標,讓哪個對象的 price 減少
// price: 每次減少的價格
//提供修改的函數
const subPrice = (i, price) => {goodsList.value[i].price -= price
}
</script>
<template><div class="list"><MyGoodsv-for="(item, index) in goodsList":key="item.id":imgUrl="item.picture":title="item.name":price="item.price":idx="index"@ccc="subPrice"/></div>
</template>
<style lang="scss">
* {margin: 0;padding: 0;box-sizing: border-box;
}
.list {width: 1000px;margin: 0 auto;display: flex;flex-wrap: wrap;
}
</style>

4.祖先傳后代

5.任意兩個組件通信

五.props校驗

作用:

我們前面使用?props 傳輸數據的時候,參數的格式傳輸錯誤,在控制臺不會顯示,我們添加了props校驗之后,就會出現報錯了,幫助開發者,快速發現錯誤。

完整語法格式:

defineProps({屬性名: {type: 類型, // Number String Boolean ...required: true, // 是否必填default: 默認值, // 默認值// value: ?傳?的值validator (value) {// ?定義校驗邏輯return 布爾值}}
})

代碼示例:里面有一種簡單寫法一種完整寫法

App.vue 文件代碼:

<script setup>
import { ref } from 'vue'
import MyProgress from './components/MyProgress.vue'
const width = ref(20)
</script>
<template><div class="app"><MyProgress :width="width" /><MyProgress :width="80" /></div>
</template>
<style></style>

MyProgress.vue 文件代碼:

<script setup>
// 不驗證的寫法
// defineProps(['width'])// 驗證的簡易寫法
// 屬性:類型
// defineProps({
//   width: Number,
// })// 驗證的完整寫法
defineProps({width: {type: Number,// required: true  // 寫了這個default就不會生效了default: 50,validator: (value) => {if (value >= 0 && value <= 100) {return true} else {console.error('The width prop must be between 0 and 100')return false}},},
})
</script>
<template><div class="my-progress"><div class="inner" :style="{ width: width + '%' }"><span>{{ width }}%</span></div></div>
</template>
<style scoped>
.my-progress {height: 26px;width: 400px;border-radius: 15px;background-color: #272425;border: 3px solid #272425;box-sizing: border-box;margin-bottom: 30px;
}
.inner {position: relative;background: #379bff;border-radius: 15px;height: 25px;box-sizing: border-box;left: -3px;top: -2px;
}
.inner span {position: absolute;right: -30px;top: 26px;
}
</style>

六.v-model進階

1.原理

v-model本質上是?個語法糖。

例如應?在輸?框上,就是 value 屬性 和 input 事件的合寫

<script setup>import { ref } from 'vue'const msg = ref('')
</script>
<template><p>{{ msg }}</p><input type="text" v-model="msg"><input type="text" :value="msg" @input="msg = $event.target.value" >
</template>

?$event.target.value 意思是獲取當前輸入框的內容。

2.v-model作用在組件上

作用:

實現父組件和子組件數據的雙向綁定

代碼實現:

App.vue 的代碼實現

<script setup>
import { ref } from 'vue'
import BitSelect from './components/BitSelect.vue'
const activeId = ref('222')
</script>
<template><!-- 組件標簽上的 $event 指的是 emit 傳遞來的參數 --><BitSelect :modelValue="activeId" @update:modelValue="activeId = $event" /><!--       自定義屬性              自定義事件 --><!-- 簡化寫法 --><!-- <BitSelect v-model="activeId" /> -->
</template>

?BitSelect.vue

<script setup>
// 接收 modelValue 是父傳子這里不能直接改,所以下面不能直接用 v-model
const props = defineProps({modelValue: {type: String,default: '',},
})
// 獲取 emit
const emit = defineEmits()
</script>
<template><!-- 原生標簽上的 $event 就是事件對象 --><!-- $event.target: select 原生DOM --><!-- $event.target.value: 選中的 option 的 value --><select :value="props.modelValue" @change="emit('update:modelValue', $event.target.value)"><option value="111">北京</option><option value="222">上海</option><option value="333">深圳</option><option value="444">杭州</option><option value="555">蘇州</option></select>
</template>

流程圖

簡化:

App.vue 文件的代碼

<script setup>
import { ref } from 'vue'
import BitSelect from './components/BitSelect.vue'
const activeId = ref('222')
</script>
<template><BitSelect v-model="activeId" />
</template>

??BitSelect.vue

<script setup>
// 子組件直接通過 defineModel() 來接收父組件傳遞的v-model值
// defineModel() 的返回值是一個 ref 數據,并且可以在子組件中直接操作這個 ref 數據,
// 并且可以在子組件中直接操作這個 ref 數據,會引起父組件的數據的同步更新
const model = defineModel()
</script>
<template><select v-model="model"><option value="111">北京</option><option value="222">上海</option><option value="333">深圳</option><option value="444">杭州</option><option value="555">蘇州</option></select>
</template>

這里的defineModel是個語法糖。?

七.ref屬性

1.ref是什么

是作用在標簽上的屬性,是 vue 新增的,原生不具備這個屬性的。

2.作用:

用來獲取原生 DOM 或 組件實例(進而調用組件提供的方法)。

3.獲取原生DOM

<!-- @format -->
<script setup>
import { onMounted, ref } from 'vue'// 準備 ref 響應式數據
const divRef = ref(null)// 組件掛載后
onMounted(() => {// 獲取原生 div// console.log(divRef.value)/// <div></div>// 以設置 div 字體顏色為例(DOM操作的代碼):divRef.value.style.color = 'red'
})
</script><template><!-- 給目標元素添加ref屬性并綁定數據 --><div ref="divRef">Some Text...</div>
</template><style scoped></style>

這個獲取是直接從自己這個組件上獲取,比原本從整棵DOM樹上獲取會快一點?

4.使用組件實例調用組件暴露的方法和屬性(defineExpose)

App.vue 文件代碼

<script setup>
import { ref } from 'vue'
import MyForm from './components/MyForm.vue'
const formRef = ref(null)
// 登錄
const onLogin = () => {console.log(formRef.value.ccc)console.log(formRef.value.validate())// 進?校驗// if (formRef.value.validate()) {//   console.log('ok')// } else {//   console.log('error')// }
}
</script>
<template><MyForm ref="formRef" /><button @click="onLogin">登 錄</button>
</template>
<style>
#app {width: 300px;margin: 100px auto;
}
</style>

MyForm.vue 文件代碼

<script setup>
// 表單校驗
const validate = () => {return Math.random() > 0.5 ? true : false
}
// 暴漏給組件, ?的是?組件可以通過 ref 可以拿到?組件的?法
defineExpose({ccc: 100,validate,
})
</script>
<template><div class="login-box">賬?:<input type="text" /><br /><br />密碼:<input type="password" /><br /><br /></div>
</template>

八.nextTick

1.作用

當數據變了,想獲取更新后的DOM,需要把代碼寫在這個方法的回調中。直接獲取是獲取不到的,因為DOM操作是異步的,獲取DOM會在更新DOM之前執行。

2.代碼案例

<script setup>
import { nextTick, ref } from 'vue'// 控制是否顯示輸入框
const isShowEdit = ref(false)// 點擊編輯按鈕
const onEdit = () => {isShowEdit.value = true// 問題:當數據變了,發現獲取DOM拿不到的// 原因:在 vue3 中,當數據變了,DOM的更新是異步的;// 也就是說,數據變了,想立即獲取最新的DOM是拿不到的,此時DOM并沒有更新// console.log(inputRef.value) // null// 解決:利用 nextTick() 這個方法,因為在這個方法的回調中,DOM更新完畢了nextTick(() => {inputRef.value.focus()})
}const inputRef = ref(null)
</script><template><div class="box"><h3>大標題</h3><button @click="onEdit">編輯</button></div><div v-if="isShowEdit"><input type="text" ref="inputRef" /><button>確認</button></div>
</template>
<style scoped>
.box {display: flex;justify-content: space-between;align-items: center;width: 200px;height: 40px;
}
</style>

九.自定義指令

1.作用

封裝?段 公共的DOM操作 代碼,便于復?。

2.基本使用?

①語法

注冊

// main.js 中
app.directive('指令名', {// 元素掛載后(成為真實DOM) ?動觸發?次?動執?mounted(el) {// el: 指令所在的DOM元素}
}

使用

<p v-指令名></p>
②代碼示例

main.js 文件代碼

// 按需導入 createApp 函數
import { createApp } from 'vue'
// 導入 App.vue
import App from './App.vue'
// 創建應用
const app = createApp(App)// 定義指令
app.directive('jujiao', {// 指令所在的標簽插入到真實DOM中自動執行一次mounted(el) {// el就是指令所在的DOM元素, 拿到 el 了,// 就可以對 el 做任何原生DOM操作// console.log('mounted', el)el.focus()}
})
// 指定渲染的位置
app.mount('#app')

App.vue 文件代碼

<template><input type="text" v-jujiao />
</template><script setup></script><style scoped></style>

3.綁定數據

①語法

1.在綁定指令時,可以通過“等號”的形式為指令 綁定 具體的參數值

<div v-color="colorStr">Some Text</div>

?2.通過 binding.value 可以拿到指令值,指令值修改會 觸發 updated 鉤?

app.directive('指令名', {// 掛載后?動觸發?次mounted(el, binding) { },// 數據更新, 每次都會執?updated(el, binding) { }
})
②代碼示例

main.js 文件代碼

// 按需導入 createApp 函數
import { createApp } from 'vue'
// 導入 App.vue
import App from './App.vue'
// 創建應用
const app = createApp(App)app.directive('color', {// 指令所在的DOM元素變成真實DOM了,會自動執行一次;// 換句話說,當指令所在表達式的值變了,該函數不會再次執行了mounted(el, binding) {// el: 指令所在元素// binding: 指令綁定的信息對象,binding.value 獲取指令表達式的結果el.style.color = binding.valueconsole.log('1-mounted')},// 每次指令綁定表達式的值變了,都會執行一次updated(el, binding) {el.style.color = binding.valueconsole.log('2-updated')}
})// 指定渲染的位置
app.mount('#app')

App.vue 文件代碼

<script setup>import { ref } from 'vue'// 提供的顏色響應式數據const colorStr = ref('red')
</script><template><!-- 使用自定義指令,并綁定表達式 --><div v-color="colorStr">Some Text</div>
</template><style scoped></style>

main.js 的簡化寫法?

對于自定義指令來說,一個很常見的情況是僅僅需要在 mounted 和 updated 上實現相同的行為。這種情況我們可以直接用一個函數的定義指令,如下所示:

app.directive('color', (el, binding) => {// 這會在 `mounted` 和 `updated` 時都調?el.style.color = binding.value
}

十.插槽

1.作用

讓組件內部的?些 結構 ?持 ?定義

2.默認插槽

①基本語法

1. 組件內需要定制的結構部分,改? <slot></slot> 占位

2. 使?組件時, <MyDialog></MyDialog>寫成雙標簽 , 包裹結構, 傳?替換slot

②代碼示例

MyDialog.vue 文件代碼

<script setup></script>
<template><div class="dialog"><div class="dialog-header"><h3>友情提?</h3><span class="close">?</span></div><div class="dialog-content"><!-- 1. 在組件內標簽不確定位置用 slot 組件占位 --><slot> </slot></div><div class="dialog-footer"><button>取消</button><button>確認</button></div></div>
</template>
<style scoped>
* {margin: 0;padding: 0;
}
.dialog {width: 470px;height: 230px;padding: 0 25px;background-color: #ffffff;margin: 40px auto;border-radius: 5px;
}
.dialog-header {height: 70px;line-height: 70px;font-size: 20px;border-bottom: 1px solid #ccc;position: relative;
}
.dialog-header .close {position: absolute;right: 0px;top: 0px;cursor: pointer;
}
.dialog-content {height: 80px;font-size: 18px;padding: 15px 0;
}
.dialog-footer {display: flex;justify-content: flex-end;
}
.dialog-footer button {width: 65px;height: 35px;background-color: #ffffff;border: 1px solid #e1e3e9;cursor: pointer;outline: none;margin-left: 10px;border-radius: 3px;
}
.dialog-footer button:last-child {background-color: #007acc;color: #fff;
}
</style>

App.vue 文件代碼

<script setup>
import MyDialog from './components/MyDialog.vue'
</script>
<template><!-- 2. 在使用組件的時候,給組件傳入想展示的結構,從而替換掉占位的 slot 組件 --><MyDialog> 你取認要刪除嗎 </MyDialog><MyDialog><span>我已經刪除了</span></MyDialog>
</template>
<style scoped>
body {background-color: #b3b3b3;
}
</style>

3.插槽默認值

通過插槽完成了內容的定制,傳什么顯?什么, 但是如果不傳,則是空?,如果我們需要有默認值在, <slot></slot> 標簽里面寫默認值就可以了,比較簡單這里就不代碼演示了。

4.具名插槽

①作用

一個組件有多個位置需要使用插槽是使用具名插槽。

②語法

?? 多個slot使?name屬性區分名字

? template配合v-slot:名字 來分發對應標簽

? v-slot寫起來太?,vue給我們提供?個簡單寫法 v-slot: 直接簡寫為 #

③代碼示例?

MyDialog.vue 文件代碼

<script setup></script>
<template><div class="dialog"><div class="dialog-header"><slot name="header"><h3>溫馨提?</h3></slot><span class="close">?</span></div><div class="dialog-content"><slot>我是主體內容</slot></div><div class="dialog-footer"><slot name="footer"><button>取消</button><button>確認</button></slot></div></div>
</template>
<style>
* {margin: 0;padding: 0;
}
.dialog {width: 470px;height: 230px;padding: 0 25px;background-color: #ffffff;margin: 40px auto;border-radius: 5px;
}
.dialog-header {height: 70px;line-height: 70px;font-size: 20px;border-bottom: 1px solid #ccc;position: relative;
}
.dialog-header .close {position: absolute;right: 0px;top: 0px;cursor: pointer;
}
.dialog-content {height: 80px;font-size: 18px;padding: 15px 0;
}
.dialog-footer {display: flex;justify-content: flex-end;
}
.dialog-footer button {width: 65px;height: 35px;background-color: #ffffff;border: 1px solid #e1e3e9;cursor: pointer;outline: none;margin-left: 10px;border-radius: 3px;
}
.dialog-footer button:last-child {background-color: #007acc;color: #fff;
}
</style>

App.vue 文件代碼

<script setup>
import MyDialog from './components/MyDialog.vue'
</script>
<template><!-- 1. 不傳、都顯?插槽默認內容 --><MyDialog /><!-- 2. 傳了 --><MyDialog><template v-slot:header><h3>友情提?</h3></template><template v-slot:default> 請輸?正確?機號 </template><template v-slot:footer><button>關閉</button></template></MyDialog><!-- 3. 傳了 --><MyDialog><template v-slot:header><h3>警告</h3></template><template v-slot:default> 你確認要退出么? </template><template v-slot:footer><button>確認</button><button>取消</button></template></MyDialog>
</template>
<style>
body {background-color: #b3b3b3;
}
</style>

5.作用域插槽

①作用

帶數據的插槽, 可以讓組件功能更強?、更靈活、復?性更?; ? slot 占位的同時, 還可以給 slot 綁定數據, 將來使?組件時, 不僅可以傳內容, 還能使? slot 帶來的數據。

②代碼示例

MyDialog.vue 文件代碼

<script setup></script><template><div class="dialog"><div class="dialog-header"><slot name="header"></slot><span class="close">×</span></div><div class="dialog-content"><slot name="body" account="xiaobit" password="123456"></slot></div><div class="dialog-footer"><button>取消</button><button>確認</button></div></div>
</template><style>
* {margin: 0;padding: 0;
}
.dialog {width: 470px;height: 230px;padding: 0 25px;background-color: #ffffff;margin: 40px auto;border-radius: 5px;
}
.dialog-header {height: 70px;line-height: 70px;font-size: 20px;border-bottom: 1px solid #ccc;position: relative;
}
.dialog-header .close {position: absolute;right: 0px;top: 0px;cursor: pointer;
}
.dialog-content {height: 80px;font-size: 18px;padding: 15px 0;
}
.dialog-footer {display: flex;justify-content: flex-end;
}
.dialog-footer button {width: 65px;height: 35px;background-color: #ffffff;border: 1px solid #e1e3e9;cursor: pointer;outline: none;margin-left: 10px;border-radius: 3px;
}
.dialog-footer button:last-child {background-color: #007acc;color: #fff;
}
</style>

App.vue 文件代碼

<script setup>
import MyDialog from './components/MyDialog.vue'
</script><template><MyDialog><template #header="obj"><h4>登錄</h4></template><template #body="obj"><!-- 默認接收的數據 obj 是個空對象 --><p>{{ obj }}</p>賬號:<input type="text" v-model="obj.account" /><br /><br />密碼:<input type="password" v-model="obj.password" /><br /><br /></template></MyDialog>
</template><style scoped></style>
③代碼工作流程圖

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/88157.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/88157.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/88157.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

OS學習筆記

《幾個基本知識點》 一、2的冪 1024210 51229 25628 12827 6426 3225 1624 823 422 221 K210 G220 M230 T240 P250 E260 Z270 Y280 R290 Q2100 二、常用的ASCII碼 ‘1’0x31 ‘A’0x41 ‘a’0x61 空格0x20 換行0x0A 回車0x0D 三、存儲器層次中的典型速度 CPU/寄存器&#xff1a…

嵌入式學習筆記-MCU階段-DAY01

恭喜大家完成了C語言的學習&#xff0c;現在咱們來到咱們的硬件MCU階段&#xff0c;咱們這里的工程用的是keil&#xff0c;環境搭建不再贅述&#xff0c;希望大家在這一階段仍然學的愉快 1.資料部分 用的最多的就是STM32f103的手冊&#xff0c;搭配STM32F103ZET6的開發板 2.概…

three案例 Three.js波紋效果演示

波紋效果&#xff0c;在智慧城市可視化開發中經常用到&#xff0c;這里分享一個比較好玩的案例 以下是詳細的步驟&#xff1a; 初始化部分&#xff1a;設置 Three.js 環境&#xff0c;包括場景、相機、渲染器和控制器 幾何體和紋理&#xff1a;創建平面幾何體并加載波紋紋理 著…

Flutter-詳解布局

上一章我們詳細的學習了 Flutter 中的Widget&#xff0c;這一章我們將要學習 Flutter 的布局&#xff0c; 在上一章我們了解到了&#xff1a;Everything is a widget&#xff0c;在 Flutter 中幾乎所有的對象都是一個 Widget &#xff0c;當然也包括布局&#xff0c;Flutter 的…

EPLAN 電氣制圖:建立自己的部件庫,添加部件-加SQL Server安裝教程(三)上

在智能電氣設計領域&#xff0c;EPLAN 作為主流的設計軟件&#xff0c;其部件庫的完善程度直接影響項目設計的效率與質量。本文將從實際操作出發&#xff0c;詳細講解如何在 EPLAN 中建立專屬部件庫并添加部件&#xff0c;為電氣設計奠定堅實基礎。一、部件庫&#xff1a;電氣設…

靜態路由進階實戰全解

一、項目背景二、項目拓撲圖三、設備命名與IP地址規劃設備名接口編號IP地址規劃R1GE0/0192.168.1.1/24GE0/1172.16.1.1/24R2GE0/0192.168.1.2/24GE0/1192.168.2.2/24R3GE0/0192.168.2.3/24GE0/1192.168.3.3/24GE0/2192.168.4.3/24R4GE0/0192.168.3.4/24GE0/1192.168.4.4/24GE0/…

stm32hal模塊驅動(3)ssd1305 oled驅動

SD1305 OLED 驅動芯片詳細介紹SSD1305 是 Solomon Systech 公司生產的一款 OLED 顯示控制器/驅動器&#xff0c;專為 128x64 或 128x32 點陣的 OLED 顯示屏設計。下面我將從多個方面詳細介紹這款驅動芯片。一、SSD1305 基本特性顯示分辨率&#xff1a;最大支持 128 segments 6…

安全為先:如何在 Python 中安全處理數據庫連接與敏感信息

安全為先:如何在 Python 中安全處理數據庫連接與敏感信息 引言:Python 與安全的數據庫交互 自 1991 年誕生以來,Python 憑借其簡潔優雅的語法和強大的生態系統,成為 Web 開發、數據科學、人工智能和數據庫交互的首選語言。作為“膠水語言”,Python 不僅讓開發者能夠快速…

服務器經常出現藍屏是什么原因導致的?如何排查和修復?

服務器出現藍屏&#xff08;BSOD&#xff0c;Blue Screen of Death&#xff09;是一個嚴重的問題&#xff0c;通常表明系統內核或硬件發生了不可恢復的錯誤。藍屏不僅會導致服務器宕機&#xff0c;還可能對業務運行造成重大影響。要有效解決藍屏問題&#xff0c;需要先找到根本…

為什么elementui的<el-table-column label=“名稱“ prop=“name“ label不用寫成:label

在 Vue.js 中&#xff0c;label 和 prop 是 el-table-column 組件的普通屬性&#xff0c;而不是動態綁定的表達式。因此&#xff0c;不需要使用 : 來綁定它們。 1. Vue.js 中的屬性綁定 在 Vue.js 中&#xff0c;屬性綁定有兩種方式&#xff1a; 靜態屬性綁定&#xff1a;直接寫…

分布式光纖傳感:為儲能安全保駕護航

儲能系統是指一種能夠將電能、化學能、動能等形式的能量進行轉化、儲存和釋放的裝置&#xff0c;廣泛應用于可再生能源發電、智能電網、電動車等領域。儲能行業這幾年得到了穩步發展&#xff0c;受到政府機構、行業協會、大型能源企業、電網公司、系統集成商、檢測認證機構等業…

從歷史航拍圖像中去除陰影

在光學遙感中&#xff0c;陰影是影響土地覆蓋制圖精度和分辨率的一個因素&#xff0c;無論是歷史影像&#xff08;黑白影像&#xff09;還是近期影像&#xff08;全彩影像&#xff09;。陰影的產生取決于太陽光照&#xff08;太陽方位角和天頂角&#xff09;、相機視點&#xf…

UE material advance 學習筆記

如何體現輪胎速度的快速感&#xff1a;就是增加一個radial blur&#xff0c;會讓視覺效果感覺輪胎已經轉冒煙了&#xff0c;但是上面兩個輪胎的轉速其實是相同的這種磨砂的感覺&#xff0c;可以用上ditherAA來實現只看法線這一塊&#xff0c;ditherAA就是讓他的表面顏色有大量的…

Vue--2、Vue2 項目配置與組件化開發

一、Vue2 項目環境搭建1. 環境準備安裝 Node.js&#xff1a;推薦使用 nvm 管理多版本 Node# 安裝Node 16.20.2 nvm install 16.20.2 # 切換至指定版本 nvm use 16.20.2 # 驗證安裝 node -v && npm -v安裝 Vue CLI 腳手架&#xff1a;# 國內鏡像源安裝 npm install --re…

虛幻基礎:函數的返回節點

能幫到你的話&#xff0c;就給個贊吧 &#x1f618; 文章目錄函數的返回節點&#xff1a;返回執行后的值返回執行后的值若不執行第一次 返回參數的默認值第二次 返回上一次執行值示例函數的返回節點&#xff1a;返回執行后的值 返回執行后的值 若不執行 第一次 返回參數的默…

FFmpeg 升級指北

近期我參與了部門底層庫依賴的 FFmpeg 從 3.4 升級至 7.0.2 的工作&#xff0c;在此分享一些經驗和遇到的 API 變動。 將 FFmpeg 升級到高版本后&#xff0c;編譯過程中遇到大量報錯是常態。這些錯誤通常源于 API 接口變更或結構體字段調整。此時不必驚慌&#xff0c;核心解決…

RISCV Linux 虛擬內存精講系列三 -- setup_vm()

在 Linux 使用虛擬地址前&#xff0c;需要先配置頁表&#xff0c;這就是 setup_vm() 的作用。然而&#xff0c;Linux 的頁表配置&#xff0c;并不是一次過完成的&#xff0c;分了兩個階段&#xff0c;如下&#xff1a;在 setup_vm() 中&#xff0c;主要初始化了&#xff1a;1. …

創客匠人:解析創始人 IP 打造的底層邏輯與知識變現路徑

在數字經濟時代&#xff0c;創始人 IP 的價值被不斷放大&#xff0c;而知識變現作為 IP 商業閉環的核心環節&#xff0c;正成為無數創業者探索的方向。創客匠人深耕知識付費領域多年&#xff0c;見證了大量創始人從 0 到 1 打造 IP 并實現變現的全過程&#xff0c;其背后的邏輯…

Visual Studio 2022 MFC Dialog 添加Toolbar及Tips提示

主要步驟&#xff1a;在主框架類中添加消息處理函數聲明在 OnCreate 函數中啟用工具欄提示在消息映射中注冊 TTN_NEEDTEXT 消息使用 OnToolTipText 函數實現自定義提示文本1.在主程序的.h文件中加入afx_msg BOOL OnToolTipText(UINT id, NMHDR* pNMHDR, LRESULT* pResult); 2.在…

2025Q2大模型更新匯總(大語言模型篇)

摘要 2025年Q2大語言模型更新匯總&#xff1a; Qwen3&#xff0c;Deepseek-R1-0528&#xff0c;Doubao-Seed-1.6, MiniMax-M1, GPT4.1/O3/O4&#xff0c;Claude4/Gemini2.5 Qwen3 ? 開源MOE模型&#xff0c; ? MOE模型&#xff1a;Qwen3-235B-A22B&#xff0c;Qwen3-30B-…