vue知識(shí)點(diǎn)總結(jié)

  1. Vue基礎(chǔ)
  • Vue實(shí)例
    Vue 實(shí)例是 Vue.js 中最基本的構(gòu)建塊之一。每個(gè) Vue 應(yīng)用程序都是由一個(gè) Vue 根實(shí)例創(chuàng)建的,該實(shí)例通過將選項(xiàng)對(duì)象傳遞給 Vue 構(gòu)造函數(shù)而創(chuàng)建。
    Vue 實(shí)例的屬性和方法包括:
    • data:用于存儲(chǔ)數(shù)據(jù)的對(duì)象,可以在模板中進(jìn)行訪問。
    • methods:用于定義在 Vue 實(shí)例中使用的方法。
    • computed:用于定義計(jì)算屬性,其值會(huì)根據(jù)依賴項(xiàng)的變化而變化。
    • watch:用于監(jiān)聽特定數(shù)據(jù)的變化,一旦變化就會(huì)觸發(fā)相應(yīng)的回調(diào)函數(shù)。
    • directives:用于定義自定義指令。
    • filters:用于定義過濾器,可以在模板中使用。
      除了這些屬性和方法之外,Vue 實(shí)例還有一些生命周期鉤子
      函數(shù),用于在實(shí)例的生命周期內(nèi)執(zhí)行特定的操作,例如在實(shí)例創(chuàng)建時(shí)執(zhí)行某些操作,或在實(shí)例銷毀時(shí)執(zhí)行清理操作。
  • 模板語法
    Vue.js 的模板語法是基于 HTML 的擴(kuò)展,通過 Vue 的指令和插值語法,使得模板能夠更加動(dòng)態(tài)和交互。下面是一些常用的 Vue 模板語法示例:
    • 插值語法
      插值語法使用雙大括號(hào) {{}} 來綁定數(shù)據(jù),它會(huì)將 Vue 實(shí)例中的數(shù)據(jù)渲染到模板中。<div>{{ message }}</div>
    • 指令
      指令是一種特殊的屬性,它們帶有 v- 前綴,指示 Vue.js 在模板中添加特殊行為。例如,v-if 指令根據(jù)表達(dá)式的值來?xiàng)l件性地渲染元素。
      <div v-if="showMessage">{{ message }}</div>
    • 綁定屬性
      Vue.js 通過 v-bind 指令來綁定元素的屬性,這使得我們可以使用表達(dá)式來動(dòng)態(tài)綁定屬性值。
      <img v-bind:src="imageUrl">
    • 循環(huán)
      使用 v-for 指令可以循環(huán)渲染列表中的元素。
      <ul> <li v-for="item in items">{{ item }}</li> </ul>
    • 事件綁定
      使用 v-on 指令可以綁定事件處理函數(shù),當(dāng)事件觸發(fā)時(shí)會(huì)執(zhí)行相應(yīng)的函數(shù)。
      <button v-on:click="handleClick">Click me</button>
      以上是一些常用的 Vue 模板語法示例,它們可以通過 Vue.js 的數(shù)據(jù)響應(yīng)系統(tǒng)來實(shí)現(xiàn)數(shù)據(jù)與模板的雙向綁定

1.3 計(jì)算屬性
Vue.js 的計(jì)算屬性是基于 Vue 實(shí)例的數(shù)據(jù)計(jì)算得出的屬性,它們具有緩存特性,只有當(dāng)它們的依賴項(xiàng)發(fā)生變化時(shí)才會(huì)重新計(jì)算。計(jì)算屬性常見的使用場(chǎng)景是對(duì)數(shù)據(jù)進(jìn)行復(fù)雜的計(jì)算,并將計(jì)算結(jié)果作為屬性進(jìn)行渲染。下面是一些常見的計(jì)算屬性的使用示例:
1.3.1 簡(jiǎn)單計(jì)算屬性

<template>
  <div>
    <p>原價(jià): {{ price }}</p>
    <p>折扣價(jià): {{ discountedPrice }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      price: 100,
      discount: 0.2
    }
  },
  computed: {
    discountedPrice() {
      return this.price * (1 - this.discount)
    }
  }
}
</script>

1.3.2 計(jì)算屬性監(jiān)聽其他屬性

<template>
  <div>
    <input v-model="firstName">
    <input v-model="lastName">
    <p>{{ fullName }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      firstName: '',
      lastName: ''
    }
  },
  computed: {
    fullName() {
      return this.firstName + ' ' + this.lastName
    }
  }
}
</script>

1.3.3 計(jì)算屬性使用 get 和 set

<template>
  <div>
    <p>商品數(shù)量: {{ quantity }}</p>
    <button @click="increment">+</button>
    <button @click="decrement">-</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      count: 0
    }
  },
  computed: {
    quantity: {
      get() {
        return this.count
      },
      set(value) {
        this.count = value
      }
    }
  },
  methods: {
    increment() {
      this.quantity += 1
    },
    decrement() {
      this.quantity -= 1
    }
  }
}
</script>

1.4 監(jiān)聽器
Vue.js 的監(jiān)聽器是一種用來監(jiān)聽 Vue 實(shí)例上指定屬性變化的方法,當(dāng)指定屬性發(fā)生變化時(shí),Vue.js 會(huì)自動(dòng)調(diào)用監(jiān)聽器中指定的回調(diào)函數(shù)。監(jiān)聽器常用于在數(shù)據(jù)變化時(shí)執(zhí)行自定義的操作,比如發(fā)送請(qǐng)求、更新其他數(shù)據(jù)等。下面是一些常見的使用場(chǎng)景和示例:
1.4.1 監(jiān)聽簡(jiǎn)單數(shù)據(jù)變化

<template>
  <div>
    <input v-model="message">
    <p>{{ reversedMessage }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      message: 'Hello, Vue!',
      reversedMessage: ''
    }
  },
  watch: {
    message(newValue, oldValue) {
      this.reversedMessage = newValue.split('').reverse().join('')
    }
  }
}
</script>

在以上示例中,監(jiān)聽器會(huì)監(jiān)聽 message 屬性的變化,當(dāng) message 發(fā)生變化時(shí),監(jiān)聽器中的回調(diào)函數(shù)會(huì)將 reversedMessage 屬性更新為 message 的反轉(zhuǎn)字符串。
1.4.2 監(jiān)聽對(duì)象屬性變化

<template>
  <div>
    <p>用戶名: {{ user.name }}</p>
    <p>年齡: {{ user.age }}</p>
    <button @click="incrementAge">加1歲</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      user: {
        name: '張三',
        age: 18
      }
    }
  },
  watch: {
    'user.age'(newValue, oldValue) {
      console.log(`年齡從 ${oldValue} 變?yōu)?${newValue}`)
    }
  },
  methods: {
    incrementAge() {
      this.user.age += 1
    }
  }
}
</script>

在以上示例中,監(jiān)聽器會(huì)監(jiān)聽 user 對(duì)象的 age 屬性變化,當(dāng) age 屬性發(fā)生變化時(shí),監(jiān)聽器中的回調(diào)函數(shù)會(huì)打印出變化的信息。
1.4.3 深度監(jiān)聽數(shù)組和對(duì)象

<template>
  <div>
    <p v-for="item in items">{{ item.name }} - {{ item.price }}</p>
    <button @click="addItem">添加商品</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      items: [
        { name: '商品A', price: 100 },
        { name: '商品B', price: 200 }
      ]
    }
  },
  watch: {
    items: {
      handler(newValue, oldValue) {
        console.log('items 數(shù)組發(fā)生變化')
      },
      deep: true
    }
  },
  methods: {
    addItem() {
      this.items.push({ name: '新商品', price: 300 })
    }
  }
}
</script>

在以上示例中,監(jiān)聽器會(huì)深度監(jiān)聽 items 數(shù)組的變化,當(dāng)數(shù)組中的對(duì)象屬性發(fā)生變化時(shí),監(jiān)聽器中的回調(diào)函數(shù)會(huì)打印出變化的信息。
1.5 組件
Vue.js 的組件是可復(fù)用的 Vue 實(shí)例,每個(gè)組件都可以擁有自己的數(shù)據(jù)、方法和生命周期鉤子等。在 Vue.js 中,我們可以通過 Vue.component() 方法來定義一個(gè)全局組件,也可以通過組件選項(xiàng)來定義一個(gè)局部組件。下面是一些常見的組件定義示例:
1.5.1 全局組件

<template>
  <div>
    <hello-world></hello-world>
  </div>
</template>

<script>
Vue.component('hello-world', {
  template: '<p>Hello, World!</p>'
})
</script>

在以上示例中,我們通過 Vue.component() 方法定義了一個(gè)名為 hello-world 的全局組件,然后在模板中使用該組件。
1.5.2 局部組件

<template>
  <div>
    <custom-button></custom-button>
  </div>
</template>

<script>
import CustomButton from './CustomButton.vue'

export default {
  components: {
    CustomButton
  }
}
</script>

在以上示例中,我們通過組件選項(xiàng) components 來定義了一個(gè)名為 CustomButton 的局部組件,并在模板中使用該組件。注意,這里的 CustomButton 組件是從一個(gè)單獨(dú)的 .vue 文件中導(dǎo)入的。
1.5.3 動(dòng)態(tài)組件

<template>
  <div>
    <component :is="currentComponent"></component>
    <button @click="changeComponent">切換組件</button>
  </div>
</template>

<script>
import FirstComponent from './FirstComponent.vue'
import SecondComponent from './SecondComponent.vue'

export default {
  data() {
    return {
      currentComponent: 'FirstComponent'
    }
  },
  methods: {
    changeComponent() {
      this.currentComponent = this.currentComponent === 'FirstComponent' ? 'SecondComponent' : 'FirstComponent'
    }
  },
  components: {
    FirstComponent,
    SecondComponent
  }
}
</script>

