The default template approach, similar to VUE2, is used for componentssetupfunction

/ / the parent component
<template>
  <div>
    <div>
      <div>{{city}}</div>
      <button @click="changeReactive">Change of reactive</button>
      <button @click="handleFather">Click on the parent</button>
    </div>
    <Child ref="childRef" @handleBtn="handleBtn" @testClick="testClick" city="Chengdu" />
  </div>
</template>

<script>
import { ref, onMounted, toRefs, reactive } from 'vue'
import Child from './Child.vue'

export default {
  components: {
    Child
  },
  setup () {
    const handleBtn = (val) = > {
      console.log('btn', val)
    }

    const testClick = (val) = > {
      console.log('testClick', val)
    }

    const childRef = ref(null)

    const handleFather = () = > {
      childRef.value.observed.a = Awesome! // The parent component modifies the value of the child component
      console.log('Methods to get child components', childRef.value)
      // The child component needs to define expose, if not, then need to return, the corresponding function, generally do not return directly, if not used on the page
      // Just expose the method or value
    }

    // Write through the method of the setup function, which returns the method and value used on the page
    // If the value is defined by reactve, the rendered value on the page is not responsive and needs to be converted through toRefs and then destructed
    / /... toRefs(testReactive)
    
    const testReactive = reactive({
      city: 'Beijing'.age: 22
    })

    const changeReactive = () = > {
      testReactive.city = 'chongqing'
    }

    return{ handleBtn, testClick, handleFather, ... toRefs(testReactive), changeReactive, childRef } } }</script>


/ / child component
<template>
  <div>
    {{observed.a}}
    <button @click="handleBtn">Click on the</button>
  </div>
</template>

<script>
import { defineProps, defineEmits, defineEmit, defineExpose, reactive } from 'vue'

export default {
  props: {
    city: String
  },

  /* This is set so that ctx.attrs cannot access this property */
  /* props (props), props (props), attrs (props), props (props), props (props

  emits: ['testClick'].// This is set so that there is no custom method on attrs.
  // If peops is set for the subcomponent, the corresponding value is not accessible in attrs
  // Arrts has been enhanced in vue3 by mounting custom methods, classes, and styles
  In VUE2, customizations are mounted to $listeners, whereas in VUE3,$Liseners were removed

  setup (props, ctx) {
    const { expose, emit } = ctx
    const handleBtn = () = > {
      console.log('btn', ctx)
      emit('testClick'.Awesome!)}const observed = reactive({
      a: 1
    })

    function clickChild (value) {
      observed.a = value
    }

    expose({
      clickChild, // Expose custom methods that the parent component calls
      observed// Expose the value of the child component
    })

    return {
      observed,
      handleBtn
    }
  }
}
</script>
Copy the code

Write setup on the script tag<script setup>

/ / the parent component
<template>
  <div>
    <button @click="handleFather">Click on the parent</button>
    <Child ref="childRef" @handleBtn="handleBtn" @testClick="testClick" city="Chengdu" />
  </div>
</template>

<script setup>
import { ref } from 'vue'
import Child from './Child.vue'
// This method does not need to be used in return export page methods and values, need to be used in vue to destruct the corresponding defin
const childRef = ref(null)

const handleBtn = (val) = > {
  console.log('btn', val)
}

const testClick = (val) = > {
  console.log('testClick', val)
}

const handleFather = () = > {
  console.log('Methods to get child components', childRef.value)
  childRef.value.testFatherClick()  // The parent component calls the methods of the child component
  // The child component exposes the corresponding method via defineExpose
}

</script>


/ / child component
<template>
  <div>
    <button @click="handleBtn">Click on the</button>
  </div>
</template>

<script setup>
import { defineProps, defineEmits, defineExpose, reactive } from 'vue'

const props = defineProps({
  city: String
})

const emit = defineEmits(['handleBtn'.'testClick'])

const handleBtn = () = > {
  // console.log('btn', props, emit)
  emit('testClick'.12)}const testFatherClick = () = > {
  console.log('Test parent component click child component')}const observed = reactive({
  a: 1
})

defineExpose({ // Expose method to parent group price
  testFatherClick,
  observed
})

</script>

<style scoped>
</style>
Copy the code

Render in JSX, which is very close to react, which is my most recommended way. JSX also supports TS, and.vue files are not as good as TSX support

/ / the parent component
import { ref, reactive } from 'vue'
import Child from './Child.jsx'

const Father = {
  setup() {
    // The ref defined in JSX needs to be accessed via.value to be used on the page
    const city = ref('Beijing')

    const changeCity = () = > {
      city.value = 'hangzhou'
    }

    const childRef = ref(null)

    const handelFather = (add) = > {
      // Also by exposing the expose method on the component
      // city.value = 'hangzhou'
      console.log('childRef', childRef.value)
    }

    const testChildClick = (val) = > {
      console.log('Test subcomponent click', val)
    }

    return () = > {
      return (
        <div>
          <div>{city.value}</div>
          <button onClick={changeCity}>Change the city</button>
          <button onClick={handelFather}>Click on the parent</button>
          <Child testChildClick={testChildClick} ref={childRef} />
        </div>)}}}export default Father


/ / child component
import { ref, reactive } from 'vue'

const Child = {
  props: {
    testChildClick: Function
  },

  setup(props, { emit, expose }) {
    const { testChildClick } = props
    const testFatherClick = () = > {
      console.log('Test parent component click child component')}const handelBtn = () = > {
      Emit ('testChildClick') // emit('testChildClick') // emit('testChildClick') // emit('testChildClick'
      // console.log('props', props)
      testChildClick('Return value to parent')
      // This is the only way to do it. This is the same as react. This is the same as passing a function to the child component, and the child component passes the value to the parent component through the function
    }

    expose({
      testFatherClick
    })

    return () = > {
      return (
        <div>
          <button onClick={handelBtn}>The child component passes values to the parent component</button>
        </div>)}}}export default Child
Copy the code