Weekly summary 20210801 Vue document learning

Time:2021-11-24

Vue learning

Arrow function

function() => {

}

JS location

Javascript code can be embedded directly anywhere on a web page, but usually we put JavaScript code in<head>Medium;
Multiple. JS files can be introduced into the same page, and can be written multiple times in the page< script > JS code... < / script >, the browser executes in order.

Due to the security restrictions of the browser, the address starting with file: / / cannot execute JavaScript code such as networking. Finally, you still need to set up a web server, and then execute all JavaScript code with the address starting with http: / / normally.

JS semicolon

JavaScript does not force you to add at the end of each statement;

Digital judgment

The only way to judge Nan is throughisNaN()function

Pay special attention to the equality operator = =. JavaScript is designed with two comparison operators:
The first is = = comparison, which will automatically convert the data type for comparison. In many cases, very strange results will be obtained;
The second is = = = comparison, which does not automatically convert data types. If the data types are inconsistent, false is returned. If they are consistent, compare again.

This is not a design flaw in JavaScript. Floating point numbers will produce errors in the operation process, because the computer cannot accurately represent infinite circular decimals. To compare whether two floating-point numbers are equal, you can only calculate the absolute value of their difference to see if it is less than a threshold:

Math.abs(1 / 3 - (1 - 2 / 3)) < 0.0000001; // true

Dynamic language and static language

The language with variable type is called dynamic language, which corresponds to static language.

dynamic parameter

<a v-on:[eventName]="doSomething"> ... </a>

WheneventNameThe value of is"focus"When,v-on:[eventName]Will be equivalent tov-on:focus

v-bind

V-bind: attribute, one-way binding?

v-on

Event monitoring,v-on:click="", abbreviation@click=""
2.6.0 add dynamic parameters to respond to different events according to conditions
It should be noted that there should be no quotation marks and spaces in the dynamic expression, because these symbols are invalid for the attribute name of HTML. At the same time, the browser will turn the attribute name to lowercase, so there should be no uppercase characters

<!--  Variable form: - >
<template>
    <input @[type?up:down]="event1" id="dynamicParam" name="dynamicParam" type="text">
</template>
<script>
    export default{
        data(){
            return {
                type:false,
                up:'keyup',
                down:'keydown'
            }
        }
    }
</script>
<!--  Calculation attribute form: - >
<template>
    <div class="dynamicParamter">    
         < label for = "dynamicparam" > dynamic parameters < / label >
        <input @[type]="event1" id="dynamicParam" name="dynamicParam" type="text">
        < button @ Click = "type1 = true" > press < / button >
        < button @ Click = "type1 = false" > lift the keyboard < / button >
    </div>
</template>
<script>
  export default{
    data(){
      return {
        href:'href',
        url:'',
        type1:null,
      }
    },
    methods:{
      event1(){
        Console.log ("trigger" + (this. Type) + 'event')
      }
    },
    computed:{
      type(){
        if(this.type1){
          return 'keyup'
        }else{
          return 'keydown'
        }
      }
    }
  }
</script>

Anti shake and throttling

Some functions, such as those triggered by MouseMove, will be called several times in a short time. If you want to execute the function only once in a period of events, you need anti chattering and throttling
Anti shake: triggered every other period of events
Throttling: after continuous triggering, it is processed every other period of time

//Anti shake
function debounce(fn, wait) {
 let timeout = null
 return function() {
  if(timeout !== null) clearTimeout(timeout)   
  timeout = setTimeout(fn, wait);
 }
}
function handle() {  
 console.log(Math.random())
}
window.addEventListener('scroll', debounce(handle, 1000))

Calculation properties

In general, templates are required to be simple and declarative, such as<span>{{label}}</span>, but sometimes it is too complex, such as:

<span>{{ author.books.length > 0 ? 'Yes' : 'No' }}</span>

Although the code can work, it is too complex. It is recommended to use calculated attributes to declare

<span>{{ publishedBooksMessage }}</span>
computed: {
    //Getter of calculated property
    publishedBooksMessage() {
        // `this` points to the vm instance
        return this.author.books.length > 0 ? 'Yes' : 'No'
    }
}

Comparison between calculated attributes and methods: calculated attributes are re evaluated only when the responsive dependency changes, and functions are re executed every time they are called

