1. Common Vue features

1.1 Calculating Attributes

1. Why do I need to evaluate attributes?

The evaluation logic of expressions can be complex, and using evaluation attributes can make template content more concise

2. Calculate the use of attributes

Computed: {Calculate attribute name () {returnResults}}Copy the code

3. Calculate the difference between attributes and methods

  • Computed properties are cached based on their dependencies
  • Method does not have a cache

1.2 Form Operations

Vue-based form operations

  • Input Single line of text
  • Textarea multi-line text
  • Select drop down multiple selections
  • Radio radio buttons
  • The checkbox boxes,

1.3 Custom Instructions

1. Why do I need custom instructions?

The built-in instructions do not meet the requirements

2. Syntax rules for custom instructions (get element focus)

Vue.directive('focus' {
    inserted: function(el) {
    // Get the focus of the elementel.focus(); }})Copy the code

3. Custom instruction usage

    <input type="text" v-focus>
Copy the code

4. Custom instructions with parameters (change element background color)

Vue. Directive (' color', { inserted: function(el, binding) { el.style.backgroundColor = binding.value.color; }})Copy the code

5. Usage of instructions

    <input type="text" v-color='{color:"orange"}'>
Copy the code

6. Local instructions

directives: { focus: { Inserted: function (el) {el.focus()}}
Copy the code

1.4 the listener

1. Application scenarios of listeners

Perform asynchronous or expensive operations when data changes

2. Usage of listeners

watch: {
    "Name of the property being listened on" (newVal, oldVal){
        
    }
}
Copy the code

Usage of case listeners

<template>
  <div>
    <input type="text" v-model="name">
  </div>
</template>

<script>
export default {
  data(){
    return {
      name: ""}},// Target: listen for changes in name value
  /* Syntax: watch: {variable name (newVal, oldVal){// Variable name corresponding value changes here automatically}} */
  watch: {
    // newVal: indicates the latest value
    // oldVal: last moment value
    name(newVal, oldVal){
      console.log(newVal, oldVal); }}}</script>

<style>

</style>
Copy the code

Summary: To listen for a property change, use the listening property Watch

3. Vue listener – Deep listening and immediate execution

Target: Listen for complex types, or execute the listener function immediately

Grammar:

<template>
  <div>
    <div class="title">
      <h4>Furong Building to Xin - chien</h4>
      <span class="btn" @click="isShow = ! isShow">{{ isShow ? "Unpack" : "unfold"}}</span>
    </div>
    <div class="container" v-show="isShow">
      <p>The cold rain comes to wu at night,</p>
      <p>Pingming send a guest chu Mountain gu.</p>
      <p>Relatives and friends in Luoyang asked,</p>
      <p>A piece of ice in the jade pot.</p>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      isShow: false}; }};</script>

<style lang="less">
.title {
  display: flex;
  justify-content: space-between;
  align-items: center;
  border: 1px solid #ccc;
  padding: 0 1em;
}
.title h4 {
  line-height: 2;
  margin: 0;
}
.container {
  border: 1px solid #ccc;
  padding: 0 1em;
}
.btn {
  /* Change mouse to hand shape */
  cursor: pointer;
}
</style>


Copy the code

Summary: Wrap tags + styles + JS – Components are all separate for reuse

1.5 the filter

1. What is the function of the filter?

Format data, such as capitalizing strings, formatting dates to a specified format, and so on

2. Customize a filter

Vue.filter(' Filter name ',function(value){
// Filter business logic
})
Copy the code

3. Use of filters

    <div>{{msg | upper}}</div> 
    <div>{{msg | upper | lower}}</div> 
    <div v-bind:id="Id | formatId"></div> 
Copy the code

4. Local filter

filters:{
    capitalize: function(){}}Copy the code

2. Componentized development

2.1 Componentized development idea

The idea of componentization in reality

  • standard
  • Divide and conquer
  • reuse
  • combination

Componentized specification: Web Components

  • We want to reuse as much code as possible
  • The way you customize components is not easy (HTML, CSS, JS)
  • Using components multiple times can lead to conflicts

2.2 Component Registration

Global – Registered for use

The global entry is registered in main.js on new Vue

Grammar:

import Vue from 'vue'
importComponent objectfrom 'Vue file path'
Vue.component("Component name", component object)Copy the code

Case global registration is used

main.js

import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false

// Target: global registration (one definition used everywhere)
// 1. Create a component-file named.vue
// 2. Import components
import Pannel from './components/Pannel_1'
// 3. Global - Register components
/* Syntax: Vue.com (" component name ", component object) */
Vue.component("PannelG", Pannel)


new Vue({
  render: h= > h(App),
}).$mount('#app')

Copy the code

Once the PannelG component name is registered globally, it can be used as a tag in any template

It can be either odd or even tags or lowercase plus -. After running, the custom tag is parsed as a component and replaced with the tag encapsulated in the component

<PannelG></PannelG>
<PannelG/>
<pannel-g></pannel-g>
Copy the code

Local – Registered for use

Grammar:

importComponent objectfrom 'Vue file path'

export default {
    components: {
        "Component name": component object}}Copy the code

Import, register, use app.vue

<template>
  <div id="app">
    <h3>Case study: Folding panel</h3>
    <! -- 4. Use component names as tags -->
    <! -- < component name ></ component name >
    <PannelG></PannelG>
    <PannelL></PannelL>
  </div>
</template>

<script>
// Target: local registration
// 1. Create a component-file named.vue
// 2. Import components
import Pannel from './components/Pannel_1'
export default {
  // 3. Local - Register components
  /* Syntax: components: {" component name ": component object} */
  components: {
    PannelL: Pannel
  }
}
</script>

<style lang="less">
body {
  background-color: #ccc;
  #app {
    width: 400px;
    margin: 20px auto;
    background-color: #fff;
    border: 4px solid blueviolet;
    border-radius: 1em;
    box-shadow: 3px 3px 3px rgba(0.0.0.0.5);
    padding: 1em 2em 2em;
    h3 {
      text-align: center; }}}</style>


