vue3. The 0 feature is continuously updated

1. Create an application instance

  • Each Vue application creates a new application instance by using the createApp function
  • This application instance is used to register the "global" component in the application
const app = Vue.createApp({})
app.component('SearchInput', SearchInputComponent)
app.directive('focus', FocusDirective)
app.use(LocalePlugin)
  • Most methods exposed by the application instance will return the same instance, allowing chaining
Vue.createApp({})
  .component('SearchInput', SearchInputComponent)
  .directive('focus', FocusDirective)
  .use(LocalePlugin)

2.setup

To start using the composite API, we first need a place where we can actually use it. In the Vue component, we call this location setup
The new setup option is executed before the component is created. Once props is parsed, it will be used as an entry to the composite API.
The setup option is a function that receives props and context, which we will discuss later. In addition, we expose everything returned by setup to the rest of the component (calculation properties, methods, life cycle hooks, etc.) and the component template
When using the setup function, it receives two parameters:

  • props
  • context
    props is responsive and will be updated when a new prop is passed in.
    However, because props is responsive, you can't use ES6 to deconstruct. It will eliminate the responsiveness of props.
    If you need to deconstruct prop, you can use the toRefs function in the setup function to complete this operation:
// MyBook.vue

import { toRefs } from 'vue'

setup(props) {
  const { title } = toRefs(props)

  console.log(title.value)
}

If title is an optional prop, there may be no title in the incoming props. In this case, toRefs will not create a ref for the title. You need to replace it with toRef:

// MyBook.vue
import { toRef } from 'vue'
setup(props) {
  const title = toRef(props, 'title')
  console.log(title.value)
}

Context

The second parameter passed to the setup function is context. Context is a common JavaScript object that exposes three properties of components:

// MyBook.vue

export default {
  setup(props, context) {
    // Attribute (non responsive object)
    console.log(context.attrs)

    // Slot (non responsive object)
    console.log(context.slots)

    // Trigger event (method)
    console.log(context.emit)
  }
}

Context is an ordinary JavaScript object, that is, it is not responsive, which means you can safely use ES6 to deconstruct context.

// MyBook.vue
export default {
  setup(props, { attrs, slots, emit }) {
    ...
  }
}

Attrs and slots are stateful objects, which are always updated with the update of the component itself. This means that you should avoid deconstructing them and always use attrs X or slots X refers to property. Note that, unlike props, attrs and slots are non responsive. If you intend to apply side effects based on attrs or slots changes, you should do so in the onUpdated lifecycle hook.

Note that refs returned from setup is automatically unpacked when accessed in the template, so it should not be used in the template value.

setup can also return a rendering function that can directly use the reactive state declared in the same scope:

// MyBook.vue

import { h, ref, reactive } from 'vue'

export default {
  setup() {
    const readersNumber = ref(0)
    const book = reactive({ title: 'Vue 3 Guide' })
    // Note that here we need to explicitly call ref's value
    return () => h('div', [readersNumber.value, book.title])
  }
}

Using Provide

When using provide in setup(), we first explicitly import the provide method from vue. This enables us to call provide to define each property.

The provide function allows you to define property with two parameters:

name (type)
value
After using the MyMap component, the value of provide can be reconstructed as follows:

<!-- src/components/MyMap.vue -->
<template>
  <MyMarker />
</template>

<script>
import { provide } from 'vue'
import MyMarker from './MyMarker.vue'

export default {
  components: {
    MyMarker
  },
  setup() {
    provide('location', 'North Pole')
    provide('geolocation', {
      longitude: 90,
      latitude: 135
    })
  }
}
</script>

Use inject

When using inject in setup(), you also need to explicitly import from vue. After importing, we can call it to define the way the components are exposed to us.

The inject function has two parameters:

The name of the property to inject
Default (optional)
Using the MyMarker component, you can refactor it with the following code:

<!-- src/components/MyMarker.vue -->
<script>
import { inject } from 'vue'

export default {
  setup() {
    const userLocation = inject('location', 'The Universe')
    const userGeolocation = inject('geolocation')

    return {
      userLocation,
      userGeolocation
    }
  }
}
</script>

Responsiveness

Add responsiveness

In order to increase the responsiveness between the provide value and the input value, we can use ref or reactive when providing the value.

Using the MyMap component, our code can be updated as follows:

<!-- src/components/MyMap.vue -->
<template>
  <MyMarker />
</template>

<script>
import { provide, reactive, ref } from 'vue'
import MyMarker from './MyMarker.vue'

export default {
  components: {
    MyMarker
  },
  setup() {
    const location = ref('North Pole')
    const geolocation = reactive({
      longitude: 90,
      latitude: 135
    })

    provide('location', location)
    provide('geolocation', geolocation)
  }
}
</script>

Now, if there are any changes in these two properties, the MyMarker component will also be updated automatically!

#Modify responsive property
When using the responsive provide / inject value, it is recommended to limit all modifications to the responsive property to the component defining the provide as much as possible.

For example, if we need to change the user's location, we'd better do this in the MyMap component.

<!-- src/components/MyMap.vue -->
<template>
  <MyMarker />
</template>

<script>
import { provide, reactive, ref } from 'vue'
import MyMarker from './MyMarker.vue'

