建立執行個體
入口檔案
./src/main.js
// 引入工廠函數,而非Vue構造函數
import {createApp} from 'vue'
import App from './App.vue'
// 建立應用執行個體對象,比Vue執行個體輕
const app = createApp(App)
// 挂載
app.mount('#app')
複制
setup元件選項
vue2中的資料,計算屬性,方法,生命周期鈎子等都可以在setup函數中構造
setup函數傳回:
- 對象,包含模闆中可以使用的屬性,方法
<template>
<!-- 可以支援多個根标簽 -->
<h1>{{ msg }}</h1>
<button @click="onClick">click</button>
</template>
<script>
export default {
name: 'HelloWorld',
setup() {
// 非響應式變量
let msg = props.props1 || 'hello world';
function onClick() {
alert(msg)
}
return {
msg,
onClick
}
}
}
</script>
複制
注,預設setup傳回對象中的變量是非響應式變量,使用ref/reactive建立響應式變量
2. 渲染函數
./component/HelloWorld.vue
<script>
// 引入渲染函數
import {h} from 'vue'
export default {
setup(){
return ()=> { return h('h1','hello') }
}
}
</script>
複制
- data,methods,computed可以通路setup中的屬性方法
- setup無法通路data,methods,computed
- 存在重名成員時,setup優先
setup執行時機
beforeCreate之前執行,this為undefined
setup參數
props: ['prop1'],
// vue3需要暴露可用事件,否則會報警告
emits: ['my-event'],
setup(props, context) {
// 取props屬性
props.prop1
// 取props沒定義的傳入屬性,傳入props沒有定義的屬性會報警告,相當于vue2中的this.$attrs
context.attrs.prop2
// 觸發事件,相當于vue2中的this.$emit
context.emit('my-event',{data:1})
// 取所有傳入slots,相當于vue2中的this.$slots
context.slots
}
複制
ref響應式變量
<template>
<!-- 插值不用寫.value -->
<h2>{{ counter }}</h2>
<button @click="increase">increase</button>
</template>
<script>
import {ref} from "vue";
export default {
name: 'HelloWorld',
setup() {
// 響應式變量,建立引用對象RefImpl
let counter = ref(0)
function increase() {
// 操作引用對象值
counter.value++
}
return {
counter,
increase
}
}
}
</script>
複制
reactive響應式對象
注,基本資料類型不要使用reactive
import {ref,reactive} from "vue";
...
setup() {
...
// 建立代理對象Proxy
const person = reactive({name:'psr',age:18}),
person1 = reactive({name:'zdd',age:18}
// 可以直接添加删除響應式屬性,差別于vue2中的vc.$set vc.$delete方法
person.sex='男'
// 建立響應式數組
const persons = reactive([]);
persons.push(person)
// 索引修改也能支援響應式
persons[0]=person1
...
}
複制
ref vs reactive
- ref一般用于定義基本類型資料(通過defineProperty實作響應式)
- reactive一般用于定義對象或數組類型資料(通過Proxy,Reflect實作響應式)
- 使用ref定義對象或數組類型資料,value會自動使用reactive轉為代理對象
- 腳本操作ref資料需要.value
computed計算屬性
import {reactive, computed} from "vue"
...
setup() {
...
let person = reactive({
name: 'psr',
firstName: 'zhou',
lastName: 'dd',
// 簡寫
fullName: computed(() => {
return person.firstName + ' - ' + person.lastName
}),
age: '18'
})
// 完整
let fullName = computed({
get() {
return person.firstName + ' - ' + person.lastName
},
set(value) {
const nameArr = value.split(' - ')
person.firstName = nameArr[0]
person.lastName = nameArr[1]
}
})
...
return {
...
person,
fullName,
...
}
}
複制
watch資料監視
import {watch} from 'vue'
複制
-
監視ref
注,如果ref包裝的是對象,需要監視.value屬性(實際監視了value中的reactive代理對象)或者開啟deep:true
watch(msg, (newValue, oldValue) => {
console.log(`msg changed: ${newValue} < ${oldValue}`)
}, { // 傳遞配置
immediate: true
})
複制
- 監視多個ref
watch([msg1, msg2], (newValue, oldValue) => {
// 不管哪個發生變化都會觸發
console.log(`something changed, msg1: ${newValue[0]} < ${oldValue[0]}`)
console.log(`something changed, msg2: ${newValue[1]} < ${oldValue[1]}`)
})
- 監視reactive,
注1,此處無法正确獲得oldValue
注2,強制開啟深度監視,deep:false配置無效
```js
watch(person, (newValue, oldValue) => {
console.log(newValue, oldValue)
})
複制
-
監視reactive中某個屬性
注,需要用函數指定屬性
watch(() => person.age, (newValue, oldValue) => {
console.log(`age changed: ${newValue} < ${oldValue}`)
})
複制
- 監視reactive中多個屬性
watch([() => person.firstName, () => person.lastName], (newValue, oldValue) => {
console.log(`something changed, firstName: ${newValue[0]} < ${oldValue[0]}`)
console.log(`something changed, lastName: ${newValue[1]} < ${oldValue[1]}`)
})
複制
-
監視reactive中的js對象屬性
注,需開啟deep:true,否則無法監視到深層變更(例如person.job.salary變更)
watch(() => person.job, (newValue, oldValue) => {
console.log(newValue, oldValue)
}, {deep: true})
複制
watchEffect 智能監視
監視函數中依賴的屬性發生變更時觸發
// person.age或person.job.salary變化時就會調用此函數
watchEffect(()=>{
console.log("年齡:"+person.age)
console.log("薪資:"+person.job.salary)
})
複制