天天看點

Vue3.0學習 - 第十三節,Vue3 setup中如何使用計算屬性computed , 父子元件如何傳值

在vue2中我們可以使用計算屬性 computed  去定義一個計算屬性并且去計算

代碼片段:

data() {
    return {
      num1: 0,
      num2: 0,
    };
  },
  computed: {
    result() {
      return parseInt(this.num1) + parseInt(this.num2);
    },
  },


           

我們可以知道是 num1和num2的和等于result

在vue3中我們如何使用computed

代碼:

<template>
  <div class="hello">
    <h1>{{msg}}</h1>
    <input type="text" v-model="state.num1" >
    <span> + </span>
    <input type="text" v-model="state.num2" >
    <span> = </span>
    {{state.result}}
  </div>
</template>

<script>
import { reactive, computed } from "vue";
export default {
  name: "HelloWorld",
  props: {
    msg: String,
  },
 
  setup() {
    let state = reactive({
      num1: 0,
      num2: 0,
      result: computed(() => {
        return parseInt(state.num1) + parseInt(state.num2);
      }),
    });
    return { state };
  },
};

// 方法單獨抽離
// function reacFun() {
//   // 聲明
//   let state = reactive({
//     num1: 0,
//     num2: 0,
//     result: 0,
//   });
//   // 邏輯
//   let add = () => {
//     console.log("123");
//     state.result = parseInt(state.num1) + parseInt(state.num2);
//   };
//   // 傳回
//   return { state, add };
// }
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped >

</style>
           

我們可以看到可以直接在定義的reactive中直接使用computed

let state = reactive({
      num1: 0,
      num2: 0,
      result: computed(() => {
        return parseInt(state.num1) + parseInt(state.num2);
      }),
    });
           

父子傳值:

vue2 是通過 this.$emit()

vue3是如何傳值呢?

setup()方法接受兩個參數

  • 入參:
    • {Data} props

    • {SetupContext} context

interface Data {
  [key: string]: unknown
}

interface SetupContext {
  attrs: Data
  slots: Slots
  emit: (event: string, ...args: unknown[]) => void
}

function setup(props: Data, context: SetupContext): Data
           

我們可以給set傳兩個參數 setup(props,ctx) ,因為es6可以解構 是以我們可以這樣寫 setup(props,{emit})

setup(props,{emit}) {
    console.log("setup---props",props)

    let state = reactive({
      num1: 0,
      num2: 0,
      result: computed(() => {
        return parseInt(state.num1) + parseInt(state.num2);
      }),
    });

    let send = ()=>{
      console.log("send",state.result)
      emit('sendMsg',state.result)
    }

    return { state,send };
  },
           

這樣我們就可以把我們父元件傳遞來的 props 直接可以在setup中拿到 直接列印,子元件通過emit向父元件傳參  和vue2方法一樣

父元件:

<template>
  <div class="home">
    <HelloWorld msg="Welcome to Your Vue.js App" @sendMsg="handler" />
  </div>
</template>

<script>
// @ is an alias to /src
import HelloWorld from '@/components/HelloWorld.vue'

export default {
  name: 'Home',
  components: {
    HelloWorld
  },
  setup(){
    //子元件傳參
    let handler = value => {
      console.log("handler",value)
    }

    return {handler}
  }
}
</script>
           

結論:

父元件  ——>  子元件 :props      setup(props,ctx)

子元件 ——> 父元件 :emit      setup(props,{emit}){ emit('sendMsg',state.result) }  或 setup(props,ctx) {  ctx.emit('sendMsg',state.result) }

注意:

在vue3中使用 emit可能會報錯警告:

Extraneous non-emits event listeners (sendMsg) were passed to component but could not be automatically inherited because component renders fragment or text root nodes. If the listener is intended to be a component custom event listener only, declare it using the "emits" option. 

問題解決:

export default {
  name: "HelloWorld",
  emits: ["sendMsg"],//添加這一行解決
  props: {
    msg: String,
  },
  setup(props, ctx) {
    console.log("setup---props", props);
  

    let state = reactive({
      num1: 0,
      num2: 0,
      result: computed(() => {
        return parseInt(state.num1) + parseInt(state.num2);
      }),
    });

    let send = () => {
      console.log("send", state.result);
      ctx.emit("sendMsg", state.result);
    };
    return { state, send };
  },
};
           

繼續閱讀