Недавно я изучал Jest с помощью @ vue / test-utils и наткнулся на интересный тестовый пример. Мне нужно было утверждать, что мой компонент вызывает метод в ответ на порожденное событие дочернего компонента. Это привело меня к открытию нескольких новых (новых для меня) способов доступа к параметрам родительского и дочернего компонентов.
Передать все реквизиты / данные сразу
Иногда нам может потребоваться просто передать все свойства родительского компонента дочернему компоненту. Это легко сделать так: <child-component :example-data="$props" />
и данные тоже <child-component :example-data="$data" />
. Быстро и безболезненно.
Бонус: вы также можете передать реквизит на <router-view />
. В этом примере данные компонента all-props.vue: элементы, ошибка и загрузка будут доступны для всех дочерних маршрутов в this.$attrs['example-data']
<template> <div class='all-props'> <child-component :example-data="$props" /> <router-view :example-data="$data" /> </div> </template> <script> import { ChildComponent } from "./components" export default { name: "all-props", components: { ChildComponent }, props: { status: { type: String, required: true, validator: val => ['loading','error','complete'].indexOf(val) > -1 } }, data:() => ({ items:[], error: false, loading: false }) }; </script>
Параметры родитель / потомок
Вы также можете легко получить доступ к параметрам родительского / дочернего компонента. Скажем, мы хотим напрямую вызвать метод в родительском компоненте с именем coolFunction()
, для этого мы можем написать this.$parent.coolFunction()
. Это работает в обоих направлениях, поэтому компонент может делать то же самое с дочерним компонентом. В приведенном ниже примере Home.vue (родительский) и HelloWorld.vue (дочерний) из каркаса проекта по умолчанию vue-cli. Мы можем напрямую вызвать дочерний метод triggerAlert()
, используя $ refs или $ children.
Home.vue
<template> <div class="home"> <HelloWorld ref="foo" msg="Hello World" /> <button @click.exact="triggerChildMethod" @keydown.enter="triggerChildMethod" > Trigger Child Method </button> </div> </template> <script> import HelloWorld from "@/components/HelloWorld.vue"; export default { name: "Home", components: { HelloWorld }, props: { items: { type: Array, default: () => [] } }, data: () => ({ lorem: "ipsum" }), methods: { triggerChildMethod() { this.$refs.foo.triggerAlert(); } }, /** * @note $refs and $children not available in created hook */ mounted() { console.log("this.$refs.foo.$data :", this.$refs.foo.$data); console.log("this.$children[0].$data :", this.$children[0].$data); } }; </script>
HelloWorld .vue
<template> <div class="hello"> <h1>{{ msg }}</h1> </div> </template> <script> export default { name: "HelloWorld", props: { msg: String }, data: () => ({ message: null, items: false, thing: true }), methods: { triggerAlert() { alert("ayyyy"); } } }; </script>
Консольные журналы данных компонентов:
И вот мы сработали наше оповещение:
Модульный тест
Как и в сценарии, с которого я начал эту миссию по написанию статьи, здесь мы можем получить доступ к экземпляру дочерних компонентов, вызвать его метод и подтвердить, что был вызван родительский метод. Вот как может выглядеть этот тест:
import { mount } from '@vue/test-utils' import Home from '@/views/home.vue' import HelloWorld from '@/components/HelloWorld.vue' describe('Home.vue', () => { it('child can access and invoke a parent method', () => { const triggerChildMethod = jest.fn() const wrapper = mount(Home, { methods: { triggerChildMethod } }) wrapper.find(HelloWorld).vm.triggerParentMethod() expect(triggerChildMethod).toHaveBeenCalledTimes(1) }) })
Спасибо
Спасибо за чтение, надеюсь, вы найдете их такими же интересными / полезными, как и я! Я планирую делиться и другими интересными моментами, когда найду их. Будьте на связи.