在以上示例中,我們通過 :is 屬性來動(dòng)態(tài)渲染組件,同時(shí)提供一個(gè)按鈕來切換組件。注意,這里的 currentComponent 是一個(gè) data 屬性,我們可以在方法中改變?cè)搶傩詠韯?dòng)態(tài)渲染不同的組件。
1.6 生命周期
Vue.js 的生命周期可以分為八個(gè)階段,分別是 beforeCreate、created、beforeMount、mounted、beforeUpdate、updated、beforeDestroy 和 destroyed。在每個(gè)階段,Vue.js 會(huì)自動(dòng)調(diào)用相應(yīng)的生命周期鉤子函數(shù),我們可以在這些鉤子函數(shù)中執(zhí)行一些初始化操作或清理操作。下面是一些常見的生命周期示例:
1.6.1 beforeCreate 和 created 鉤子

<template>
  <div>
    <p>{{ message }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      message: 'Hello, World!'
    }
  },
  beforeCreate() {
    console.log('beforeCreate')
  },
  created() {
    console.log('created')
  }
}
</script>

1.6.2 beforeMount 和 mounted 鉤子

<template>
  <div>
    <p ref="message">{{ message }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      message: 'Hello, World!'
    }
  },
  beforeMount() {
    console.log('beforeMount')
  },
  mounted() {
    console.log('mounted')
    console.log(this.$refs.message.innerText)
  }
}
</script>

在以上示例中,我們定義了一個(gè)名為 message 的 data 屬性,并在 beforeMount 和 mounted 鉤子函數(shù)中分別打印了日志。beforeMount 鉤子函數(shù)在模板編譯之后,掛載之前被調(diào)用,mounted 鉤子函數(shù)在實(shí)例掛載完成之后被調(diào)用,這兩個(gè)鉤子函數(shù)常用于操作 DOM 元素或執(zhí)行一些異步操作。
1.6.3 beforeUpdate 和 updated 鉤子

<template>
  <div>
    <p>{{ message }}</p>
    <button @click="changeMessage">改變消息</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      message: 'Hello, World!'
    }
  },
  methods: {
    changeMessage() {
      this.message = 'Hello, Vue!'
    }
  },
  beforeUpdate() {
    console.log('beforeUpdate')
  },
  updated() {
    console.log('updated')
  }
}
</script>

在以上示例中,我們定義了一個(gè)名為 message 的 data 屬性,并在 beforeUpdate 和 updated 鉤子函數(shù)中分別打印了日志。beforeUpdate 鉤子函數(shù)在數(shù)據(jù)更新之前被調(diào)用,updated 鉤子函數(shù)在數(shù)據(jù)更新之后被調(diào)用,這兩個(gè)鉤子函數(shù)常用于在數(shù)據(jù)更新之前或之后執(zhí)行一些操作。
1.6.4 beforeDestroy 和 destroyed 鉤子

<template>
  <div>
    <p>{{ message }}</p>
    <button @click="destroy">銷毀實(shí)例</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      message: 'Hello, World!'
    }
  },
  methods: {
    destroy() {
      this.$destroy()
    }
  },
  beforeDestroy() {
    console.log('beforeDestroy')
  },
  destroyed() {
    console.log('destroyed')
  }
}
</script>

1.7 自定義指令
在 Vue.js 中,我們可以通過自定義指令來擴(kuò)展其功能,從而實(shí)現(xiàn)一些非常靈活的操作。下面是一個(gè)簡(jiǎn)單的自定義指令示例:

<template>
  <div>
    <p v-highlight="'yellow'">這是一段需要高亮的文字</p>
  </div>
</template>

<script>
export default {
  directives: {
    highlight: {
      bind(el, binding) {
        el.style.backgroundColor = binding.value
      }
    }
  }
}
</script>

在以上示例中,我們定義了一個(gè)自定義指令 highlight,并在模板中使用了它。指令的作用是將綁定的元素的背景顏色設(shè)置為指定的顏色。在 directives 屬性中定義了 highlight 指令的實(shí)現(xiàn),它有一個(gè) bind 鉤子函數(shù),在指令綁定到元素上時(shí)被調(diào)用。在 bind 鉤子函數(shù)中,我們通過 el 參數(shù)訪問到綁定的元素,通過 binding 參數(shù)訪問到指令的綁定值,然后將背景顏色設(shè)置為綁定值即可。
1.8 渲染函數(shù)
Vue 渲染函數(shù)是一種用 JavaScript 編寫模板的方法,通過編寫 JavaScript 代碼來生成虛擬 DOM,然后將虛擬 DOM 渲染到頁面上。它可以更加靈活地控制頁面的渲染過程,適用于一些需要?jiǎng)討B(tài)生成頁面的場(chǎng)景。

下面是 Vue 渲染函數(shù)的常見用法示例代碼:

Vue.component('my-component', {
  render: function (createElement) {
    return createElement(
      'div',
      {
        attrs: {
          id: 'my-component'
        }
      },
      [
        createElement('h1', 'Hello World!'),
        createElement('p', 'This is my component.')
      ]
    )
  }
})

在上面的代碼中,我們定義了一個(gè)名為 my-component 的組件,通過 render 方法返回一個(gè)虛擬 DOM,其中使用了 createElement 方法來創(chuàng)建元素節(jié)點(diǎn)。在 createElement 方法中,第一個(gè)參數(shù)為標(biāo)簽名或組件名,第二個(gè)參數(shù)為元素的屬性對(duì)象,第三個(gè)參數(shù)為元素的子節(jié)點(diǎn)數(shù)組。
在實(shí)際開發(fā)中,我們可以通過編寫 JavaScript 代碼來動(dòng)態(tài)生成虛擬 DOM,從而更加靈活地控制頁面的渲染過程。

  • 插件
    Vue 插件是一種可以擴(kuò)展 Vue 功能的方式,它可以為 Vue 添加全局的功能或者組件。通常情況下,Vue 插件會(huì)暴露一個(gè) install 方法,該方法會(huì)在 Vue 實(shí)例化之前被調(diào)用,從而可以在 Vue 實(shí)例化之前對(duì)其進(jìn)行一些初始化或者注冊(cè)全局組件等操作。

下面是一個(gè)示例代碼,演示了如何編寫一個(gè) Vue 插件:

// 定義插件
const myPlugin = {
  install: function (Vue, options) {
    // 添加全局方法或?qū)傩?    Vue.myGlobalMethod = function () {
      // 全局方法的邏輯代碼
    }

    // 添加全局組件
    Vue.component('my-component', {
      // 組件的選項(xiàng)
    })

    // 添加實(shí)例方法
    Vue.prototype.$myMethod = function (options) {
      // 實(shí)例方法的邏輯代碼
    }
  }
}

// 使用插件
Vue.use(myPlugin)

在上面的代碼中,我們定義了一個(gè)名為 myPlugin 的插件,該插件暴露了一個(gè) install 方法。在 install 方法中,我們可以添加全局方法、屬性、組件以及實(shí)例方法等。在使用插件時(shí),我們可以通過 Vue.use 方法來安裝插件,從而將插件添加到 Vue 中。

例如,在上面的代碼中,我們添加了一個(gè)名為 myGlobalMethod 的全局方法,一個(gè)名為 my-component 的全局組件,以及一個(gè)名為 $myMethod 的實(shí)例方法。在使用插件后,我們就可以在任何 Vue 實(shí)例中使用這些方法或組件了。

需要注意的是,Vue 插件通常會(huì)提供一些選項(xiàng)參數(shù),以便用戶在安裝插件時(shí)進(jìn)行配置。在上面的代碼中,我們將選項(xiàng)參數(shù)傳遞給了 install 方法的第二個(gè)參數(shù) options 中。

  1. Vue組件
    2.1 組件通信
    Vue 組件通信是指在不同的 Vue 組件之間進(jìn)行數(shù)據(jù)傳遞和交互的過程。Vue 提供了多種組件通信的方式,包括 props、事件、插槽等。下面是一些常見的 Vue 組件通信示例代碼:
    2.1.1 父子組件通信 - 使用 props
// 父組件
<template>
  <div>
    <child-component :message="parentMessage"></child-component>
  </div>
</template>

<script>
  import ChildComponent from './ChildComponent.vue'

  export default {
    components: {
      ChildComponent
    },
    data () {
      return {
        parentMessage: 'Hello from parent'
      }
    }
  }
</script>

// 子組件
<template>
  <div>
    {{ message }}
  </div>
</template>

<script>
  export default {
    props: {
      message: String
    }
  }
</script>

在上面的代碼中,我們使用了 props 屬性將父組件中的數(shù)據(jù)傳遞給了子組件。在父組件中,我們通過 :message 的方式將 parentMessage 數(shù)據(jù)傳遞給了子組件。在子組件中,我們使用 props 屬性來聲明 message 屬性,從而接收父組件傳遞過來的數(shù)據(jù)。
2.1.2 子父組件通信 - 使用事件

// 父組件
<template>
  <div>
    <child-component @emit-message="handleMessage"></child-component>
  </div>
</template>

<script>
  import ChildComponent from './ChildComponent.vue'

  export default {
    components: {
      ChildComponent
    },
    methods: {
      handleMessage (message) {
        console.log(message)
      }
    }
  }
</script>

// 子組件
<template>
  <div>
    <button @click="emitMessage">Click me</button>
  </div>
</template>

<script>
  export default {
    methods: {
      emitMessage () {
        this.$emit('emit-message', 'Hello from child')
      }
    }
  }
</script>

在上面的代碼中,我們使用了 $emit 方法將子組件中的事件傳遞給了父組件。在子組件中,我們通過 emitMessage 方法觸發(fā)了 emit-message 事件,并將數(shù)據(jù) 'Hello from child' 作為參數(shù)傳遞給了該事件。在父組件中,我們使用 @emit-message 的方式監(jiān)聽了該事件,并在 handleMessage 方法中處理了傳遞過來的數(shù)據(jù)。
2.1.3 兄弟組件通信 - 使用事件總線