<span>{{ countBooks1() }}</span>
<span>{{ countBools2 }}</span>
methods:{
    countBooks1() {
        return books.length
    }
},
computed:{
    countBooks2() {
        return books.length
    }
}

Setters and getters can be set for calculation properties

computed: {
  fullName: {
    // getter
    get() {
      return this.firstName + ' ' + this.lastName
    },
    // setter
    set(newValue) {
      const names = newValue.split(' ')
      this.firstName = names[0]
      this.lastName = names[names.length - 1]
    }
  }
}

Listener Watch

It can execute functions when responsive data changes. Compared with calculating attributes, watch can perform asynchronous operations, such as accessing APIs, but the overhead is greater than calculating attributes

watch: {
    // whenever question changes, this function will run
    question(newQuestion, oldQuestion) {
        if (newQuestion.indexOf('?') > -1) {
            this.getAnswer()
        }
    }
}

Truth value

In JS, exceptfalse0""nullundefinedandNaNAll other values are true.

if (true)
if ({})
if ([])
if (42)
if ("foo")
if (new Date())
if (-42)
if (3.14)
if (-3.14)
if (Infinity)
if (-Infinity)

:class

:class="{ active: isActive }"Class isisActiveValue, whenisActivebynulWhen, there is no class.
In addition,:classCan be withclassProperty coexistence,:classYou can also have multiple values within a class, or use an array to provide a class

<div :class="[activeClass, errorClass]"></div>
data() {
  return {
    activeClass: 'active',
    errorClass: 'text-danger'
  }
}

: style syntax

:styleThe object syntax is very intuitive – it looks very much like CSS, but it’s actually a JavaScript object. CSS property names can be named by camel case or kebab case

conditional rendering

There are two types of conditional rendering:v-ifandv-show
v-ifOnly when the condition is true, the condition is fast and can be compared withv-else-ifandv-elseUse together.
v-showIt will always be rendered, and the change of true and false values is reflected in the change of CSS

v-for

Can correspondarray, or correspondingobject
When corresponding to the array, the two parameters represent the value and index in turn;
When corresponding to the object, the three parameters represent the value, key and index in turn.

<ul id="array-with-index">
  <li v-for="(item, index) in items">
    {{ parentMessage }} - {{ index }} - {{ item.message }}
  </li>
</ul>
<li v-for="(value, name, index) in myObject">
  {{ index }}. {{ name }}: {{ value }}
</li>

When the order of data items in the corresponding data of V-for is changed, Vue will not move DOM elements to match the data, but use the “update in place” strategy. If you want to change the position of the corresponding DOM elements, you need to add:keyattribute

Array update detection

Array change

The following functions can trigger view updates

  • push()
  • pop()
  • shift()
  • unshift()
  • splice()
  • sort()
  • reverse()

    Array replacement

    The following function can keep the original array and return a new array

  • filter()
  • concat()
  • slice()

Display, filter and sort arrays

Can be inv-forCalculation properties or methods used in

Using V-for on components

Because the component has its own independent scope, it should be used when defining the componentpropsTo pass parameters.

<div id="todo-list-example">
  <form v-on:submit.prevent="addNewTodo">
    <label for="new-todo">Add a todo</label>
    <input
      v-model="newTodoText"
      id="new-todo"
      placeholder="E.g. Feed the cat"
    />
    <button>Add</button>
  </form>
  <ul>
    <todo-item
      v-for="(todo, index) in todos"
      :key="todo.id"
      :title="todo.title"
      @remove="todos.splice(index, 1)"
    ></todo-item>
  </ul>
</div>
const app = Vue.createApp({
  data() {
    return {
      newTodoText: '',
      todos: [
        {
          id: 1,
          title: 'Do the dishes'
        },
        {
          id: 2,
          title: 'Take out the trash'
        },
        {
          id: 3,
          title: 'Mow the lawn'
        }
      ],
      nextTodoId: 4
    }
  },
  methods: {
    addNewTodo() {
      this.todos.push({
        id: this.nextTodoId++,
        title: this.newTodoText
      })
      this.newTodoText = ''
    }
  }
})

app.component('todo-item', {
  template: `
    <li>
      {{ title }}
      <button @click="$emit('remove')">Remove</button>
    </li>
  `,
  props: ['title']
})

app.mount('#todo-list-example')

event processing

