688 vue3 Composition API:生命周期,provide,inject,hooks,render,h函数,jsx

生命周期钩子


App.vue

<template>
  <div>
    <button @click="increment">{{ counter }}</button>
  </div>
</template>

<script>
  import { onMounted, onUpdated, onUnmounted, ref } from 'vue'

  export default {
    setup() {
      const counter = ref(0)
      const increment = () => counter.value++

      // 【不推荐使用beforeCreate、created了,如果需要做这2个函数做的操作,可以在setup里面做,setup在这2个函数之前执行。】
      // 【同一个生命周期可以使用多次,每次都会执行,这样就可以将某一个抽离到hooks中。】
      onMounted(() => {
        console.log('App Mounted1')
      })
      onMounted(() => {
        console.log('App Mounted2')
      })
      onUpdated(() => {
        console.log('App onUpdated')
      })
      onUnmounted(() => {
        console.log('App onUnmounted')
      })

      return {
        counter,
        increment,
      }
    },
  }
</script>

<style scoped></style>

写的App.vue

<template>
  <div>
    <h3 ref="numRef">num的值是: {{ num }}</h3>
    <button @click="addOne">+1</button>
  </div>
</template>

<script>
  import { ref, onBeforeUpdate, onUpdated } from 'vue'

  export default {
    setup() {
      const num = ref(100)
      const numRef = ref(null)

      const addOne = () => num.value++

      onBeforeUpdate(() => {
        console.log('onBeforeUpdate') // onBeforeUpdate 
        // <h3>num的值是: 101</h3>   "object"
        console.log(numRef.value, typeof numRef.value)
        // 要通过 value.innerHTML 这种方式才能拿到界面变化前后的值
        console.log(numRef.value.innerHTML) // num的值是: 100
      })

      onUpdated(() => {
        // onUpdated <h3>num的值是: 101</h3>
        console.log('onUpdated', numRef.value)
        console.log(numRef.value.innerHTML) // num的值是: 101
      })

      return {
        num,
        numRef,
        addOne,
      }
    },
  }
</script>

Provide函数


Inject函数


数据的响应式


修改响应式Property


App.vue

<template>
  <div>
    <home />
    <h2>App Counter: {{ counter }}</h2>
    <button @click="increment">App中的+1</button>
  </div>
</template>

<script>
  import { provide, ref, readonly } from 'vue'
  import Home from './Home.vue'

  export default {
    components: {
      Home,
    },
    setup() {
      const name = ref('haha')
      let counter = ref(100)

      provide('name', readonly(name))
      provide('counter', readonly(counter))

      const increment = () => counter.value++

      return {
        increment,
        counter,
      }
    },
  }
</script>

<style scoped></style>

Home.vue

<template>
  <div>
    <h2>{{ name }}</h2>
    <h2>{{ counter }}</h2>

    <button @click="homeIncrement">home+1</button>
  </div>
</template>

<script>
  import { inject } from 'vue'

  export default {
    setup() {
      // 参数1:key,参数2:默认值,可以不写
      const name = inject('name')
      const counter = inject('counter')

      const homeIncrement = () => counter.value++

      return {
        name,
        counter,
        homeIncrement,
      }
    },
  }
</script>

<style scoped></style>

useCounter


useCounter.js

import { ref, computed } from 'vue'

export default function () {
  const counter = ref(0)
  const doubleCounter = computed(() => counter.value * 2)

  const increment = () => counter.value++
  const decrement = () => counter.value--

  return {
    counter,
    doubleCounter,
    increment,
    decrement,
  }
}

useTitle


useTitle.js

import { ref, watch } from 'vue'

// 场景:title要根据某个变量修改,根据返回值修改title
export default function (title = '默认的title') {
  const titleRef = ref(title)

  watch(
    titleRef,
    newValue => {
      document.title = newValue
    },
    {
      immediate: true,
    }
  )

  return titleRef
}

useScrollPosition


useScrollPosition.js

import { ref } from 'vue'

export default function () {
  const scrollX = ref(0)
  const scrollY = ref(0)

  document.addEventListener('scroll', () => {
    scrollX.value = window.scrollX
    scrollY.value = window.scrollY
  })

  return {
    scrollX,
    scrollY,
  }
}

useMousePosition


useMousePosition.js

import { ref } from 'vue'

export default function () {
  const mouseX = ref(0)
  const mouseY = ref(0)

  window.addEventListener('mousemove', event => {
    mouseX.value = event.pageX
    mouseY.value = event.pageY
  })

  return {
    mouseX,
    mouseY,
  }
}

useLocalStorage


useLocalStorage.js

import { ref, watch } from 'vue'

