1. The basic

The syntax of VUe2 (data,methods, etc.) can also be used, but is not recommended

<tamplate>// You can do without the outer div<h2>{{ count }}</h2>
<button @click="update">update</button>
</tamplate>// Use the ts code<script lang="ts"></script>
Copy the code

2. Setup (Parent-child component interaction)

Execute before beforeCreate

The parent component:

<child :msg="msg" attr="attr" @fn="fn"/>
Copy the code
import child from './child.vue'
components: {
  child
}
Copy the code

Child components:

<h3>msg: {{ msg }}</h3>
<h3>msg2: {{ $attrs.msg2 }}</h3>
Copy the code
// setup (props, context) {
setup (props, {attrs, emit, slots}) {
  /* Props: data passed by the parent to the child attr: properties written by the parent to the child emit: method passed by the parent to the child slots: slots */
  console.log(props.msg, attrs.msg2, slots, emit)

  function update () {
    emit('fn'.'+ +')}}Copy the code

3. Calculate attributes

const user = reactive({
  firstName: 'A'.lastName: 'B'
})

// Only getter computed properties
const fullName1 = computed(() = > {
  return user.firstName + The '-' + user.lastName
})

Getters and setters
const fullName2 = computed({
  get () {
    // return to fullName2
    return user.firstName + The '-' + user.lastName
  },

  set (value: string) { // value: fullName2
    const [firstName, lastName] = value.split(The '-')
    user.firstName = firstName
    user.lastName = lastName
  }
})
Copy the code

4. Listen to attributes

watch(user, (newVal, oldVal) = > {
  fullName3.value = newVal.firstName + The '-' + newVal.lastName
}, {
  immediate: true.// Whether to initialize immediately. Default is false
  deep: true.// If it is deep monitoring, the default is false
})

/* Listen for multiple data: use an array to specify a value in a REF object, and use a function to specify a value in a reactive object
// watch([user, fullName3], (values) => {
watch([() = > user.firstName, () = > user.lastName, fullName3], (values) = > {
  console.log('Monitor multiple data', values)
})

// Listen for all variables inside watchEffect. Initialization is performed immediately
watchEffect(() = > {
  fullName3.value = user.firstName + The '-' + user.lastName
})
Copy the code

5. Life cycle

  • BeforeCreate -> Use setup()
  • Created -> Setup ()
  • beforeMount -> onBeforeMount
  • mounted -> onMounted
  • beforeUpdate -> onBeforeUpdate
  • updated -> onUpdated
  • beforeDestroy -> onBeforeUnmount
  • destroyed -> onUnmounted
  • errorCaptured -> onErrorCaptured

6. hook

hooks/useMousePosition.ts:

import { ref, onMounted, onUnmounted } from 'vue'
// Collect the page coordinates of the user's mouse clicks
export default function useMousePosition () {
  // Initialize coordinate data
  const x = ref(-1)
  const y = ref(-1)

  // A function to collect click event coordinates
  const updatePosition = (e: MouseEvent) = > {
    x.value = e.pageX
    y.value = e.pageY
  }

  // Bind click listener after mount
  onMounted(() = > {
    document.addEventListener('click', updatePosition)
  })

  // Unbind before uninstall click listen
  onUnmounted(() = > {
    document.removeEventListener('click', updatePosition)
  })

  return {x, y}
}
Copy the code

index.ts:

/* Introducing and using custom hook functions in components: similar to mixin in VUe2; advantage: code reuse */
import useMousePosition from './hooks/useMousePosition'

export default {
  setup() {
    const {x, y} = useMousePosition()

    return {
      x,
      y,
    }
  }
}
Copy the code

7. Composition API

7.1 ref Retrieves elements

<input type="text" ref="inputRef">
Copy the code
import { onMounted, ref } from 'vue'
export default {
  setup() {
    const inputRef = ref<HTMLElement | null> (null)

    onMounted(() = > {
      // Make the input field automatically get focus
      inputRef.value && inputRef.value.focus()
    })

    return {
      inputRef
    }
  },
}
Copy the code

7.2 ref

<template>// No need to add value to HTML<h2>{{ count }}</h2>
  <button @click="update">update</button>
</template>
Copy the code
<script>
  import { ref } from 'vue'
  export default {
    setup () {
      // Non-responsive, HML cannot detect the change of count in JS
      const count = 1
      // ref: define reactive data (for basic data types, you can also put objects, but multiple values are not necessary)
      const count = ref(1)

      function update () {
        // use in js, need to add value
        count.value = count.value + 1
      }

      // Expose it for HTML
      return {
        count,
        update
      }
    }
  }
</script>
Copy the code

7.3 reactive

<template>
  <h2>name: {{ state.name }}</h2>
  <button @click="update">update</button>
</template>