If you want to access the original DOM event in event processing, you can pass in the method with the special variable $event

<button @click="warn('Test', $event)">Submit</button>
warn(message, event) {
  if (event) {
    event.preventDefault()
  }
}

An event can be handled by multiple methods separated by commas

<button @click="one($event), two($event)">

Event. Preventdefault() and event. Stoppropagation()

event.preventDefault()Prevent the default action sending of events, such as clicking the check box can not switch the check state, entering non specified characters in the input box can not be entered, etc.

event.stopPropagation()The default action will still be executed, but after execution, the event will no longer be dispatched to other nodes.

JS bubble and capture

First, we need to formmonitorMy thoughts. Without using any framework, we pass it in JSaddEventListenerMethod to add event listeners to dom. The literal translation of this method is to add an event listener. As events, our operations on DOM will be gradually transferred from the outermost ancestor DOM to the target DOM (capture process), and then transmitted from the original path of the target DOM (bubble process). Usually we only monitor the bubbling process. In Vue, when we add an event modifiercaptureBefore it becomes a capture listener.

So in Vue.stopIt is easy to understand the stop propagation of modifiers. Generally speaking, when bubble listening, it is set from the inner sub DOM to the outer ancestor dom.stopAfter the event is processed in this DOM, the event will no longer bubble.

and.selfIt can be understood as skipping bubbling events and capturing events. Only events directly acting on this element can be executed.

Event modifier

  • .stopStop propagation after executing event
  • .preventNot executing the default action is equivalent to executingevent.preventDefault()
  • .captureChange from bubble monitoring to capture monitoring
  • .selfSkip bubbling events and capture events, and only events directly acting on the element can be executed
  • .onceExecute only once
  • .passiveWill not executeevent.preventDefault()

Key modifier

Use @ to listen for keyboard events

<input @keyup.enter="submit" />
  • .enter
  • .tab
  • .delete(capture delete and backspace keys)
  • .esc
  • .space
  • .up
  • .down
  • .left
  • .right

Modifier key

The modifier key is different from the conventional key, only when pressed and heldModifier keyThe event can be triggered only when other keys are released. Simply releasing the modifier key does not trigger an event.

<!-- Ctrl + Click -->
<div @click.ctrl="doSomething">Do something</div>

Keyboard modifier

  • .ctrl
  • .alt
  • .shift
  • .meta

Mouse modifier

  • .left
  • .right
  • .middle

.exactModifier

The. Exact modifier allows you to control events triggered by a precise combination of system modifiers.

<!--  Even if ALT or shift is pressed together, it will trigger -- >
<button @click.ctrl="onClick">A</button>

<!--  Yes, and only triggered when Ctrl is pressed -- >
<button @click.ctrl.exact="onCtrlClick">A</button>

<!--  Triggered when no system modifier is pressed -- >
<button @click.exact="onClick">A</button>

v-model

For the options of radio buttons, check boxes and selection boxes, the value bound by V-model is usually a static string (for check boxes, it can also be a Boolean value)
v-modelThere are three modifiers

  • .lazyUpdate at “change” instead of “input”
  • .numberConvert the user’s input value to a numeric type. If the value cannot be parsed by parsefloat(), the original value will be returned
  • .trimAutomatically filter the first and last white space characters entered by the user

Component Foundation

Because components are reusable component instances, they are associated withnew VueReceive the same options, for exampledatacomputedwatchmethodsAnd life cycle hooks. adoptcomponentGlobal registration is possible.

//Define a new global component named button counter
app.component('button-counter', {
  data() {
    return {
      count: 0
    }
  },
  template: `
    <button @click="count++">
      You clicked me {{ count }} times.
    </button>`
})

prop

adoptpropDefine properties and pass data to subcomponents

const app = Vue.createApp({})

app.component('blog-post', {
  props: ['title'],
  template: `<h4>{{ title }}</h4>`
})

app.mount('#blog-post-demo')

Listen for subcomponent events

through the use of$emitTo pass in the external event name, or you can pass out the internal parameters.

<div id="blog-posts-events-demo">
  <div v-bind:style="{ fontSize: postFontSize + 'em' }">
    <blog-post 
      v-for="post in posts" 
      :key="post.id" 
      :title="title"
      @enlarge-text="postFontSize += $event"></blog-post>
  </div>
