天天看點

vue3筆記1 元件配置API建立執行個體setup元件選項

建立執行個體

入口檔案

./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函數傳回:

  1. 對象,包含模闆中可以使用的屬性,方法
<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)
})           

複制