目錄
vue2
基礎屬性
組件通信
全局狀態管理 vueX
路由
路由守衛
vue3
基礎屬性
組件通信
全局狀態管理 Pinia
路由
路由守衛
vue2、vue3生命周期
setup
vue2
基礎屬性
data:用于定義組件的初始數據,必須是一個函數,返回一個對象,每個組件實例都會有自己的數據對象,避免組件之間數據相互影響。
props:用于接收父組件傳遞的數據,必須是一個數組或對象,數組中的每個元素是一個字符串,表示接收的屬性名,對象中的每個屬性表示接收的屬性名和屬性值的類型。
methods:用于定義組件的方法,每個方法都是一個函數,可以在組件中通過 this 訪問。
watch:用于監聽數據的變化,當數據發生變化時,執行相應的回調函數,可以監聽單個數據或多個數據的變化。
computed:用于計算屬性,根據已有的數據計算出新的數據,可以監聽多個數據的變化,只有當依賴的數據發生變化時才會重新計算。
created:在實例創建完成后立即執行,可以在這個鉤子函數中進行數據初始化、事件監聽等操作。
computed計算屬性
watch
基本使用
watch: {name: { //這里是要監聽的變量名handler(newValue, oldValue) { //這里的第一個參數是改變后的值,第二個參數是原來的值console.log('改后的值是:' + newValue)console.log('原來的值是:' + oldValue)}}}
簡寫
watch: {name(newValue, oldValue) { //這里的第一個參數是改變后的值,第二個參數是原來的值console.log('改后的值是:' + newValue)console.log('原來的值是:' + oldValue)}}
immediate:就是當值第一次綁定時,不會執行監聽函數,只有值發生改變時才會執行。如果我們需要在最初綁定值的時候也執行函數,需要用到immediate屬性;
deep:當需要監聽一個對象的改變時,普通的watch方法無法監聽到對象內部屬性的改變,此時就需要deep屬性對對象進行深度監聽,數組字符串一般不需要。
watch: {name: {handler(newValue, oldValue) {//這里的第一個參數是改變后的值,第二個參數是原來的值console.log('改后的值是:' + newValue)console.log('原來的值是:' + oldValue)},immediate: true,deep:true}}
組件通信
父傳子
子傳父
非父子通信 eventBus事件總線(兄弟組件)
?src/utils/eventBus.js
import Vue from 'vue';
export const EventBus = new Vue();
<template><button @click="sendData">發送數據到組件 B</button>
</template><script>
import { EventBus } from '@/utils/eventBus';export default {methods: {sendData() {EventBus.$emit('dataEvent', '來自組件 A 的數據');}}
};
</script>
<template><p>收到的數據:{{ receivedData }}</p>
</template><script>
import { EventBus } from '@/utils/eventBus';export default {data() {return { receivedData: '' };},created() {EventBus.$on('dataEvent', data => {this.receivedData = data;});},beforeDestroy() {EventBus.$off('dataEvent');}
};
</script>
組件通信——非父子通信 Provide Inject(跨層級組件)
<template><ChildComponent />
</template><script>
export default {provide() {return {sharedMessage: 'Hello from Provide!'};}
};
</script>
<template><p>收到的數據:{{ sharedMessage }}</p>
</template><script>
export default {inject: ['sharedMessage']
};
</script>
組件通信——非父子通信?$attrs ?$listeners
官方文檔介紹:包含了父作用域不作為prop被識別(且獲取)的attribute綁定(class和style除外)。當一個組件沒有生命任何prop時,這里會包含所有父作用域的綁定(class和style除外),并且可以通過v-bind="$attrs"傳入內部組件–在創建高級別的組件時非常有用。
通俗地來說就是如果從父組件傳過來的值,沒有在子組件中被接收,那么這些值就會被存在$attrs對象中。
//Father.vue
<template><div class="father"><span>父親</span><Son :message="message" :age="18"></Son></div>
</template><script>
import Son from "../components/Son.vue";
export default {data() {return {message: "父組件傳過來的值",age: 18,};},components: {Son,},
};
</script>//Son.vue
<template><div class="son"><span>兒子</span><GrandSon v-bind="$attrs"></GrandSon></div>
</template><script>
import GrandSon from "../components/GrandSon.vue";
export default {components: {GrandSon,},created() {console.log("son", this.$attrs);},
};//GrandSon.vue
<template><div class="grandson"><span>孫子</span><div>{{ $attrs.message }}</div></div>
</template><script>
export default {created() {console.log("grandson", this.$attrs);},
};
</script>
組件通信——ref $refs
?引用信息會注冊在父組件的$ref對象上? ?vue2/vue3 ref組件通信
//父
<template><div id="app"><TodoItem ref="msg"></TodoItem><p ref="dom"></p></div>
</template><script>
import TodoItem from './components/so.vue'export default {name: 'App',components: {TodoItem},mounted() {console.log(this.$refs)// 通過這種方法給子組件傳遞數據this.$refs.msg.getmsg("我是tc") // this.$refs.msg指向的是子組件的實例},
}
</script>//子
<template><div class="so"><p>{{ msg }}</p></div>
</template><script>
export default {name: "todo-item",data() {return {msg: ''}},methods: {getmsg(s) {this.msg = s}}
}
</script>
全局狀態管理 vueX
vueX詳解(1)
vueX詳解(2)
路由
路由詳解
路由守衛
路由守衛詳解
vue3
基礎屬性
import { computed, ref } from 'vue';
export default {setup() {const count = ref(0);// 定義一個計算屬性const doubledCount = computed(() => count.value * 2);return {count,doubledCount};}
};
const fullName = computed({// getterget() {return firstName.value + ' ' + lastName.value},// setterset(newValue) {// 注意:我們這里使用的是解構賦值語法[firstName.value, lastName.value] = newValue.split(' ')}
})
watch
//ref
<script setup lang="ts">
import { watch, ref } from 'vue'
const sum=ref(1);
// New: 新值 | Old: 老值
watch(sum,(New, Old)=>{console.log(`新值:${New} ——— 老值:${Old}`)
})
</script>
//reactive
<script setup lang="ts">import { watch,reactive} from 'vue'// 響應式變量const sum = reactive({value: 1})// watch是一個函數// 第一個參數: 要監聽的響應式變量(數據源)// 第二個參數:執行的回調函數// 第三個參數: 配置(例如deep深度監聽/immediate是否立即監聽等)// 注意:當監聽一個對象時,第一個參數數據源必須是函數且返回一個值即 "() => 對象.要監聽的屬性"watch(() => sum.value, (New, Old) => {console.log(`新值:${New} ——— 老值:${Old}`)}, { immediate: true, deep:ture })
</script>
watchEffect
- 不需要手動傳入依賴(不用指定監聽對象)
- 無法獲取原始值,只能獲取更新后的值
- 立即執行(在
onMounted
前調用)- 一些異步操作放里面更加的合適
const count = ref(0)
watchEffect(() => {console.log(count.value)
})
const stop = watchEffect(() => {/* ... */
})
// 停止監聽
stop()
副作用清除??做一些異步請求連發限制或取消請求的操作,保證請求數據的完整和準確性。
watchEffect(async (onCleanup) => {const { response, cancel } = doAsyncWork(id.value)// `cancel` 會在 `id` 更改時調用// 以便取消之前// 未完成的請求onCleanup(cancel)data.value = await response
})
組件通信
父傳子
<Child info="我愛祖國" :money="money"></Child>
子組件獲取父組件傳遞數據:方式1
let props = defineProps({money:{type:Number,default:0
}})子組件獲取父組件傳遞數據:方式2
let props = defineProps(["info",'money']);
子傳父
<Event2 @xxx="handler3"></Event2>
<script setup lang="ts">
let $emit = defineEmits(["xxx"]);
const handler = () => {$emit("xxx", "法拉利", "茅臺");
};
</script>
v-model
<template><child v-model:name="name"></child>
</template><script setup>
import { ref } from 'vue'
import Child from './Child.vue'const name = ref('XXX')
</script>
<template><input :value="name" @input="updateName" />
</template><script setup>
import { defineProps, defineEmits } from 'vue'const props = defineProps(['name'])
const emit = defineEmits(['update:name'])const updateName = (e) => {emit('update:name', e.target.value)
}
</script>
依賴注入 (Provide/Inject)
<script setup>
import { provide, ref } from 'vue'const themeColor = ref('blue')
provide('theme', themeColor)
</script>
<script setup>
import { inject } from 'vue'const theme = inject('theme')
console.log(theme.value) // 'blue'
</script>
ref
<template><TodoItem :ref="(el) => child = el"></TodoItem><p ref="dom"></p>
</template><script>
import TodoItem from './components/so'
import { ref, onMounted } from 'vue'export default {name: 'App',components: {TodoItem}
}
</script><script setup>const child = ref(null)// const msg = ref()const dom = ref()onMounted(() => {console.log(child.value.getmsg("我是tc"))// msg.value.getmsg("我是tc")dom.value.innerHTML = "我是一個普通的DOM元素"})
</script>
<template><div class="so"><p>{{ msg }}</p></div></template><script setup>
import { ref, defineExpose } from 'vue'const msg = ref("")
const getmsg = (s) => {msg.value = s
}
// 想要父組件可以獲取到需要使用defineExpose向父組件暴露
defineExpose({getmsg})
</script>
事件總線
vue3中移除了事件總線,可以借助于第三方工具來完成,Vue官方推薦 mitt 或 tiny-emitter?
全局狀態管理 Pinia
Pinia詳解
路由
路由詳解
路由守衛
vue2、vue3路由區別及原理
vue3路由守衛詳解
vue2、vue3生命周期
setup
setup() 鉤子是在組件中使用組合式 API 的入口
vue3 setup