</div>
app.component('blog-post', {
  props: ['title'],
  template: `
    <div class="blog-post">
      <h4>{{ title }}</h4>
      <button @click="$emit('enlarge-text', 0.1)">
        Enlarge text
      </button>
    </div>
  `
})

Implement the V-model bidirectional binding of components

For use in componentsv-model, the component needs to expose an acceptedpropAnd specify the value of the data inwardgetterandsettergettersetterThis can be achieved by calculating attributes.

<custom-input v-model="searchText"></custom-input>
app.component('custom-input', {
  props: ['modelValue'],
  template: `
    <input v-model="value">
  `,
  computed: {
    value: {
      get() {
        return this.modelValue
      },
      set(value) { this.$emit('update:modelValue', value)
      }
    }
  }
})

Simple slot

Components are used where they need to be inserted<slot>Label, which is directly wrapped with the component name label when using the component.

<alert-box>
  Something bad happened.
</alert-box>
app.component('alert-box', {
  template: `
    <div class="demo-alert-box">
      <strong>Error!</strong>
      <slot></slot>
    </div>
  `
})

Dynamically loading components

Use properties:isYou can easily load a simple assembly into this location.

<script></script>

<div id="dynamic-component-demo" class="demo">
  <button
     v-for="tab in tabs"
     v-bind:key="tab"
     v-bind:class="['tab-button', { active: currentTab === tab }]"
     v-on:click="currentTab = tab"
   >
    {{ tab.name }}
  </button>

  <component
      v-bind:is="currentTab.component"
    ></component>
</div>
const tabs = [
  {
    name: 'Home',
    component: {
      template: `<div class="demo-tab">Home component</div>`
    }
  },
  {
    name: 'Posts',
    component: {
      template: `<div class="demo-tab">Posts component</div>`
    }
  },
  {
    name: 'Archive',
    component: {
      template: `<div class="demo-tab">Archive component</div>`
    }
  }
]

const app = Vue.createApp({
  data() {
    return {
      tabs,
      currentTab: tabs[0]
    }
  },
  computed: {
    currentTabComponent() {
      return 'tab-' + this.currentTab.toLowerCase()
    }
  }
})

app.component('tab-home', {
  template: `<div class="demo-tab">Home component</div>`
})
app.component('tab-posts', {
  template: `<div class="demo-tab">Posts component</div>`
})
app.component('tab-archive', {
  template: `<div class="demo-tab">Archive component</div>`
})

app.mount('#dynamic-component-demo')

Special DOM parsing considerations

Shape such as<table><select><ul>These tags are strictly regulated by which sub tags can appear inside them (for example<tr>Can appear in<table>Medium). And some labels such as<li><tr>and<option>And so on can only appear inside a specific element. If you use custom components inside these specific tags, it may cause errors. You can usev-isProperty to help resolve the component.

<!--  Error -- >
<table>
  <blog-post-row></blog-post-row>
</table>

<!--  Correct -- >
<table>
  <tr v-is="'blog-post-row'"></tr>
</table>

Deep component

Component naming

Kebab case is recommended

Local registration

Local registration requires reference

import ComponentA from './ComponentA.vue'

export default {
  components: {
    ComponentA
  }
  // ...
}

Prop type

propThe type can be set, and the user will be prompted on the console when the setting error occurs.

props: {
  title: String,
  likes: Number,
  isPublished: Boolean,
  commentIds: Array,
  author: Object,
  callback: Function,
  Contactspromise: promise // or any other constructor
}

Dynamic incoming prop

When a value is passed in, there are two ways:

<!--  Static assignment -- >
<blog-post></blog-post>
<!--  Dynamically assign a variable value -- >
<blog-post :title="post.title"></blog-post>

The static assignment Vue is treated as a string, andv-bindOr abbreviation:Tell Vue this is a JS expression.

In particular, when all the attributes of an object need to be passed in, you can use the method without parametersv-bind

post: {
  id: 1,
  title: 'My Journey with Vue'
}
<blog-post v-bind="post"></blog-post>
<!--  Equivalent to -- >
<blog-post v-bind:id="post.id" v-bind:title="post.title"></blog-post>

Unidirectional data flow

We already know,propDefine external incoming data in. If we want these data to become local data for sub components to use, and the sub components will also be updated when the data is updated, but not vice versa (it will prevent accidental changes in the state of the parent component from the sub component, resulting in difficult understanding of the data flow of your application), we can define it inpropThe attribute in is defined as adata propertyOr calculate properties.

