The component Context API provides a mechanism for components to ‘talk’ to each other without passing data and functions as properties, or sending lots of events. Similar to vue provide and inject

There are two API functions related to Context, setContext and getContext

If a component calls setContext(key, context), then any of its children can retrieve the context by const Context = getContext(key).

SetContext and getContext are similar to lifecycle functions and can only be called during component initialization.

The parent component App. Svelte

<script>
  import { setContext } from 'svelte'
  import Child1 from './Child1.svelte'
  import Child2 from './Child2.svelte'
	
  // The value of Context can be any data type
  setContext('child1', {
    msg: 'child1 message'
  })

  setContext('child2', {
    msg: 'child2 message'
  })
</script>

<Child1 />
<Child2 />
Copy the code

Child components

<! -- Child1.svelte -->
<h2>{ctx.msg}</h2>

<script>
  import { getContext } from 'svelte'
  let ctx
	
  // If the child component's parent set a context named child1, the child component can be obtained using the getContext method
  // If the parent component does not set the context or the child component is used alone, the child component may not get a valid context
  // Therefore, it is necessary to use the corresponding logical judgment
  if (getContext('child1')) {
    ctx = getContext('child1')}</script>

<! -------------------------------------->

<! -- Child2.svelte -->
<h2>{ctx.msg}</h2>

<script>
  import { getContext } from 'svelte'
  let ctx

  if (getContext('child2')) {
    ctx = getContext('child2')}</script>
Copy the code

When setting a context, you can use any data type as the key of the context in principle, but it is recommended to use the reference data type as the key of the context

For example: setContext({},…) This avoids key conflicts (because {}! == {} “x” === “x”)

<! -- parent app.svelte -->
<script>
  import { setContext } from 'svelte'
  import Middle from './Middle.svelte'
	
  setContext('child', {
    msg: 'App message'
  })
</script>

<Middle />

<! Middle. Svelte -->
<Child />

<script>
  import { setContext } from 'svelte'
  import Child from './Child.svelte'

  setContext('child', {
    msg: 'Middle message'
  })
</script>

<! -- Child component child. svelte -->
<h2>{ctx.msg}</h2> <! -- output Middle message -->

<script>
  import { getContext } from 'svelte'
  let ctx

  if (getContext('child')) {
    ctx = getContext('child')}</script>
Copy the code

Contexts vs Props vs Stores

category describe
Contexts To pass from father to father or all descendants

(including children that are generations away or passed in slot mode)

The data is not responsive
Props The father the son

Data is responsive
Stores Any component and between components (does not need to be parent and child)

Data is responsive

Context is not reactive by default. If you want values in Context to support reactivity,

You should store the value in the Store first and then place the Store in the context.

Module context

Typically, a script contains code that needs to be executed each time a component is instantiated

If I want some code to be executed the first time a component is instantiated, and then not executed again, I can use the module context

The main purpose of a module context is to provide a way for all instances of a component to share the same context

If you want to share values across multiple components, it is recommended to use store

The module context is written in the top-level script tag

Values declared in a module context can be accessed from a regular

Note: Variables defined in the Module script are not responsive. So assignment does not trigger it to be rerendered, even though the variable itself is updated.

<! -- Child.svelte -->
<script context="module">
  // After setting context="module" on the script, the code in the scipt block will only be executed on the first instantiation
  // Subsequent instantiations of the component will not be executed
  const elements = new Set(a);// Any content exported from the context="module" block will become an export of the module itself
  // Currently, the export can only be a normal export. You cannot use the default export because the component itself uses the default export
  export function stopAll() {
    elements.forEach(element= > element.pause() });
  }
</script>

<! -- App.svelte -->
<script>
  import Child, { stopAll } from './Child.svelte';
</script>
Copy the code