// 創(chuàng)建事件總線
export const eventBus = new Vue()

// 組件A
<template>
  <div>
    <button @click="sendMessage">Send message</button>
  </div>
</template>

<script>
  import { eventBus } from './event-bus.js'

  export default {
    methods: {
      sendMessage () {
        eventBus.$emit('message', 'Hello from A')
      }
    }
  }
</script>

// 組件B
<template>
  <div>
    {{ message }}
  </div>
</template>

<script>
  import { eventBus } from './event-bus.js'

  export default {
    data () {
      return {
        message: ''
      }
    },
    created () {
      eventBus.$on('message', message => {
        this.message = message
      })
    }
  }
</script>

在上面的代碼中,我們創(chuàng)建了一個(gè)名為 eventBus 的事件總線,并將其導(dǎo)出。在組件A中,我們使用 $emit 方法觸發(fā)了名為 message 的事件,并將數(shù)據(jù) 'Hello from A' 作為參數(shù)傳遞給了該事件。在組件B中,我們使用 $on 方法監(jiān)聽了名為 message 的事件,并在回調(diào)函數(shù)中處理了傳遞過來的數(shù)據(jù)。由于事件總線是全局的,因此可以在任何組件中使用該方式進(jìn)行通信。
2.2 組件生命周期
Vue 組件生命周期是指 Vue 組件從創(chuàng)建到銷毀的整個(gè)過程中,會(huì)經(jīng)歷一系列的生命周期鉤子函數(shù),這些鉤子函數(shù)會(huì)在不同的階段執(zhí)行,用于完成不同的任務(wù)。下面是 Vue 組件生命周期的常見鉤子函數(shù)以及使用示例代碼:
2.2.1 beforeCreate
在組件實(shí)例被創(chuàng)建之初,beforeCreate 鉤子函數(shù)會(huì)被調(diào)用,此時(shí)組件的數(shù)據(jù)和方法都還未初始化。

export default {
  beforeCreate () {
    console.log('beforeCreate')
  }
}

2.2.2 created
在組件實(shí)例創(chuàng)建完成之后,created 鉤子函數(shù)會(huì)被調(diào)用,此時(shí)組件的數(shù)據(jù)和方法已經(jīng)初始化完成,但 DOM 元素還未生成。

export default {
  created () {
    console.log('created')
  }
}

2.2.3 beforeMount
在組件掛載到 DOM 元素之前,beforeMount 鉤子函數(shù)會(huì)被調(diào)用。

export default {
  beforeMount () {
    console.log('beforeMount')
  }
}

2.2.4 mounted
在組件掛載到 DOM 元素之后,mounted 鉤子函數(shù)會(huì)被調(diào)用,此時(shí)組件已經(jīng)渲染完成。

export default {
  mounted () {
    console.log('mounted')
  }
}

2.2.5 beforeUpdate
在組件更新之前,beforeUpdate 鉤子函數(shù)會(huì)被調(diào)用。

export default {
  beforeUpdate () {
    console.log('beforeUpdate')
  }
}

2.2.6 updated
在組件更新之后,updated 鉤子函數(shù)會(huì)被調(diào)用。

export default {
  updated () {
    console.log('updated')
  }
}

2.2.7 beforeDestroy
在組件銷毀之前,beforeDestroy 鉤子函數(shù)會(huì)被調(diào)用。

export default {
  beforeDestroy () {
    console.log('beforeDestroy')
  }
}

2.2.8 destroyed
在組件銷毀之后,destroyed 鉤子函數(shù)會(huì)被調(diào)用。

export default {
  destroyed () {
    console.log('destroyed')
  }
}

以上是 Vue 組件生命周期的常見鉤子函數(shù)以及使用示例代碼。在實(shí)際開發(fā)中,我們可以利用這些鉤子函數(shù)來完成一些特定的任務(wù),比如在 created 鉤子函數(shù)中發(fā)起網(wǎng)絡(luò)請(qǐng)求,或者在 mounted 鉤子函數(shù)中初始化一些插件等。
2.3 父子組件通信
在 Vue 中,父子組件之間的通信是非常常見的需求。Vue 提供了多種方式來實(shí)現(xiàn)父子組件之間的通信,下面是其中的兩種方式:
2.3.1 Props
通過 props 將父組件的數(shù)據(jù)傳遞給子組件,子組件通過 props 接收父組件傳遞過來的數(shù)據(jù)。這是 Vue 中最基本、最常用的一種方式。
在父組件中,我們可以通過 v-bind 或簡(jiǎn)寫的 : 來傳遞數(shù)據(jù):

<template>
  <div>
    <ChildComponent :message="message"></ChildComponent>
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue'

export default {
  components: {
    ChildComponent
  },
  data () {
    return {
      message: 'Hello World'
    }
  }
}
</script>

在子組件中,我們可以通過 props 接收父組件傳遞過來的數(shù)據(jù):

<template>
  <div>{{ message }}</div>
</template>

<script>
export default {
  props: {
    message: String
  }
}
</script>

2.3.2 emit 在子組件中,通過emit 觸發(fā)一個(gè)自定義事件,并攜帶參數(shù),父組件通過 v-on 或簡(jiǎn)寫的 @ 監(jiān)聽這個(gè)自定義事件,并處理子組件傳遞過來的數(shù)據(jù)。
在子組件中,我們可以通過 $emit 觸發(fā)一個(gè)自定義事件:

<template>
  <button @click="handleClick">Click me</button>
</template>

<script>
export default {
  methods: {
    handleClick () {
      this.$emit('custom-event', 'Hello World')
    }
  }
}
</script>

在父組件中,我們可以通過 v-on 或簡(jiǎn)寫的 @ 監(jiān)聽這個(gè)自定義事件,并處理子組件傳遞過來的數(shù)據(jù):

<template>
  <div>
    <ChildComponent @custom-event="handleCustomEvent"></ChildComponent>
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue'

export default {
  components: {
    ChildComponent
  },
  methods: {
    handleCustomEvent (data) {
      console.log(data) // 輸出 "Hello World"
    }
  }
}
</script>

以上是 Vue 父子組件通信的兩種方式以及使用示例代碼。在實(shí)際開發(fā)中,我們可以根據(jù)具體的需求選擇合適的方式來實(shí)現(xiàn)父子組件之間的通信。
2.4 非父子組件通信
在 Vue 中,非父子組件之間的通信是指兩個(gè)沒有直接關(guān)系的組件之間的通信,比如兄弟組件、跨級(jí)組件等。Vue 提供了多種方式來實(shí)現(xiàn)非父子組件之間的通信,下面是其中的兩種方式:
2.4.1 Event Bus
Event Bus 是一種常見的非父子組件通信方式,它利用一個(gè)空的 Vue 實(shí)例作為中央事件總線(或者叫事件中心),用來傳遞事件和數(shù)據(jù)。

// EventBus.js
import Vue from 'vue'
export default new Vue()

// ComponentA.vue
import EventBus from './EventBus.js'

export default {
  methods: {
    handleClick () {
      EventBus.$emit('custom-event', 'Hello World')
    }
  }
}

// ComponentB.vue
import EventBus from './EventBus.js'

export default {
  mounted () {
    EventBus.$on('custom-event', data => {
      console.log(data) // 輸出 "Hello World"
    })
  }
}

2.4.2 Vuex
Vuex 是 Vue 的狀態(tài)管理庫,它提供了一種集中式管理應(yīng)用所有組件的狀態(tài)的方式,也可以用來實(shí)現(xiàn)非父子組件之間的通信。

// store.js
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    message: 'Hello World'
  },
  mutations: {
    setMessage (state, message) {
      state.message = message
    }
  }
})

// ComponentA.vue
export default {
  methods: {
    handleClick () {
      this.$store.commit('setMessage', 'Hello World')
    }
  }
}

// ComponentB.vue
export default {
  computed: {
    message () {
      return this.$store.state.message
    }
  }
}

以上是 Vue 非父子組件通信的兩種方式以及使用示例代碼。在實(shí)際開發(fā)中,我們可以根據(jù)具體的需求選擇合適的方式來實(shí)現(xiàn)非父子組件之間的通信。
2.5 動(dòng)態(tài)組件
Vue 動(dòng)態(tài)組件是一種常見的組件復(fù)用方式,它可以根據(jù)組件的數(shù)據(jù)來動(dòng)態(tài)地選擇要渲染的組件。下面是 Vue 動(dòng)態(tài)組件的常見用法示例代碼:

<template>
  <div>
    <component :is="currentComponent"></component>
    <button @click="toggleComponent">Toggle Component</button>
  </div>
</template>

<script>
import ComponentA from './ComponentA.vue'
import ComponentB from './ComponentB.vue'

export default {
  components: {
    ComponentA,
    ComponentB
  },
  data () {
    return {
      currentComponent: 'ComponentA'
    }
  },
  methods: {
    toggleComponent () {
      this.currentComponent = this.currentComponent === 'ComponentA' ? 'ComponentB' : 'ComponentA'
    }
  }
}
</script>

在上面的示例代碼中,我們通過 component 標(biāo)簽來渲染動(dòng)態(tài)組件,并通過 :is 屬性指定要渲染的組件。在 data 中定義了一個(gè) currentComponent 變量,初始值為 ComponentA,表示默認(rèn)渲染 ComponentA 組件。在 toggleComponent 方法中,我們通過判斷當(dāng)前渲染的組件來動(dòng)態(tài)地切換要渲染的組件。
需要注意的是,動(dòng)態(tài)組件的名稱必須是一個(gè)字符串或一個(gè)組件選項(xiàng)對(duì)象,不能是一個(gè)變量或表達(dá)式。如果需要渲染一個(gè)動(dòng)態(tài)組件列表,可以使用 v-for 循環(huán)來渲染多個(gè)動(dòng)態(tài)組件。