export default function (key, value) {
  const data = ref(value)

  if (value) {
    window.localStorage.setItem(key, JSON.stringify(value))
  } else {
    data.value = JSON.parse(window.localStorage.getItem(key))
  }

  watch(data, newValue => {
    window.localStorage.setItem(key, JSON.stringify(newValue))
  })

  return data
}

// 一个参数: 取值
// const data = useLocalStorage("name");

// // 二个参数: 保存值
// const data = useLocalStorage("name", "haha");

// data.value = "kobe";

index.js

import useCounter from './useCounter'
import useTitle from './useTitle'
import useScrollPosition from './useScrollPosition'
import useMousePosition from './useMousePosition'
import useLocalStorage from './useLocalStorage'

export {
  useCounter,
  useTitle,
  useScrollPosition,
  useMousePosition,
  useLocalStorage,
}

setup顶层编写方式

App.vue

<template>
  <div>
    <h2>当前计数: {{ counter }}</h2>
    <button @click="increment">+1</button>

    <hello-world message="呵呵呵" @increment="getCounter"></hello-world>
  </div>
</template>

<script setup>
  import { ref } from 'vue'
  import HelloWorld from './HelloWorld.vue'

  const counter = ref(0)
  const increment = () => counter.value++

  const getCounter = payload => {
    console.log(payload)
  }
</script>

<style scoped></style>

HelloWorld.vue

<template>
  <div>
    <h2>Hello World</h2>
    <h2>{{ message }}</h2>
    <button @click="emitEvent">发射事件</button>
  </div>
</template>

<script setup>
  import { defineProps, defineEmit } from 'vue'

  const props = defineProps({
    message: {
      type: String,
      default: '哈哈哈',
    },
  })

  const emit = defineEmit(['increment', 'decrement'])

  const emitEvent = () => {
    emit('increment', '100000')
  }
</script>

<style scoped></style>

认识h函数


h()函数 如何使用呢?


h函数的基本使用


h函数计数器案例


函数组件和插槽的使用


01_render的基本使用.vue

<script>
  import { h } from 'vue'

  export default {
    render() {
      return h('h2', { class: 'title' }, 'Hello Render')
    },
  }
</script>

<style scoped></style>

02_render函数实现计数器.vue

<script>
  import { h } from 'vue'

  export default {
    data() {
      return {
        counter: 0,
      }
    },
    render() {
      return h('div', { class: 'app' }, [
        h('h2', null, `当前计数: ${this.counter}`),
        h(
          'button',
          {
            onClick: () => this.counter++,
          },
          '+1'
        ),
        h(
          'button',
          {
            onClick: () => this.counter--,
          },
          '-1'
        ),
      ])
    },
  }
</script>

<style scoped></style>

03_setup函数实现计数器.vue

<script>
  import { ref, h } from 'vue'

  export default {
    setup() {
      const counter = ref(0)

      return () => {
        return h('div', { class: 'app' }, [
          h('h2', null, `当前计数: ${counter.value}`),
          h(
            'button',
            {
              onClick: () => counter.value++,
            },
            '+1'
          ),
          h(
            'button',
            {
              onClick: () => counter.value--,
            },
            '-1'
          ),
        ])
      }
    },
  }
</script>

<style scoped></style>

App.vue

<script>
  import { h } from 'vue'
  import HelloWorld from './HelloWorld.vue'

  export default {
    render() {
      return h('div', null, [
        h(HelloWorld, null, {
          default: props =>
            h('span', null, `app传入到HelloWorld中的内容: ${props.name}`),
        }),
      ])
    },
  }
</script>

<style scoped></style>

HelloWorld.vue

<script>
  import { h } from 'vue'

  export default {
    render() {
      return h('div', null, [
        h('h2', null, 'Hello World'),
        this.$slots.default
          ? this.$slots.default({ name: 'coderwhy' })
          : h('span', null, '我是HelloWorld的插槽默认值'),
      ])
    },
  }
</script>

<style lang="scss" scoped></style>

jsx的babel配置


jsx计数器案例


jsx组件的使用


App.vue

<script>
  import HelloWorld from './HelloWorld.vue'

  export default {
    data() {
      return {
        counter: 0,
      }
    },

    render() {
      const increment = () => this.counter++
      const decrement = () => this.counter--

      return (
        <div>
          <h2>当前计数: {this.counter}</h2>
          <button onClick={increment}>+1</button>
          <button onClick={decrement}>-1</button>
          <HelloWorld></HelloWorld>
        </div>
      )
    },
  }
</script>

<style lang="scss" scoped></style>

HelloWorld.vue

<script>
  export default {
    render() {
      return (
        <div>
          <h2>HelloWorld</h2>
          {this.$slots.default ? this.$slots.default() : <span>哈哈哈</span>}
        </div>
      )
    },
  }
</script>

<style scoped></style>

posted on 2021-06-22 21:29  冲啊!  阅读(273)  评论(0编辑  收藏  举报

导航