//Defined as data
props: ['initialCounter'],
data() {
  return {
    counter: this.initialCounter
  }
}
//Define as calculated attribute
props: ['size'],
computed: {
  normalizedSize: function () {
    return this.size.trim().toLowerCase()
  }
}

Prop data validation

You can define data types, specify default values, and customize validation rules.

app.component('my-component', {
  props: {
    //Basic type check (` null 'and ` undefined' will pass any type verification)
    propA: Number,
    //Multiple possible types
    propB: [String, Number],
    //Required string
    propC: {
      type: String,
      required: true
    },
    //Number with default value
    propD: {
      type: Number,
      default: 100
    },
    //Objects with default values
    propE: {
      type: Object,
      //Object or array defaults must be obtained from a factory function
      default: function() {
        return { message: 'hello' }
      }
    },
    //Custom validation function
    propF: {
      validator: function(value) {
        //This value must match one of the following strings
        return ['success', 'warning', 'danger'].indexOf(value) !== -1
      }
    },
    //Functions with default values
    propG: {
      type: Function,
      //Unlike the default value of an object or array, this is not a factory function -- it is a function used as the default value
      default: function() {
        return 'Default function'
      }
    }
  }
})

Attribute inheritance of non prop

Non prop attributes refer to attributes that are not defined inpropProperties in, such asclassidstylewait. When components are used externally and these attributes are used, they will be inherited to the root element inside the component by default; If there are multiple root elements or you want to inherit to non root elements, you can usev-bind="$attrs"$attrsInclude componentspropsandemits propertyAll properties not included in (for exampleclassstylev-onListeners, etc.) To select a DOM element inheritance.

The same is true for the inheritance of event listeners, which will inherit to the internal root element of the component by default.

<!--  Date picker component with non prop attribute -- >
<date-picker data-status="activated"></date-picker>

<!--  Render date picker component -- >
<div class="date-picker" data-status="activated">
  <input type="datetime" />
</div>

Note that if you want the non root node to inherit, you need to set it in the component optionsinheritAttrs: false

app.component('date-picker', {
  inheritAttrs: false,
  template: `
    <div class="date-picker">
      <input type="datetime" v-bind="$attrs" />
    </div>
  `
})
<!--  Date picker component uses non prop attribute -- >
<date-picker data-status="activated"></date-picker>

<!--  Render date picker component -- >
<div class="date-picker">
  <input type="datetime" data-status="activated" />
</div>

Custom event

Naming recommendedkebab-case(dashed connection) becausev-onThe event listener is automatically converted to all lowercase in the DOM template. Custom events can be combined withpropProperty.

app.component('custom-form', {
  emits: {
    //No validation
    click: null,

    //Validate submit event
    submit: ({ email, password }) => {
      if (email && password) {
        return true
      } else {
        console.warn('Invalid submit event payload!')
        return false
      }
    }
  },
  methods: {
    submitForm() {
      this.$emit('submit', { email, password })
    }
  }
})

The V-model parameter is bound to multiple v-models

In components, inpropThe attributes defined in can be used externallyV-model: attribute nameThe way to carry out multiplev-modelBinding.

Custom V-model modifier

You can also customize the V-model modifier in the component. However, it should be noted that the specific method of the modifier is written in the setter function of the property, and the name of the modifier isarg + "Modifiers"

<div id="app">
  <my-component v-model:name.capitalize="myText"></my-component>
  {{ myText }}
</div>
const app = Vue.createApp({
  data() {
    return {
      myText: ''
    }
  }
})

app.component('my-component', {
  props: {
    name: String,
    nameModifiers: {
      default: () => ({})
    }
  },
  methods: {
    emitValue(e) {
      let value = e.target.value
      if (this.modelModifiers.capitalize) {
        value = value.charAt(0).toUpperCase() + value.slice(1)
      }
      this.$emit('update:name', value)
    }
  },
  template: `<input
    type="text"
    :value="name"
    @input="emitValue">`
})

app.mount('#app')

slot

It can be defined in the template of the component<slot>Tags, which can be replaced with strings, HTML code, or other components. When<slot>When there is content in the middle of the label, this part will be used as the default.