Copy the code

Component usage summary:

  1. Encapsulate HTML + CSS +vue into a separate. Vue file
  2. (Import registration) Component file => get component configuration object
  3. Use the current page as a tag

2.3 VUE components – Scoped functions

  • Purpose: To solve the problem of conflicting component style names
  • Need: div tag name selector, set background color
  • Problem: Found that div inside component and div outside component are working
  • Solution: Add scoped to pannel. vue’s style tag
<style scoped>
Copy the code
  • And it must be an element of the current component to have this custom property
  • Adding the scoped attribute to the style adds a randomly generated data-v attribute to the component’s label

Summary: Style plus scoped, styles within components only apply to the current VUE component

2.4 VUE Component Communication

Parent component passes value to child component

1. The component internally receives the value through props

Vue.com ponent (' menu item', {
props: ['title'],
template: '<div>{{ title }}</div>'})Copy the code

2. The parent component passes the value to the child component via properties

<template>
  <div>
    <! -- Target: parent (app.vue) -> child (myProduct.vue); Child component - props - Variables (ready to receive) 2. Parent component - Pass in ->
    <Product title="Delicious mouth chicken." price="50" intro="Opening ceremony, 20% off."></Product>
    <Product title="So cute, so cute." price="20" intro="Boss out of town, 10% off."></Product>
    <Product title="What an expensive Peking duck!" price="290" :intro="str"></Product>
  </div>
</template>
Copy the code

3. Props attribute name rule

  • Use the hump form in props and the short bar form in templates
  • String templates do not have this limitation