2.6 組件注冊(cè)
在 Vue 中,組件可以通過 Vue.component 方法或者單文件組件來注冊(cè)。下面是兩種方式的示例代碼:
2.6.1 Vue.component 方法注冊(cè)組件

<template>
  <div>
    <my-component></my-component>
  </div>
</template>

<script>
import MyComponent from './MyComponent.vue'

export default {
  components: {
    'my-component': MyComponent
  }
}
</script>

在上面的示例代碼中,我們通過 Vue.component 方法來注冊(cè)一個(gè)名為 my-component 的組件,它的定義在 MyComponent.vue 文件中。在組件選項(xiàng)中,我們通過 components 屬性將 my-component 組件注冊(cè)到當(dāng)前組件中。在模板中,我們可以像普通 HTML 標(biāo)簽一樣使用 my-component 組件。
2.6.2 單文件組件注冊(cè)組件

<template>
  <div>
    <my-component></my-component>
  </div>
</template>

<script>
import MyComponent from './MyComponent.vue'

export default {
  components: {
    'my-component': MyComponent
  }
}
</script>

<style>
/* 樣式代碼 */
</style>

在上面的示例代碼中,我們通過單文件組件的方式來注冊(cè)一個(gè)名為 my-component 的組件,它的定義在同一個(gè)文件中的 <script> 標(biāo)簽中。在組件選項(xiàng)中,我們同樣通過 components 屬性將 my-component 組件注冊(cè)到當(dāng)前組件中。在模板中和樣式中,我們可以像普通 HTML 標(biāo)簽和 CSS 樣式一樣使用 my-component 組件。
需要注意的是,組件名必須是一個(gè) kebab-case 形式的字符串,即使用短橫線分隔單詞。在模板中使用組件時(shí),組件名也必須是 kebab-case 形式的字符串。
2.7 組件props
2.7.1 基本用法:在子組件中定義 props,然后在父組件中通過屬性綁定傳遞數(shù)據(jù)。

// 子組件
Vue.component('child-component', {
  props: ['message'],
  template: '<div>{{ message }}</div>'
});

// 父組件
<template>
  <div>
    <child-component :message="'Hello World'"></child-component>
  </div>
</template>

2.7.2 指定 props 的類型和默認(rèn)值:

// 子組件
Vue.component('child-component', {
  props: {
    message: {
      type: String,
      required: true,
      default: 'Hello World'
    }
  },
  template: '<div>{{ message }}</div>'
});

// 父組件
<template>
  <div>
    <child-component :message="'Hello Vue'"></child-component>
  </div>
</template>

2.7.3 使用 props 來觸發(fā)事件:

// 子組件
Vue.component('child-component', {
  props: ['message'],
  template: '<button @click="$emit(\'custom-event\', message)">Click me!</button>'
});

// 父組件
<template>
  <div>
    <child-component :message="'Hello Vue'" @custom-event="handleCustomEvent"></child-component>
  </div>
</template>

<script>
export default {
  methods: {
    handleCustomEvent(message) {
      console.log(message);
    }
  }
}
</script>
  1. Vue路由
    3.1 安裝Vue Router
    3.1.1 npm 安裝npm install vue-router
    3.1.2 安裝完成后,在您的 Vue 應(yīng)用程序中導(dǎo)入 Vue Router:
import Vue from 'vue'
import VueRouter from 'vue-router'

Vue.use(VueRouter)

3.1.3 創(chuàng)建一個(gè)路由實(shí)例并將其添加到 Vue 實(shí)例中:

const router = new VueRouter({
  routes: [
    // 定義路由
    { path: '/home', component: Home },
    { path: '/about', component: About },
    { path: '/contact', component: Contact }
  ]
})

new Vue({
  router,
  el: '#app',
  render: h => h(App)
})

3.2 路由配置
Vue Router 是 Vue.js 官方的路由管理器。它允許您在 Vue 應(yīng)用程序中定義路由,以便用戶在瀏覽器中導(dǎo)航到不同的頁面或視圖。以下是 Vue 路由配置的常見用法:
3.2.1 基本用法:定義路由和組件

import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from './components/Home.vue'
import About from './components/About.vue'

Vue.use(VueRouter)

const router = new VueRouter({
  routes: [
    { path: '/', component: Home },
    { path: '/about', component: About }
  ]
})

new Vue({
  router,
  el: '#app'
})

在這個(gè)示例中,我們定義了兩個(gè)路由,一個(gè)是根路徑 / 對(duì)應(yīng) Home 組件,另一個(gè)是 /about 對(duì)應(yīng) About 組件。我們還創(chuàng)建了一個(gè) router 實(shí)例,并將其傳遞給 Vue 實(shí)例。
3.2.2 帶參數(shù)的路由

import Vue from 'vue'
import VueRouter from 'vue-router'
import User from './components/User.vue'

Vue.use(VueRouter)

const router = new VueRouter({
  routes: [
    { path: '/user/:id', component: User }
  ]
})

new Vue({
  router,
  el: '#app'
})

在這個(gè)示例中,我們定義了一個(gè) /user/:id 路由,其中 :id 是一個(gè)參數(shù)。當(dāng)用戶訪問 /user/123 路徑時(shí),Vue Router 會(huì)將參數(shù) 123 傳遞給 User 組件。
3.2.3 嵌套路由

import Vue from 'vue'
import VueRouter from 'vue-router'
import User from './components/User.vue'
import UserProfile from './components/UserProfile.vue'
import UserPosts from './components/UserPosts.vue'

Vue.use(VueRouter)

const router = new VueRouter({
  routes: [
    { 
      path: '/user/:id', 
      component: User,
      children: [
        {
          path: '',
          component: UserProfile
        },
        {
          path: 'posts',
          component: UserPosts
        }
      ]
    }
  ]
})

new Vue({
  router,
  el: '#app'
})

在這個(gè)示例中,我們定義了一個(gè) /user/:id 路由,并將其嵌套在 User 組件中。在 User 組件中,我們定義了兩個(gè)子路由:一個(gè)是空路徑對(duì)應(yīng) UserProfile 組件,另一個(gè)是 /posts 對(duì)應(yīng) UserPosts 組件。
這些是 Vue 路由配置的一些常見用法。使用這些功能,您可以創(chuàng)建復(fù)雜的單頁應(yīng)用程序,并使用戶能夠輕松地導(dǎo)航到不同的頁面或視圖。
3.3 路由導(dǎo)航
Vue Router 提供了許多用于導(dǎo)航的功能,以下是一些常見的路由導(dǎo)航功能:
3.3.1 聲明式導(dǎo)航
使用 <router-link> 組件可以在 Vue 應(yīng)用程序中聲明式地導(dǎo)航。例如:

<router-link to="/home">Home</router-link>

這會(huì)創(chuàng)建一個(gè)鏈接,當(dāng)用戶單擊它時(shí),它會(huì)導(dǎo)航到 /home 路徑。
3.3.2 編程式導(dǎo)航
您可以使用 $router 對(duì)象進(jìn)行編程式導(dǎo)航。例如:

// 在當(dāng)前路由下導(dǎo)航到 /home
this.$router.push('/home')

// 在當(dāng)前路由下導(dǎo)航到 /about,并保留瀏覽歷史記錄
this.$router.push({ path: '/about', preserveQueryParams: true })

// 在當(dāng)前路由下導(dǎo)航到 /user/123
this.$router.push('/user/123')

// 在當(dāng)前路由下導(dǎo)航到 /user/123,并保留查詢參數(shù)
this.$router.push({ path: '/user/123', query: { foo: 'bar' } })

// 在當(dāng)前路由下導(dǎo)航到一個(gè)命名路由
this.$router.push({ name: 'user', params: { id: 123 } })

3.3.3 動(dòng)態(tài)路由
您可以在路由路徑中使用參數(shù)來創(chuàng)建動(dòng)態(tài)路由。例如:

const router = new VueRouter({
  routes: [
    { path: '/user/:id', component: User }
  ]
})

在這個(gè)示例中,我們定義了一個(gè) /user/:id 路由,其中 :id 是一個(gè)參數(shù)。當(dāng)用戶訪問 /user/123 路徑時(shí),Vue Router 會(huì)將參數(shù) 123 傳遞給 User 組件。
3.3.4 命名路由
您可以為路由定義一個(gè)名稱,并在導(dǎo)航時(shí)使用該名稱。例如:

const router = new VueRouter({
  routes: [
    { path: '/user/:id', component: User, name: 'user' }
  ]
})

// 在代碼中使用命名路由
this.$router.push({ name: 'user', params: { id: 123 } })

3.3.5 重定向和別名
您可以使用重定向和別名來更改路由的行為。例如:

const router = new VueRouter({
  routes: [
    { path: '/home', component: Home },
    { path: '/about', component: About },
    { path: '*', redirect: '/home' },
    { path: '/contact', component: Contact, alias: '/contact-us' }
  ]
})

在這個(gè)示例中,我們定義了一個(gè) * 路由,它會(huì)將所有未匹配的路徑重定向到 /home 路徑。我們還定義了一個(gè) /contact 路由,并為它定義了一個(gè)別名 /contact-us。
這些是 Vue Router 中一些常見的路由導(dǎo)航功能。使用這些功能,您可以輕松地創(chuàng)建復(fù)雜的單頁應(yīng)用程序,并使用戶能夠輕松地導(dǎo)航到不同的頁面或視圖。
3.6 命名路由
Vue 命名路由的常見用法是在路由定義中為路由指定一個(gè)名稱,然后在代碼中使用該名稱來導(dǎo)航到該路由。以下是一些常見的用法示例代碼:
3.6.1 簡(jiǎn)單的命名路由