<button type="submit">
  <slot>Submit</slot>
</button>

Named slot

When multiple slots are required, each slot needs to be given a name in order to identify different slotsname, withoutnameThe slot will have an implied name “default”. When using the named slot of the component externally, use<template>ofv-slotIndicates the slot name. Note that it must be usedv-slotMust be at<template>Label.

<div class="container">
  <header>
    <slot name="header"></slot>
  </header>
  <main>
    <slot></slot>
  </main>
  <footer>
    <slot name="footer"></slot>
  </footer>
</div>
<base-layout>
  <template v-slot:header>
    <h1>Here might be a page title</h1>
  </template>

  <template v-slot:default>
    <p>A paragraph for the main content.</p>
    <p>And another one.</p>
  </template>

  <template v-slot:footer>
    <p>Here's some contact info</p>
  </template>
</base-layout>

If you want external access to the internal data of the component (for example, the internal data of the component is required when inserting content), you can set the attribute of the slot in the component template to data.

<slot name="slot1" :item="label"></slot>
<aaa>
  <template v-slot:slot1="slotProps">
    <p>{{slotProps.item}}</p>
  </template>
</aaa>

becausev-slotThe value of is used as a function parameter, so it can be written as any JavaScript expression that can be used as a parameter in the function definition.

<!--  Rename parameter -- >
<todo-list v-slot="{ item: todo }">
  <i class="fas fa-check"></i>
  <span class="green">{{ todo }}</span>
</todo-list>
<!--  Parameter default value -- >
<todo-list v-slot="{ item = 'Placeholder' }">
  <i class="fas fa-check"></i>
  <span class="green">{{ item }}</span>
</todo-list>

v-slotDynamic parameters can also be used<template v-slot:[dynamicSlotName]>

Abbreviation for named slot

Abbreviations can be used only when there are parameters#replacev-slot

<todo-list #default="{ item }">
  <i class="fas fa-check"></i>
  <span class="green">{{ item }}</span>
</todo-list>

Supply and injection

In a multi-layer nested component chain, there are two methods for the inner component to obtain the data of the outer component:

The first is the setting mentioned earlierprop, but it is inconvenient that this needs to be set in each layer of componentsprop, the development is a little troublesome;

The second is the mode that the parent component provides data and the child component injects data, which we can useprovideandinjectyes. A parent component can be a dependency provider for all its child components, regardless of how deep the component hierarchy is. This feature has two parts: the parent component has oneprovideOption to provide data. The subcomponent has oneinjectOption to start using this data.

The injected data is non responsive by default. If you want responsive data injection, you need to allocate a composite APIcomputedProperties.

//Provided by parent component
app.component('todo-list', {
  data() {
    return {
      todos: ['Feed a cat', 'Buy tickets']
    }
  },
  provide() {
    return {
      todoLength1: this.todos.length,
      Todolength2: Vue. Computed (() = > this. Todos. Length) // response
    }
  },
  template: `
    ...
  `
})

app.component('todo-list-statistics', {
  inject: ['todoLength'],
  created() {
    Console.log (` injected property: ${this. Todolength1} ` // > injected property: John Doe
  }
})

Keep alive label

In some scenes, such as switching tabs, constantly switching tabs will constantly re render components. Use keep alive label<keep-alive>You can maintain the state of these components to avoid performance problems caused by repeated re rendering.

<keep-alive>
  <component :is="currentTabComponent"></component>
</keep-alive>

Asynchronous component

I don’t quite understand it. I can’t use it for the time being. I’ll study it again when I read it for the second time.

Template reference

If you need to access components in JS, you can userefSpecify the reference ID for the component or HTML element. Note that due to$refsIt will only take effect after the component rendering is completed, and access in templates or calculated properties should be avoided$refs

<input ref="input" />
const app = Vue.createApp({})

app.component('base-input', {
  template: `
    <input ref="input" />
  `,
  methods: {
    focusInput() {
      this.$refs.input.focus()
    }
  },
  mounted() {
    this.focusInput()
  }
})

Recommended Today

Seven solutions for distributed transactions

1、 What is distributed transaction Distributed transaction means that transaction participants, transaction supporting servers, resource servers and transaction managers are located on different nodes of different distributed systems. A large operation is completed by more than n small operations. These small operations are distributed on different services. For these operations, either all of them are […]