Vue.com ponent (' menu item', {// in JavaScript is humped props: [' menuTitle'].template: '<div>{{ menuTitle }}</div>'}) <! -- In HTML, it's dashes --><menu-item menu-title="Nihao"></menu-item>
Copy the code

4. The props property value type

  • String String
  • The numerical Number
  • Boolean value Boolean
  • An Array of Array
  • Object the Object

The case component internally receives the values passed through the props

Steps:

  1. Create component Components/myProduct.vue – Prepare label
  2. The component defines variables for props to receive external values. (It is recommended that the props property names be lowercase, because properties in tags can only be lowercase.)
  3. App.vue introduces the registered component, and when used, passes in specific data to the component to display components/ myProduct.vue – ready label

components/MyProduct.vue

<template>
  <div class="my-product">
    <h3>{{title}}</h3>
    <p>Price: {{price}} yuan</p>
    <p>{{ intro }}</p>
  </div>
</template>

<script>
export default {
  props: ['title'.'price'.'intro']}</script>

<style>
.my-product {
  width: 400px;
  padding: 20px;
  border: 2px solid # 000;
  border-radius: 5px;
  margin: 10px;
}
</style>
Copy the code

Data is used and passed in app.vue

<template>
  <div>
    <! -- Target: parent (app.vue) -> child (myProduct.vue); Child component - props - Variables (ready to receive) 2. Parent component - Pass in ->
    <Product title="Delicious mouth chicken." price="50" intro="Opening ceremony, 20% off."></Product>
    <Product title="So cute, so cute." price="20" intro="Boss out of town, 10% off."></Product>
    <Product title="What an expensive Peking duck!" price="290" :intro="str"></Product>
  </div>
</template>

<script>
// 1. Create component (.vue file)
// 2. Import components
import Product from './components/MyProduct'
export default {
  data(){
    return {
      str: "It's so expensive. Come on. It's delicious."}},// 3. Register components
  components: {
    // Product: Product // Key and value variables have the same name - short
    Product
  }
}
</script>

<style>

</style> 
Copy the code

5. One-way data flow

You need to follow the one-way data flow principle in VUE

  1. If the parent component’s data changes, the child component automatically follows
  2. The child component cannot modify the props passed by the parent component directly

A parent component passes an object to a child component. If a child component modifies the properties of the object, no error is reported. Objects are reference types and update each other

Conclusion: The value of props cannot be reassigned. The object reference relation property values change and affect each other

Child components pass values to parent components

1. Child components pass information to parent components through custom events

Grammar:

  • Parent: @custom event name =” Parent methods function”
  • Child: this.$emit(” custom event name “, pass value) – Executes the parent methods code
export default {
  props: ['index'.'title'.'price'.'intro'].methods: {
    subFn(){
      this.$emit('subprice'.this.index, 1) / / the child to the father
      eventBus.$emit("send".this.index, 1) / / across components}}}Copy the code

2. The parent component listens for events of the child component

<Product v-for="(obj,index) in list" :key="obj.id" :title=obj.proname :price=obj.proprice :intro=obj.info :index=index @subprice="sub"></Product> <! -- parent: @ Custom event name ="Parent methods function" -->
Copy the code

3. Child components pass information to parent components through custom events

// Child: this.$emit(" custom event name ", pass value) - Executes the parent methods code
      this.$emit('subprice'.this.index); / / the child to the father
        // eventBus.$emit("send", this.index, 1
Copy the code

Case child component passes value to parent component

App.vue

<template>
  <div>
     <! -- Target: parent (app.vue) -> child (myProduct.vue); Child component - props - Variables (ready to receive) 2. Parent component - Pass in ->
    <! <Product title=" intro "price="50" intro=" intro" price="50" intro=" </Product> <Product title=" intro ":intro=" STR "></Product>

    <Product v-for="(obj,index) in list" :key="obj.id" :title=obj.proname :price=obj.proprice :intro=obj.info :index=index @subprice="sub"></Product>
    <! -- parent: @custom event name =" parent "-->
   
  </div>
</template>
<script>
import Product from './components/MyProduct'
export default {
  data() {
    return {
      list: [{id: 1.proname: "A really good lollipop.".proprice: 18.8.info: 'Opening ceremony, 20% off.' },
    { id: 2.proname: "Super tasty big drumsticks.".proprice: 34.2.info: 'It's delicious. Come buy it.' },
    { id: 3.proname: "The best ice cream ever.".proprice: 14.2.info: 'It's a hot summer day. It's ice cream.'},]}},components:{
    Product
  },
  methods: {
    sub(index){
      if(this.list[index].proprice<1) {return
      }
      this.list[index].proprice--
      this.list[index].proprice = this.list[index].proprice.toFixed(2)
      // this.$set(this.list,index,{
      / /... this.list[index],
      // proprice:this.list[index].proprice-1
      // })}}},</script>
<style>
  
</style>
Copy the code

components/.components.vue

<template>
  <div class="my-product">
    <h3>{{title}}</h3>
    <p>Price: {{price}} yuan</p>
    <p>{{ intro }}</p>
    <button @click="subFn">Dong Dong cut a knife</button>
  </div>
</template>

<script>
export default {
  props: ['index'.'title'.'price'.'intro'].methods: {
    subFn() {
    // Child: this.$emit(" custom event name ", pass value) - Executes the parent methods code
      this.$emit('subprice'.this.index); / / the child to the father
        // eventBus.$emit("send", this.index, 1,}}};</script>

<style>
.my-product {
  width: 400px;
  padding: 20px;
  border: 2px solid # 000;
  border-radius: 5px;
  margin: 10px;
}
</style>

Copy the code

Non-parent components pass values

1. Communication between independent event center management components

var eventHub = new Vue()
Copy the code

2. Listen events and destroy events

var eventHub = new Vue()
eventHub.$on('add-todo', addTodo)
eventHub.$off('add-todo')
Copy the code

3. Trigger events

eventHub.$emit('add-todo', id)
Copy the code

Integrated case – To-do list

App.vue

<template>
  <section class="todoapp">
    <! -- parent: @custom event name =" parent "-->
    <TodoHeader @create="createFn" :arr="list"/>
    <TodoBody :arr="list" @del="delFn" />
    <TodoFooter/>
  </section>
</template>

<script>
// 1. Style introduction
import './assets/base.css';
import './assets/index.css';
// 3. App.vue introduces the registration component, when using, pass in the specific data to the component display

// import component object from 'vue file path '
import TodoHeader from './components/TodoHeader';
import TodoBody from './components/TodoBody';
import TodoFooter from './components/TodoFooter';

// export default {
// components: {
// "Component name ": component object
/ /}
// }
export default {
  data() {
    return {
      list: [{id: 100.name: 'eat'.isDone: true },
        { id: 201.name: 'sleep'.isDone: false },
        { id: 103.name: 'Beat the beans'.isDone: true},]}; },methods: {
    createFn(taskName) {
      let id =
        this.list.length == 0 ? 100 : this.list[this.list.length - 1].id + 1;
        this.list.push({
          id:id,
          name:taskName,
          isDone:false})},delFn(index){
            this.list.splice(index,1)}},components: {
    TodoHeader,
    TodoBody,
    TodoFooter,
  },
};
</script>

Copy the code

TodoHeader.vue

<template>
  <header class="header">
    <h1>todo</h1>
    <input id="toggle-all" class="toggle-all" type="checkbox" v-model="all" />
    <label for="toggle-all"></label>
    <! 3.1 Input box v-model get value -->
    <input
      class="new-todo"
      placeholder="Enter the task name - Enter Confirm"
      autofocus
      @keydown.enter="downFn"
      v-model="task"
    />
  </header>
</template>

<script>
// 3. Goal - New task
export default {
  props: ['arr'].data() {
    return {
      task: ' '}; },methods: {
    downFn() {
      // Child: this.$emit(" custom event name ", pass value) - Executes the parent methods code
      this.$emit('create'.this.task), (this.task = ' '); }},computed: {
    all: {
      set(checked) {
        this.arr.forEach(obj= > (obj.isDone = checked));
      },
      get() {
        return (
          this.arr.length ! = =0 && this.arr.every(obj= > obj.isDone === true)); }},}};</script>

Copy the code

TodoBody.vue

<template>
  <ul class="todo-list">
    <! -- 2.2 Loop Task -- Associate Selected Status -- Lay data -->
    <! -- completed: Name of the completed class -->
    <li
      :class="{ completed: obj.isDone }"
      v-for="(obj, index) in arr"
      :key="obj.id"
    >
      <div class="view">
        <input class="toggle" type="checkbox" v-model="obj.isDone" />
        <label>{{ obj.name }}</label>
        <! -- 4.0 Register events -->
        <button @click="delFn(index)" class="destroy"></button>
      </div>
    </li>
  </ul>
</template>

<script>
export default {
  props: ['arr'].methods: {
    delFn(index) {
      // 4.1 Child passes to father
      this.$emit('del', index); ,}}};</script>

<style></style>

Copy the code