const router = new VueRouter({
  routes: [
    {
      path: '/home',
      component: Home,
      name: 'home'
    }
  ]
})

在這個(gè)示例中,我們?yōu)?/home 路由指定了一個(gè)名稱 home。我們可以在代碼中使用 $router.push 方法來導(dǎo)航到該路由:

this.$router.push({ name: 'home' })

3.6.2 帶參數(shù)的命名路由

const router = new VueRouter({
  routes: [
    {
      path: '/user/:id',
      component: User,
      name: 'user'
    }
  ]
})

在這個(gè)示例中,我們?yōu)?/user/:id 路由指定了一個(gè)名稱 user。我們可以在代碼中使用 $router.push 方法來導(dǎo)航到該路由,并傳遞參數(shù):

this.$router.push({ name: 'user', params: { id: 123 } })

3.6.3 嵌套命名路由

const router = new VueRouter({
  routes: [
    {
      path: '/user/:id',
      component: User,
      children: [
        {
          path: 'profile',
          component: Profile,
          name: 'user-profile'
        },
        {
          path: 'posts',
          component: Posts,
          name: 'user-posts'
        }
      ]
    }
  ]
})

在這個(gè)示例中,我們定義了一個(gè) /user/:id 路由,它有兩個(gè)子路由:/user/:id/profile 和 /user/:id/posts。我們?yōu)檫@兩個(gè)子路由分別指定了名稱 user-profile 和 user-posts。我們可以在代碼中使用 $router.push 方法來導(dǎo)航到這些子路由:

this.$router.push({ name: 'user-profile', params: { id: 123 } })
this.$router.push({ name: 'user-posts', params: { id: 123 } })

這些示例演示了 Vue 命名路由的常見用法。使用命名路由可以使代碼更具可讀性和可維護(hù)性,并使導(dǎo)航更加靈活。
3.7 嵌套路由
Vue 嵌套路由是指在一個(gè)路由下定義多個(gè)子路由,這些子路由可以有自己的組件和路徑,從而實(shí)現(xiàn)更加靈活的頁面結(jié)構(gòu)。以下是一些常見的 Vue 嵌套路由用法示例代碼:
3.7.1 基本的嵌套路由

const router = new VueRouter({
  routes: [
    {
      path: '/home',
      component: Home,
      children: [
        {
          path: 'news',
          component: News
        },
        {
          path: 'about',
          component: About
        }
      ]
    }
  ]
})

在這個(gè)示例中,我們定義了一個(gè) /home 路由,它有兩個(gè)子路由:/home/news 和 /home/about。我們可以在 Home 組件中使用 <router-view> 標(biāo)簽來渲染這些子路由。
3.7.2 帶參數(shù)的嵌套路由

const router = new VueRouter({
  routes: [
    {
      path: '/user/:id',
      component: User,
      children: [
        {
          path: 'profile',
          component: Profile
        },
        {
          path: 'posts',
          component: Posts
        }
      ]
    }
  ]
})

在這個(gè)示例中,我們定義了一個(gè) /user/:id 路由,它有兩個(gè)子路由:/user/:id/profile 和 /user/:id/posts。這些子路由都可以訪問 User 組件中的 id 參數(shù)。
3.7.3 命名視圖的嵌套路由

const router = new VueRouter({
  routes: [
    {
      path: '/home',
      components: {
        default: Home,
        sidebar: Sidebar
      },
      children: [
        {
          path: 'news',
          components: {
            default: News,
            sidebar: NewsSidebar
          }
        },
        {
          path: 'about',
          components: {
            default: About,
            sidebar: AboutSidebar
          }
        }
      ]
    }
  ]
})

在這個(gè)示例中,我們定義了一個(gè) /home 路由,它有兩個(gè)子路由:/home/news 和 /home/about。我們使用命名視圖來為每個(gè)路由指定多個(gè)組件。例如,我們?yōu)?/home 路由指定了 Home 組件和 Sidebar 組件,為 /home/news 路由指定了 News 組件和 NewsSidebar 組件。

這些示例演示了 Vue 嵌套路由的常見用法。使用嵌套路由可以使頁面結(jié)構(gòu)更加靈活,同時(shí)也可以提高代碼的可讀性和可維護(hù)性。
3.7.4 命名視圖的進(jìn)一步說明
Vue 命名視圖(Named Views)是一種高級(jí)的路由技術(shù),它允許我們?cè)谝粋€(gè)路由中同時(shí)渲染多個(gè)視圖。通常情況下,一個(gè)路由只會(huì)渲染一個(gè)視圖,這個(gè)視圖通常是一個(gè)單文件組件。但是,在某些場(chǎng)景下,我們可能需要在一個(gè)路由中渲染多個(gè)視圖,例如在一個(gè)頁面中同時(shí)顯示主要內(nèi)容和側(cè)邊欄。
使用命名視圖可以讓我們?cè)谝粋€(gè)路由中指定多個(gè)組件,并且讓這些組件分別渲染到不同的視圖中。例如,在以下代碼中:

const router = new VueRouter({
  routes: [
    {
      path: '/home',
      components: {
        default: Home,
        sidebar: Sidebar
      }
    }
  ]
})

我們?yōu)?/home 路由指定了兩個(gè)組件:Home 組件和 Sidebar 組件。其中,Home 組件會(huì)被渲染到默認(rèn)的視圖中,而 Sidebar 組件會(huì)被渲染到名為 sidebar 的命名視圖中。在使用命名視圖時(shí),我們需要在模板中使用 <router-view> 標(biāo)簽來指定每個(gè)視圖的位置,例如:

<template>
  <div>
    <router-view></router-view>
    <router-view name="sidebar"></router-view>
  </div>
</template>

在這個(gè)模板中,我們使用了兩個(gè) <router-view> 標(biāo)簽來分別指定默認(rèn)視圖和命名視圖的位置。其中,命名視圖需要使用 name 屬性來指定視圖的名稱。
使用命名視圖可以讓我們更加靈活地組織頁面結(jié)構(gòu),同時(shí)也可以提高代碼的可讀性和可維護(hù)性。但是,在使用命名視圖時(shí)需要注意一些問題,例如在定義路由時(shí)需要使用 components 屬性來指定多個(gè)組件,而不是使用 component 屬性來指定單個(gè)組件。此外,在模板中也需要使用正確的命名視圖名稱來渲染對(duì)應(yīng)的組件。

3.8 路由參數(shù)
在 Vue 中,我們可以使用路由參數(shù)來傳遞數(shù)據(jù)。路由參數(shù)是指在路由路徑中包含的動(dòng)態(tài)參數(shù),例如 /user/:id 中的 :id 就是一個(gè)路由參數(shù)。我們可以使用 $route.params 來訪問當(dāng)前路由的參數(shù)。除了路由參數(shù),我們還可以使用查詢參數(shù)(Query Parameters)來傳遞數(shù)據(jù),查詢參數(shù)是指在 URL 中以 ? 開頭的鍵值對(duì),例如 /user?id=123 中的 id=123 就是一個(gè)查詢參數(shù)。我們可以使用 $route.query 來訪問當(dāng)前路由的查詢參數(shù)。
下面是幾個(gè)常見的路由參數(shù)傳遞的用法:
3.8.1 動(dòng)態(tài)路由
動(dòng)態(tài)路由是指在路由路徑中包含動(dòng)態(tài)參數(shù)的路由,例如 /user/:id。我們可以使用動(dòng)態(tài)路由來實(shí)現(xiàn)根據(jù)用戶 ID 顯示不同用戶信息的功能。以下是一個(gè)動(dòng)態(tài)路由的示例代碼:

const router = new VueRouter({
  routes: [
    {
      path: '/user/:id',
      component: User
    }
  ]
})

// User.vue
<template>
  <div>
    User ID: {{ $route.params.id }}
  </div>
</template>

在這個(gè)示例中,我們定義了一個(gè)動(dòng)態(tài)路由 /user/:id,并且在 User 組件中通過 $route.params.id 訪問了當(dāng)前路由的參數(shù)。
3.8.2 命名路由
命名路由是指給一個(gè)路由設(shè)置一個(gè)名稱,以便在代碼中進(jìn)行跳轉(zhuǎn)或傳遞參數(shù)。命名路由可以讓我們?cè)诖a中使用路由名稱來跳轉(zhuǎn)路由,而不必?fù)?dān)心路由路徑的變化。以下是一個(gè)命名路由的示例代碼:

const router = new VueRouter({
  routes: [
    {
      path: '/user/:id',
      name: 'user',
      component: User
    }
  ]
})

// 跳轉(zhuǎn)到命名路由
<router-link :to="{ name: 'user', params: { id: 123 }}">User</router-link>

// User.vue
<template>
  <div>
    User ID: {{ $route.params.id }}
  </div>
</template>

在這個(gè)示例中,我們定義了一個(gè)命名路由 user,并且在代碼中使用 <router-link> 標(biāo)簽來跳轉(zhuǎn)到該路由。在 User 組件中,我們?nèi)匀豢梢酝ㄟ^ $route.params.id 訪問當(dāng)前路由的參數(shù)。
3.8.3 查詢參數(shù)
查詢參數(shù)是指在 URL 中以 ? 開頭的鍵值對(duì),例如 /user?id=123 中的 id=123 就是一個(gè)查詢參數(shù)。我們可以使用查詢參數(shù)來傳遞一些非必要的參數(shù),例如分頁信息、搜索關(guān)鍵字等。以下是一個(gè)查詢參數(shù)的示例代碼:

const router = new VueRouter({
  routes: [
    {
      path: '/user',
      component: User
    }
  ]
})

// 跳轉(zhuǎn)到帶查詢參數(shù)的路由
<router-link :to="{ path: '/user', query: { id: 123 }}">User</router-link>