<script>
  import { reactive } from 'vue'
  export default {
    setup () {
      // Reactive: Defines reactive data (for objects) and deep responses (changes to internal arrays can be responded to)
      // const state = reactive
       
        ({// any type can add new attributes
       
      const state = reactive({ // New attributes cannot be added by default
        name: 'tom'.wife: {
          name: 'marry'.arr: [1.2.3]}})const update = () = > {
        state.name += The '-'
        state.wife.arr[4] = 4
      }

      return {
        state,
        update,
      }
    }
  }
</script>
Copy the code

7.4 toRef

const state = reactive({
  foo: 'a'.bar: 'b',})// foo1 and state.foo interact
const foo1 = toRef(state, 'foo')
// foo2 and state.foo do not interact
const foo2 = ref(state.foo)
Copy the code

7.5 toRefs

Export default {setup () {const state = reactive({foo: 'a', bar: 'b',}); const bar = ref('b'); */ const stateAsRefs = toRefs(state) const { foo2, bar2 } = useReatureX() return { ... StateAsRefs, foo2, bar2}},} Function useReatureX() {const state = reactive({foo2: 'a', bar2: 'b', }) return toRefs(state) }Copy the code

7.6 toRaw markRaw

const state = reactive<any>({
  name: 'tom'.age: 25,})const testToRaw = () = > {
  const user = toRaw(state)
  // State does not change
  user.age++
}

const testMarkRaw = () = > {
  const likes = ['a'.'b']
  // Likes are no longer responsive, other attributes remain responsive
  state.likes = markRaw(likes)
}
Copy the code

7.7 with shallowReadonly readonly

// Deep read-only data
const rState1 = readonly(state)
// Shallow read-only data: the outer layer cannot be modified, but the inner layer can be modified
const rState2 = shallowReadonly(state)
Copy the code

ShallowReactive and shallowRef(rarely used)

// Deep response
const m1 = reactive({a: 1.b: {c: 2}})
// Shallow response, the outer layer is responding, the inner layer is not responding
const m2 = shallowReactive({a: 1.b: {c: 2}})

// Deep response
const m3 = ref({a: 1.b: {c: 2}})
// Shallow response: only the value response is processed, not the object response
const m4 = shallowRef({a: 1.b: {c: 2}})
Copy the code

7.9 customRef: create a customRef

setup () {
  // Parameter one: initial value
  const keyword = useDebouncedRef('xxx'.500)

  return {
    keyword
  }
}

// Implement a custom ref for function stabilization
function useDebouncedRef<T> (value: T, delay = 200) {
  let timeout: number
  return customRef((track, trigger) = > {
    return {
      get() {
        // Tell Vue the trace data
        track()
        return value
      },
      set(newValue: T) {
        clearTimeout(timeout)
        timeout = setTimeout(() = > {
          value = newValue
          // Tell Vue to trigger interface update
          trigger()
        }, delay)
      }
    }
  })
}
Copy the code

7.10 Judgment of responsive data

  1. IsRef: Checks whether a value is a ref object
  2. IsReactive: Checks whether an object is a reactive agent created by Reactive
  3. IsReadonly: Checks whether an object is a read-only proxy created by readOnly
  4. IsProxy: Checks whether an object is a proxy created by reactive or readonly methods

8. A new component

8.1 Teleport

<template>
  <button @click="modalOpen = true">Open</button>// Insert the component's HTML display under a specific tag (most likely body) outside the parent component's interface<teleport to="body">
    <div v-if="modalOpen" class="modal">
      <div>
        <button @click="modalOpen = false">Close</button>
      </div>
    </div>
  </teleport>
</template>
Copy the code

8.2 Suspense

The application renders some back-up content while waiting for the asynchronous component

The parent component:

<template>
  <Suspense>
    <template v-slot:default>
      <AsyncAddress/>
    </template>

    <template v-slot:fallback>
      <h1>LOADING...</h1>
    </template>
  </Suspense>
</template>
Copy the code

Child component: asyncaddress.vue

async setup() {
  const result = await axios.get('/data/address.json')
  return {
    data: result.data
  }
}
Copy the code

9. Comparison of VUe3 and VUe2

  1. New scaffold vite(not support VUE2)
  2. Support for ts
  3. Faster: virtual DOM optimization, life cycle optimization, etc
  4. The package is smaller
  5. New Composition API, more conducive to achieve code reuse
  6. Refactoring responsive systems to replace Object.defineProperty with Proxy (important)
  7. You can listen directly for changes in array type data
  8. Add/delete object attributes directly
  9. The target of listening is the Object itself and there is no need to iterate over every attribute like object.defineProperty, which has some performance benefits
  10. 13 methods such as Apply, ownKeys, and HAS can be intercepted, but Object.defineProperty cannot

source

B station is still silicon Valley tutorial: video notes