export default {
  components: {
    MyMarker
  },
  setup() {
    const location = ref('North Pole')
    const geolocation = reactive({
      longitude: 90,
      latitude: 135
    })

    provide('location', location)
    provide('geolocation', geolocation)

    return {
      location
    }
  },
  methods: {
    updateLocation() {
      this.location = 'South Pole'
    }
  }
}
</script>

However, sometimes we need to update the inject data inside the component that injects the data. In this case, we suggest providing a method to change the responsive property.

<!-- src/components/MyMap.vue -->
<template>
  <MyMarker />
</template>

<script>
import { provide, reactive, ref } from 'vue'
import MyMarker from './MyMarker.vue'

export default {
  components: {
    MyMarker
  },
  setup() {
    const location = ref('North Pole')
    const geolocation = reactive({
      longitude: 90,
      latitude: 135
    })

    const updateLocation = () => {
      location.value = 'South Pole'
    }

    provide('location', location)
    provide('geolocation', geolocation)
    provide('updateLocation', updateLocation)
  }
}
</script>
<!-- src/components/MyMarker.vue -->
<script>
import { inject } from 'vue'

export default {
  setup() {
    const userLocation = inject('location', 'The Universe')
    const userGeolocation = inject('geolocation')
    const updateUserLocation = inject('updateLocation')

    return {
      userLocation,
      userGeolocation,
      updateUserLocation
    }
  }
}
</script>

Finally, if you want to ensure that the data passed through the provide will not be changed by the inject component, we recommend using readonly for the provider's property.

<!-- src/components/MyMap.vue -->
<template>
  <MyMarker />
</template>

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

export default {
  components: {
    MyMarker
  },
  setup() {
    const location = ref('North Pole')
    const geolocation = reactive({
      longitude: 90,
      latitude: 135
    })

    const updateLocation = () => {
      location.value = 'South Pole'
    }

    provide('location', readonly(location))
    provide('geolocation', readonly(geolocation))
    provide('updateLocation', updateLocation)
  }
}
</script>

3. Responsive variable with ref

These functions accept a callback that will be executed when the hook is called by the component.
Only when accessing nested ref s, you need to add them to the template value:

Let's add it to the setup function:

// src/components/UserRepositories.vue `setup` function
import { fetchUserRepositories } from '@/api/repositories'
import { ref, onMounted } from 'vue'

// In our component
setup (props) {
  const repositories = ref([])
  const getUserRepositories = async () => {
    repositories.value = await fetchUserRepositories(props.user)
  }

  onMounted(getUserRepositories) // Call 'getUserRepositories' when' mounted '`

  return {
    repositories,
    getUserRepositories
  }
}

The responsiveness of both properties using deconstruction will be lost. In this case, we need to convert our responsive object into a set of refs. These refs retain the responsive association with the source object:

import { reactive, toRefs } from 'vue'

const book = reactive({
  author: 'Vue Team',
  year: '2020',
  title: 'Vue 3 Guide',
  description: 'You are reading this book right now ;)',
  price: 'free'
})

let { author, title } = toRefs(book)

title.value = 'Vue 3 Detailed Guide' // We need to use value as the title, now ref
console.log(book.title) // 'Vue 3 Detailed Guide'

4.watch responsive change

Just as we use the watch option in the component and set the listener on the user property, we can also use the watch function imported from Vue to perform the same operation. It accepts three parameters:

  • A responsive reference or getter function that you want to listen on
  • A callback
  • Optional configuration options
  • Let's take a quick look at how it works
import { ref, watch } from 'vue'

const counter = ref(0)
watch(counter, (newValue, oldValue) => {
  console.log('The new counter value is: ' + counter.value)
})

Now we apply it to our example:

// src/components/UserRepositories.vue `setup` function
import { fetchUserRepositories } from '@/api/repositories'
import { ref, onMounted, watch, toRefs } from 'vue'

// In our component
setup (props) {
  // Use 'toRefs' to create a responsive reference to the' user 'property of prop
  const { user } = toRefs(props)

  const repositories = ref([])
  const getUserRepositories = async () => {
    // Update ` prop User ` to ` user Value ` access reference value
    repositories.value = await fetchUserRepositories(user.value)
  }

  onMounted(getUserRepositories)

  // Set a listener on the responsive reference of user prop
  watch(user, getUserRepositories)

  return {
    repositories,
    getUserRepositories
  }
}

5. Independent computed attribute

Similar to ref and watch, you can also use the calculated function imported from Vue to create calculated properties outside Vue components. Let's return to the example of counter:

import { ref, computed } from 'vue'

const counter = ref(0)
const twiceTheCounter = computed(() => counter.value * 2)

counter.value++
console.log(counter.value) // 1
console.log(twiceTheCounter.value) // 2

6. Life cycle

Options APIsetup
beforeMountonBeforeMount
mountedonMounted
updatedonUpdated
unmountedonUnmounted

Because setup runs around the beforeCreate and created lifecycle hooks, there is no need to explicitly define them. In other words, any code written in these hooks should be written directly in the setup function.

Keywords: Javascript node.js Vue.js

Added by jbille on Fri, 17 Dec 2021 02:51:00 +0200