// User.vue
<template>
  <div>
    User ID: {{ $route.query.id }}
  </div>
</template>

在這個(gè)示例中,我們定義了一個(gè)路由 /user,并且在 <router-link> 標(biāo)簽中使用 query 屬性來傳遞查詢參數(shù)。在 User 組件中,我們使用 $route.query.id 訪問當(dāng)前路由的查詢參數(shù)。

3.9 路由組件傳參
在 Vue 中,我們可以使用路由組件傳參來實(shí)現(xiàn)組件之間的數(shù)據(jù)傳遞。路由組件傳參是指通過路由配置傳遞數(shù)據(jù)給組件的一種方式。以下是幾個(gè)常見的路由組件傳參的用法:
3.9.1 props
我們可以在路由配置中使用 props 屬性來傳遞數(shù)據(jù)給組件。props 屬性可以是一個(gè)對(duì)象或一個(gè)函數(shù),用來將路由參數(shù)映射為組件的屬性。以下是一個(gè)使用 props 屬性傳遞數(shù)據(jù)的示例代碼:

const router = new VueRouter({
  routes: [
    {
      path: '/user/:id',
      component: User,
      props: true
    }
  ]
})

// User.vue
<template>
  <div>
    User ID: {{ id }}
  </div>
</template>

<script>
export default {
  props: {
    id: {
      type: Number,
      required: true
    }
  }
}
</script>

在這個(gè)示例中,我們?cè)诼酚膳渲弥性O(shè)置了 props: true,表示將路由參數(shù)作為組件的屬性傳遞。在 User 組件中,我們定義了一個(gè) id 屬性,并且在 props 中聲明了該屬性的類型和是否必須。在模板中,我們使用 {{ id }} 訪問該屬性。
3.9.2 字符串
除了使用 props 屬性,我們還可以在路由路徑中使用字符串傳遞數(shù)據(jù)。例如,我們可以定義一個(gè)帶有參數(shù)的路由 /user/:id,并且在代碼中通過 $route.params.id 訪問該參數(shù)。以下是一個(gè)使用字符串傳遞數(shù)據(jù)的示例代碼:

const router = new VueRouter({
  routes: [
    {
      path: '/user/:id',
      component: User
    }
  ]
})

// User.vue
<template>
  <div>
    User ID: {{ $route.params.id }}
  </div>
</template>

在這個(gè)示例中,我們定義了一個(gè)帶有參數(shù)的路由 /user/:id,并且在 User 組件中通過 $route.params.id 訪問該參數(shù)。
3.9.3 對(duì)象
除了使用 props 屬性和字符串,我們還可以在路由配置中使用對(duì)象傳遞數(shù)據(jù)。對(duì)象傳遞數(shù)據(jù)可以用來傳遞一些非路由參數(shù)的數(shù)據(jù),例如頁面標(biāo)題、面包屑導(dǎo)航等。以下是一個(gè)使用對(duì)象傳遞數(shù)據(jù)的示例代碼:

const router = new VueRouter({
  routes: [
    {
      path: '/user/:id',
      component: User,
      meta: {
        title: 'User Profile'
      }
    }
  ]
})

// User.vue
<script>
export default {
  metaInfo() {
    return {
      title: this.$route.meta.title
    }
  }
}
</script>

在這個(gè)示例中,我們?cè)诼酚膳渲弥性O(shè)置了一個(gè) meta 對(duì)象,用來傳遞頁面標(biāo)題。在 User 組件中,我們使用 metaInfo 函數(shù)來動(dòng)態(tài)設(shè)置頁面標(biāo)題,通過 $route.meta.title 訪問該標(biāo)題。

  1. Vue狀態(tài)管理
    4.1 安裝Vuex
    4.1.1 首先,使用npm安裝Vuex。在終端中,進(jìn)入Vue項(xiàng)目的根目錄并運(yùn)行以下命令:
    npm install vuex --save
    4.1.2 安裝完成后,在Vue項(xiàng)目的main.js文件中導(dǎo)入Vuex并創(chuàng)建一個(gè)新的store實(shí)例。您可以按照以下示例代碼進(jìn)行操作:
import Vue from 'vue'
import Vuex from 'vuex'
import App from './App.vue'

Vue.use(Vuex)

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  }
})

new Vue({
  el: '#app',
  store,
  render: h => h(App)
})

在上面的示例代碼中,我們創(chuàng)建了一個(gè)名為“store”的新Vuex實(shí)例,并在Vue實(shí)例中將其傳遞給“store”選項(xiàng)。在“store”對(duì)象中,我們定義了一個(gè)名為“count”的狀態(tài)和一個(gè)名為“increment”的突變。狀態(tài)是我們應(yīng)用程序中需要跟蹤的數(shù)據(jù),而突變是用于更改狀態(tài)的方法。
4.1.3 現(xiàn)在,您可以在Vue組件中使用Vuex。例如,在組件中獲取狀態(tài)并觸發(fā)突變的示例代碼如下:

<template>
  <div>
    <p>Count: {{ count }}</p>
    <button @click="increment">Increment</button>
  </div>
</template>

<script>
export default {
  computed: {
    count () {
      return this.$store.state.count
    }
  },
  methods: {
    increment () {
      this.$store.commit('increment')
    }
  }
}
</script>

在上面的示例代碼中,我們使用計(jì)算屬性從Vuex store中獲取狀態(tài),并使用方法來觸發(fā)突變。當(dāng)用戶單擊“Increment”按鈕時(shí),將調(diào)用名為“increment”的突變,從而遞增狀態(tài)中的計(jì)數(shù)器。
4.2 state
在Vue中,state是用于存儲(chǔ)應(yīng)用程序狀態(tài)的對(duì)象。在Vuex中,state是唯一的數(shù)據(jù)源,并且所有狀態(tài)的更改都必須通過mutations來進(jìn)行。以下是一個(gè)簡(jiǎn)單的示例代碼,演示如何在Vue中使用state:

// store.js
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment(state) {
      state.count++
    },
    decrement(state) {
      state.count--
    }
  }
})

在上面的示例代碼中,我們定義了一個(gè)名為“count”的狀態(tài),并使用mutations來遞增和遞減這個(gè)狀態(tài)?,F(xiàn)在,我們可以在Vue組件中使用這個(gè)狀態(tài)了:

// Counter.vue
<template>
  <div>
    <p>Count: {{ count }}</p>
    <button @click="increment">Increment</button>
    <button @click="decrement">Decrement</button>
  </div>
</template>

<script>
import { mapState, mapMutations } from 'vuex'

export default {
  computed: {
    ...mapState(['count'])
  },
  methods: {
    ...mapMutations(['increment', 'decrement'])
  }
}
</script>

在上面的示例代碼中,我們使用了Vuex提供的輔助函數(shù)mapState和mapMutations來將state和mutations映射到組件的計(jì)算屬性和方法中?,F(xiàn)在,當(dāng)用戶單擊“Increment”或“Decrement”按鈕時(shí),將調(diào)用相應(yīng)的mutations來更改狀態(tài)。
希望這個(gè)示例能夠幫助您理解Vue中的state對(duì)象。

4.3 getters
Vuex getters是用于從store中獲取數(shù)據(jù)的函數(shù),類似于store中的計(jì)算屬性。它們可以接受state作為第一個(gè)參數(shù),并且可以接受其他getter作為第二個(gè)參數(shù)。Getter函數(shù)的返回值會(huì)根據(jù)它的依賴被緩存起來,只有當(dāng)依賴發(fā)生改變才會(huì)重新計(jì)算。
下面是一個(gè)示例代碼,展示如何使用Vuex getters:

// 在store中定義getter
const store = new Vuex.Store({
  state: {
    todos: [
      { id: 1, text: 'Buy groceries', done: false },
      { id: 2, text: 'Do laundry', done: true },
      { id: 3, text: 'Clean room', done: false }
    ]
  },
  getters: {
    doneTodos: state => {
      return state.todos.filter(todo => todo.done)
    },
    // 使用其他getter作為參數(shù)
    doneTodosCount: (state, getters) => {
      return getters.doneTodos.length
    }
  }
})

// 在組件中使用getter
export default {
  computed: {
    // 獲取doneTodosCount的值
    doneTodosCount () {
      return this.$store.getters.doneTodosCount
    }
  }
}

在上面的示例中,我們定義了一個(gè)getter函數(shù)doneTodos,用于獲取所有已完成的任務(wù)。我們還定義了另一個(gè)getter函數(shù)doneTodosCount,它依賴于doneTodos,用于獲取已完成任務(wù)的數(shù)量。在組件中,我們可以通過this.$store.getters.doneTodosCount來獲取已完成任務(wù)的數(shù)量。
4.4 mutations
Vuex mutations是用于修改store中狀態(tài)的唯一途徑。每個(gè)mutation都有一個(gè)字符串類型的事件類型(type)和一個(gè)回調(diào)函數(shù)(handler),回調(diào)函數(shù)接受state作為第一個(gè)參數(shù),并且可以接受額外的載荷(payload)作為第二個(gè)參數(shù)。我們可以在回調(diào)函數(shù)中修改state的值。
下面是一個(gè)示例代碼,展示如何使用Vuex mutations:

// 在store中定義mutation
const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    // 增加count的值
    increment (state) {
      state.count++
    },
    // 減少count的值
    decrement (state) {
      state.count--
    },
    // 增加count的值,根據(jù)傳入的payload
    incrementBy (state, payload) {
      state.count += payload.amount
    }
  }
})

// 在組件中使用mutation
export default {
  methods: {
    // 調(diào)用increment mutation
    increment () {
      this.$store.commit('increment')
    },
    // 調(diào)用decrement mutation
    decrement () {
      this.$store.commit('decrement')
    },
    // 調(diào)用incrementBy mutation,并傳入payload
    incrementBy (amount) {
      this.$store.commit('incrementBy', { amount: amount })
    }
  }
}

在上面的示例中,我們定義了三個(gè)mutation函數(shù),分別用于增加count的值、減少count的值以及根據(jù)傳入的payload增加count的值。在組件中,我們可以通過this.$store.commit('mutationName', payload)來調(diào)用mutation函數(shù)。其中,mutationName是mutation的事件類型,payload是可選的載荷。通過這種方式,我們可以修改store中的狀態(tài)。
4.6 actions
Vuex actions是用于處理異步操作的函數(shù),它們可以包含任意異步操作、提交mutation等。每個(gè)action都有一個(gè)字符串類型的事件類型(type)和一個(gè)回調(diào)函數(shù)(handler),回調(diào)函數(shù)接受一個(gè)context對(duì)象作為第一個(gè)參數(shù),context對(duì)象中包含了state、commit、dispatch等方法,以及額外的載荷(payload)作為第二個(gè)參數(shù)。我們可以在回調(diào)函數(shù)中執(zhí)行異步操作,并通過commit提交mutation來修改state的值。
下面是一個(gè)示例代碼,展示如何使用Vuex actions:

// 在store中定義action
const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    // 增加count的值
    increment (state) {
      state.count++
    }
  },
  actions: {
    // 延遲一秒后增加count的值
    incrementAsync (context) {
      setTimeout(() => {
        context.commit('increment')
      }, 1000)
    },
    // 增加count的值,根據(jù)傳入的payload
    incrementByAsync (context, payload) {
      setTimeout(() => {
        context.commit('incrementBy', payload)
      }, 1000)
    }
  }
})

// 在組件中使用action
export default {
  methods: {
    // 調(diào)用incrementAsync action
    incrementAsync () {
      this.$store.dispatch('incrementAsync')
    },
    // 調(diào)用incrementByAsync action,并傳入payload
    incrementByAsync (amount) {
      this.$store.dispatch('incrementByAsync', { amount: amount })
    }
  }
}

在上面的示例中,我們定義了兩個(gè)action函數(shù),分別用于延遲一秒后增加count的值以及根據(jù)傳入的payload增加count的值。在組件中,我們可以通過this.$store.dispatch('actionName', payload)來調(diào)用action函數(shù)。其中,actionName是action的事件類型,payload是可選的載荷。通過這種方式,我們可以處理異步操作,并通過commit提交mutation來修改store中的狀態(tài)。
4.7 modules
Vuex modules是用于將store分割成多個(gè)模塊的功能,每個(gè)模塊都有自己的state、mutations、actions、getters等。這樣可以使得store更加靈活、易于維護(hù)。每個(gè)模塊都可以包含自己的子模塊,形成一個(gè)樹形結(jié)構(gòu)。
下面是一個(gè)示例代碼,展示如何使用Vuex modules:

// 在store中定義module
const moduleA = {
  state: { ... },
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}

const moduleB = {
  state: { ... },
  mutations: { ... },
  actions: { ... }
}

const store = new Vuex.Store({
  modules: {
    // 使用moduleA
    a: moduleA,
    // 使用moduleB
    b: moduleB
  }
})

// 在組件中使用module
export default {
  computed: {
    // 獲取moduleA中的count值
    countA () {
      return this.$store.state.a.count
    },
    // 獲取moduleB中的count值
    countB () {
      return this.$store.state.b.count
    }
  },
  methods: {
    // 調(diào)用moduleA中的increment action
    incrementA () {
      this.$store.dispatch('a/increment')
    },
    // 調(diào)用moduleB中的decrement action
    decrementB () {
      this.$store.dispatch('b/decrement')
    }
  }
}

在上面的示例中,我們定義了兩個(gè)module,分別是moduleA和moduleB。在store中,我們使用modules選項(xiàng)來引入這兩個(gè)module。在組件中,我們可以通過this.$store.state.moduleName.stateName來訪問module中的state值,通過this.$store.dispatch('moduleName/actionName')來調(diào)用module中的action。其中,moduleName是module的名稱,actionName是action的名稱。通過這種方式,我們可以將store分割成多個(gè)模塊,使得store更加靈活、易于維護(hù)。

  1. Vue進(jìn)階
    5.1 插槽
    Vue的插槽(slot)是一種組件間通信的方式,它允許父組件向子組件傳遞任意內(nèi)容,包括HTML、組件、函數(shù)等。插槽可以在子組件中作為一個(gè)標(biāo)記位置,父組件可以將任意內(nèi)容插入到這個(gè)標(biāo)記位置中,從而實(shí)現(xiàn)動(dòng)態(tài)渲染的效果。
    下面是一個(gè)示例代碼,展示如何使用Vue的插槽:
<!-- 父組件 -->
<template>
  <div>
    <h1>我是父組件</h1>
    <child-component>
      <!-- 插入內(nèi)容到默認(rèn)插槽 -->
      <p>這是一段默認(rèn)插槽的內(nèi)容</p>
    </child-component>
    <child-component>
      <!-- 插入內(nèi)容到具名插槽 -->
      <template v-slot:header>
        <h2>這是header插槽的內(nèi)容</h2>
      </template>
      <template v-slot:footer>
        <h2>這是footer插槽的內(nèi)容</h2>
      </template>
    </child-component>
  </div>
</template>

<!-- 子組件 -->
<template>
  <div>
    <h3>我是子組件</h3>
    <!-- 渲染默認(rèn)插槽 -->
    <slot></slot>
    <!-- 渲染具名插槽 -->
    <slot name="header"></slot>
    <slot name="footer"></slot>
  </div>
</template>

在上面的示例中,我們定義了一個(gè)父組件和一個(gè)子組件。在父組件中,我們使用<child-component>來引入子組件,并在其中通過<slot>標(biāo)簽插入內(nèi)容到默認(rèn)插槽中。同時(shí),我們使用<template>標(biāo)簽來定義具名插槽,并在其中插入內(nèi)容。在子組件中,我們使用<slot>標(biāo)簽來渲染默認(rèn)插槽,使用<slot name="slotName">來渲染具名插槽。其中,slotName是具名插槽的名稱。通過這種方式,父組件可以向子組件傳遞任意內(nèi)容,并動(dòng)態(tài)渲染出需要的效果。
5.2 過渡和動(dòng)畫
Vue的過渡和動(dòng)畫是一種在組件顯示和隱藏時(shí)添加動(dòng)畫效果的方式。Vue提供了<transition>和<transition-group>兩個(gè)組件來實(shí)現(xiàn)過渡和動(dòng)畫效果。
<transition>組件可以為組件的顯示和隱藏添加過渡效果??梢酝ㄟ^設(shè)置name屬性來指定過渡效果的名稱,然后在CSS中定義過渡效果的樣式。<transition>組件還提供了幾個(gè)鉤子函數(shù),可以在過渡的不同階段執(zhí)行一些操作。
下面是一個(gè)示例代碼,展示如何使用<transition>組件實(shí)現(xiàn)過渡效果:

<template>
  <div>
    <button @click="show=!show">Toggle</button>
    <transition name="fade">
      <p v-if="show">這是一個(gè)有過渡效果的段落。</p>
    </transition>
  </div>
</template>

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

<style>
.fade-enter-active, .fade-leave-active {
  transition: opacity .5s;
}
.fade-enter, .fade-leave-to {
  opacity: 0;
}
</style>

在上面的示例中,我們使用<transition>組件包裹了一個(gè)段落,并通過v-if指令來控制段落的顯示和隱藏。在CSS中,我們定義了.fade-enter-active和.fade-leave-active類來設(shè)置過渡效果的樣式,定義了.fade-enter和.fade-leave-to類來設(shè)置過渡前后的樣式。當(dāng)段落顯示和隱藏時(shí),Vue會(huì)自動(dòng)添加相應(yīng)的類名,從而實(shí)現(xiàn)過渡效果。

<transition-group>組件可以為多個(gè)組件的顯示和隱藏添加過渡效果。與<transition>組件不同的是,<transition-group>組件需要使用v-for指令來渲染多個(gè)組件,并設(shè)置name屬性來指定過渡效果的名稱。<transition-group>組件還提供了幾個(gè)鉤子函數(shù),可以在過渡的不同階段執(zhí)行一些操作。

下面是一個(gè)示例代碼,展示如何使用<transition-group>組件實(shí)現(xiàn)動(dòng)畫效果:

<template>
  <div>
    <button @click="addItem">Add Item</button>
    <button @click="removeItem">Remove Item</button>
    <transition-group name="list" tag="ul">
      <li v-for="(item, index) in items" :key="item.id">{{ item.text }}</li>
    </transition-group>
  </div>
</template>

<script>
export default {
  data() {
    return {
      items: [
        { id: 1, text: 'Item 1' },
        { id: 2, text: 'Item 2' },
        { id: 3, text: 'Item 3' }
      ]
    }
  },
  methods: {
    addItem() {
      const id = this.items.length + 1
      this.items.push({ id, text: `Item ${id}` })
    },
    removeItem() {
      this.items.pop()
    }
  }
}
</script>

<style>
.list-enter-active, .list-leave-active {
  transition: all .5s;
}
.list-enter, .list-leave-to {
  opacity: 0;
  transform: translateY(30px);
}
</style>

在上面的示例中,我們使用<transition-group>組件包裹了一個(gè)<ul>元素,并使用v-for指令渲染多個(gè)<li>元素。在CSS中,我們定義了.list-enter-active和.list-leave-active類來設(shè)置過渡效果的樣式,定義了.list-enter和.list-leave-to類來設(shè)置過渡前后的樣式。當(dāng)添加或刪除<li>元素時(shí),Vue會(huì)自動(dòng)添加相應(yīng)的類名,從而實(shí)現(xiàn)動(dòng)畫效果。
5.3 自定義過濾器
Vue.js 允許我們自定義過濾器來處理文本格式化。 自定義過濾器是一種簡(jiǎn)單的方法來過濾文本格式,以便在應(yīng)用程序中重復(fù)使用。下面是一個(gè)示例代碼:

<template>
  <div>
    <p>{{ message | capitalize }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      message: 'hello world'
    }
  },
  filters: {
    capitalize(value) {
      if (!value) return ''
      value = value.toString()
      return value.charAt(0).toUpperCase() + value.slice(1)
    }
  }
}
</script>

在這個(gè)示例中,我們定義了一個(gè) capitalize 過濾器,它將字符串的第一個(gè)字母大寫,并返回新的字符串。在模板中,我們使用 message 數(shù)據(jù)屬性,并將其傳遞給 capitalize 過濾器。最后,我們將過濾器返回的結(jié)果渲染到頁面上。
您可以使用 Vue.filter() 全局方法來定義全局過濾器。例如:

Vue.filter('capitalize', function(value) {
  if (!value) return ''
  value = value.toString()
  return value.charAt(0).toUpperCase() + value.slice(1)
})

然后,在任何組件中都可以使用 capitalize 過濾器。
5.4 mixin
Vue.js 中的 mixin 是一種可重復(fù)使用的代碼塊,它可以在多個(gè)組件之間共享。Mixin 可以包含任何組件選項(xiàng),例如 data、methods、computed 等。
下面是一個(gè)示例代碼:

const myMixin = {
  data() {
    return {
      message: 'Hello from mixin!'
    }
  },
  methods: {
    sayHello() {
      console.log(this.message)
    }
  }
}

export default {
  mixins: [myMixin],
  data() {
    return {
      name: 'John'
    }
  },
  created() {
    this.sayHello()
  }
}

在這個(gè)示例中,我們定義了一個(gè)名為 myMixin 的 mixin,它包含一個(gè)名為 message 的數(shù)據(jù)屬性和一個(gè)名為 sayHello 的方法。然后,在我們的組件中,我們使用 mixins 選項(xiàng)將 myMixin 添加到組件中。組件還包含一個(gè)名為 name 的數(shù)據(jù)屬性和一個(gè)在 created 生命周期鉤子中調(diào)用的 sayHello 方法。由于我們使用了 mixin,因此組件也具有 message 數(shù)據(jù)屬性和 sayHello 方法。
您可以使用多個(gè) mixin,并且它們將按照定義的順序進(jìn)行合并。如果多個(gè) mixin 包含同名選項(xiàng),則這些選項(xiàng)將合并為一個(gè)數(shù)組,并且在組件中定義的選項(xiàng)將覆蓋 mixin 中的選項(xiàng)。
請(qǐng)注意,mixin 不應(yīng)該被濫用。如果您發(fā)現(xiàn)自己在多個(gè)組件中使用相同的代碼,則可以考慮將其提取到 mixin 中。但是,如果您的 mixin 包含太多代碼或太多選項(xiàng),則可能會(huì)導(dǎo)致代碼難以維護(hù)。
5.5 v-model原理
v-model 是 Vue.js 中一種常見的指令,它用于在表單元素和組件之間創(chuàng)建雙向數(shù)據(jù)綁定。當(dāng)表單元素的值發(fā)生變化時(shí),組件中的數(shù)據(jù)也會(huì)隨之更新;反之亦然。
v-model 的實(shí)現(xiàn)原理是通過綁定 value 屬性和 input 事件來實(shí)現(xiàn)雙向數(shù)據(jù)綁定。對(duì)于表單元素,v-model 綁定的是 value 屬性和 input 事件;對(duì)于自定義組件,v-model 綁定的是 value 屬性和名為 input 的自定義事件。這樣,當(dāng)表單元素或自定義組件的值發(fā)生變化時(shí),就會(huì)觸發(fā)相應(yīng)的 input 事件,從而更新組件中綁定的數(shù)據(jù)。
下面是一個(gè)示例代碼:

<template>
  <div>
    <input v-model="message">
    <p>{{ message }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      message: 'Hello world!'
    }
  }
}
</script>

在這個(gè)示例中,我們使用 v-model 指令將輸入框和組件中的 message 數(shù)據(jù)屬性進(jìn)行雙向綁定。當(dāng)用戶在輸入框中輸入文本時(shí),message 數(shù)據(jù)屬性也會(huì)相應(yīng)地更新,并且在頁面上顯示出來。
需要注意的是,對(duì)于一些特殊的表單元素,例如 checkbox 和 radio,v-model 的實(shí)現(xiàn)方式略有不同。對(duì)于 checkbox,v-model 綁定的是 checked 屬性和 change 事件;對(duì)于 radio,v-model 綁定的是 value 屬性和 change 事件。
5.6 服務(wù)端渲染
Vue.js 服務(wù)端渲染(SSR)是一種將 Vue.js 應(yīng)用程序渲染為 HTML 字符串的技術(shù),該技術(shù)可以提高應(yīng)用程序的首次加載速度和搜索引擎優(yōu)化(SEO)。服務(wù)端渲染可以將 Vue.js 應(yīng)用程序的初始渲染放在服務(wù)器端完成,然后將渲染后的 HTML 字符串發(fā)送給客戶端,客戶端在接收到 HTML 字符串后,再將其轉(zhuǎn)換為交互式應(yīng)用程序。
下面是一個(gè)示例代碼:

// server.js

const express = require('express')
const Vue = require('vue')
const serverRenderer = require('vue-server-renderer').createRenderer()

const app = express()

app.get('*', (req, res) => {
  const vm = new Vue({
    data: {
      message: 'Hello from server!'
    },
    template: `<div>{{ message }}</div>`
  })

  serverRenderer.renderToString(vm, (err, html) => {
    if (err) {
      res.status(500).send('Internal Server Error')
    } else {
      res.send(`
        <!DOCTYPE html>
        <html>
          <head>
            <title>Vue SSR</title>
          </head>
          <body>
            ${html}
          </body>
        </html>
      `)
    }
  })
})

app.listen(3000, () => {
  console.log('Server started on port 3000')
})

這個(gè)示例中,我們使用 Express 框架創(chuàng)建了一個(gè)簡(jiǎn)單的服務(wù)器。在服務(wù)器的路由處理函數(shù)中,我們創(chuàng)建了一個(gè)新的 Vue 實(shí)例,并將其渲染為 HTML 字符串。我們使用 vue-server-renderer 模塊中的 createRenderer() 方法創(chuàng)建了一個(gè)渲染器,并使用 renderToString() 方法將 Vue 實(shí)例渲染為 HTML 字符串。最后,我們將 HTML 字符串包裝在一個(gè)完整的 HTML 頁面中,并將其發(fā)送給客戶端。
需要注意的是,服務(wù)端渲染需要考慮到一些特殊的問題,例如在服務(wù)器上無法使用瀏覽器 API、需要處理異步數(shù)據(jù)獲取等等。因此,在實(shí)際應(yīng)用中,需要根據(jù)具體情況進(jìn)行相應(yīng)的調(diào)整和優(yōu)化。

5.7 單元測(cè)試
Vue.js 的單元測(cè)試是一種測(cè)試技術(shù),用于測(cè)試 Vue.js 組件的行為和功能。單元測(cè)試可以幫助我們確保組件的正確性和穩(wěn)定性,從而提高代碼質(zhì)量和可維護(hù)性。

Vue.js 的單元測(cè)試通常使用 Jest 或 Mocha 等測(cè)試框架,以及 Vue Test Utils 等測(cè)試工具。其中,Vue Test Utils 是 Vue.js 官方提供的測(cè)試工具,它提供了一系列 API,用于模擬組件的行為和狀態(tài),并對(duì)組件進(jìn)行斷言驗(yàn)證。
下面是一個(gè)示例代碼:

<!-- Counter.vue -->

<template>
  <div>
    <p>Count: {{ count }}</p>
    <button @click="increment">Increment</button>
    <button @click="decrement">Decrement</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      count: 0
    }
  },
  methods: {
    increment() {
      this.count++
    },
    decrement() {
      this.count--
    }
  }
}
</script>
// Counter.spec.js

import { shallowMount } from '@vue/test-utils'
import Counter from './Counter.vue'

describe('Counter.vue', () => {
  it('renders count', () => {
    const wrapper = shallowMount(Counter)
    expect(wrapper.text()).toContain('Count: 0')
  })

  it('increments count when button is clicked', () => {
    const wrapper = shallowMount(Counter)
    const button = wrapper.find('button:first-of-type')
    button.trigger('click')
    expect(wrapper.text()).toContain('Count: 1')
  })

  it('decrements count when button is clicked', () => {
    const wrapper = shallowMount(Counter)
    const button = wrapper.find('button:last-of-type')
    button.trigger('click')
    expect(wrapper.text()).toContain('Count: -1')
  })
})

在這個(gè)示例中,我們創(chuàng)建了一個(gè)簡(jiǎn)單的計(jì)數(shù)器組件 Counter,并編寫了三個(gè)測(cè)試用例來測(cè)試組件的行為和功能。在每個(gè)測(cè)試用例中,我們使用 shallowMount 方法創(chuàng)建了一個(gè)組件實(shí)例,并對(duì)其進(jìn)行斷言驗(yàn)證。其中,第一個(gè)測(cè)試用例驗(yàn)證了組件是否正確渲染初始計(jì)數(shù)器的值;第二個(gè)和第三個(gè)測(cè)試用例分別驗(yàn)證了點(diǎn)擊增加和減少按鈕后,計(jì)數(shù)器的值是否正確更新。

需要注意的是,在編寫單元測(cè)試時(shí),應(yīng)該盡量避免測(cè)試具體的實(shí)現(xiàn)細(xì)節(jié),而是應(yīng)該關(guān)注組件的行為和功能。這樣可以確保測(cè)試用例的可維護(hù)性和可重用性。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容