vue3.0基礎使用(附代碼)

1. 認識Vue3

1) 了解相關信息

2) 性能提升:

  • 打包大小減少41%

  • 初次渲染快55%, 更新渲染快133%

  • 內(nèi)存減少54%

  • 使用Proxy代替defineProperty實現(xiàn)數(shù)據(jù)響應式

  • 重寫虛擬DOM的實現(xiàn)和Tree-Shaking

3) 新增特性

  • Composition (組合) API

  • setup

    • ref 和 reactive

    • computed 和 watch

    • 新的生命周期函數(shù)

    • provide與inject

    • ...

  • 新組件

    • Fragment - 文檔碎片

    • Teleport - 瞬移組件的位置

    • Suspense - 異步加載組件的loading界面

  • 其它API更新

    • 全局API的修改

    • 將原來的全局API轉(zhuǎn)移到應用對象

    • 模板語法變化

2. 創(chuàng)建vue3項目

1) 使用 vue-cli 創(chuàng)建

文檔: https://cli.vuejs.org/zh/guide/creating-a-project.html#vue-create

npm install -g @vue/cli
## 保證 vue cli 版本在 4.5.0 以上
vue --version
## 創(chuàng)建項目
vue create my-project

然后的步驟

  • Please pick a preset - 選擇 Manually select features

  • Check the features needed for your project - 選擇上 TypeScript ,特別注意點空格是選擇科盛,點回車是下一步

  • Choose a version of Vue.js that you want to start the project with - 選擇 3.x (Preview)

  • Use class-style component syntax - 直接回車

  • Use Babel alongside TypeScript - 直接回車

  • Pick a linter / formatter config - 直接回車

  • Use history mode for router? - 直接回車

  • Pick a linter / formatter config - 直接回車

  • Pick additional lint features - 直接回車

  • Where do you prefer placing config for Babel, ESLint, etc.? - 直接回車

  • Save this as a preset for future projects? - 直接回車

2) 使用 vite 創(chuàng)建

  • 文檔: https://v3.cn.vuejs.org/guide/installation.html

  • vite 是一個由原生 ESM 驅(qū)動的 Web 開發(fā)構(gòu)建工具帽衙。在開發(fā)環(huán)境下基于瀏覽器原生 ES imports 開發(fā),

  • 它做到了本地快速開發(fā)啟動, 在生產(chǎn)環(huán)境下基于 Rollup 打包贞绵。

    • 快速的冷啟動厉萝,不需要等待打包操作;

    • 即時的熱模塊更新榨崩,替換性能和模塊數(shù)量的解耦讓更新飛起谴垫;

    • 真正的按需編譯,不再等待整個應用編譯完成母蛛,這是一個巨大的改變翩剪。

3. Composition API(常用部分)

文檔:

https://composition-api.vuejs.org/zh/api.html

1) setup

  • 新的option, 所有的組合API函數(shù)都在此使用, 只在初始化時執(zhí)行一次

  • 函數(shù)如果返回對象, 對象中的屬性或方法, 模板中可以直接使用

2) ref

  • 作用: 定義一個數(shù)據(jù)的響應式

  • 語法: const xxx = ref(initValue):

    • 創(chuàng)建一個包含響應式數(shù)據(jù)的引用(reference)對象

    • js中操作數(shù)據(jù): xxx.value

    • 模板中操作數(shù)據(jù): 不需要.value

  • 一般用來定義一個基本類型的響應式數(shù)據(jù)

<template>
 <h2>{{count}}</h2>
 <hr>
 <button @click="update">更新</button>
</template>

<script>
import { ref } from 'vue'
export default {

/* 使用vue3的composition API */
 setup () {

   // 定義響應式數(shù)據(jù) ref對象
   const count = ref(1)
   console.log(count)

   // 更新響應式數(shù)據(jù)的函數(shù)
   function update () {
     // alert('update')
     count.value += 1
   }

   return {
     count,
     update
     }
   }
}
</script>

3) reactive

  • 作用: 定義多個數(shù)據(jù)的響應式

  • const proxy = reactive(obj): 接收一個普通對象然后返回該普通對象的響應式代理器對象

  • 響應式轉(zhuǎn)換是“深層的”:會影響對象內(nèi)部所有嵌套的屬性

  • 內(nèi)部基于 ES6 的 Proxy 實現(xiàn),通過代理對象操作源對象內(nèi)部數(shù)據(jù)都是響應式的

<template>
   <h2>name: {{state.name}}</h2>
   <h2>age: {{state.age}}</h2>
   <h2>wife: {{state.wife}}</h2>
   <hr>
   <button @click="update">更新</button>
</template>

<script>
/* 
reactive: 
 作用: 定義多個數(shù)據(jù)的響應式
 const proxy = reactive(obj): 接收一個普通對象然后返回該普通對象的響應式代理器對象
 響應式轉(zhuǎn)換是“深層的”:會影響對象內(nèi)部所有嵌套的屬性
 內(nèi)部基于 ES6 的 Proxy 實現(xiàn)彩郊,通過代理對象操作源對象內(nèi)部數(shù)據(jù)都是響應式的
*/
import { reactive } from 'vue'
export default {
   setup () {
     /* 
     定義響應式數(shù)據(jù)對象
     */
     const state = reactive({
       name: 'tom',
       age: 25,
       wife: {
         name: 'marry',
         age: 22
       },
     })
     console.log(state, state.wife)

     const update = () => {
       state.name += '--'
       state.age += 1
       state.wife.name += '++'
       state.wife.age += 2
     }

     return {
       state,
       update,
     }
   }
}
</script>

4) 比較Vue2與Vue3的響應式(重要)

vue2的響應式

  • 核心:

    • 對象: 通過defineProperty對對象的已有屬性值的讀取和修改進行劫持(監(jiān)視/攔截)

    • 數(shù)組: 通過重寫數(shù)組更新數(shù)組一系列更新元素的方法來實現(xiàn)元素修改的劫持

Object.defineProperty(data, 'count', {
 get () {}, 
 set () {}
})
  • 問題

    • 對象直接新添加的屬性或刪除已有屬性, 界面不會自動更新

    • 直接通過下標替換元素或更新length, 界面不會自動更新 arr[1] = {}

Vue3的響應式

new Proxy(data, {
   // 攔截讀取屬性值
   get (target, prop) {
     return Reflect.get(target, prop)
   },
   // 攔截設置屬性值或添加新屬性
   set (target, prop, value) {
     return Reflect.set(target, prop, value)
   },
   // 攔截刪除屬性
   deleteProperty (target, prop) {
     return Reflect.deleteProperty(target, prop)
   }
})

proxy.name = 'tom' 
<!DOCTYPE html>
<html lang="en">
  <head>
     <meta charset="UTF-8">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <title>Proxy 與 Reflect</title>
  </head>
  <body>
   <script>
     const user = {
       name: "apple",
       age: 12
     };

     /* 
     proxyUser是代理對象, user是被代理對象
     后面所有的操作都是通過代理對象來操作被代理對象內(nèi)部屬性
     */
     const proxyUser = new Proxy(user, {

       get(target, prop) {
         console.log('劫持到了get()~', prop)
         return Reflect.get(target, prop)
       },

       set(target, prop, val) {
         console.log('劫持到了set()~', prop, val)
         return Reflect.set(target, prop, val);
       },

       deleteProperty (target, prop) {
         console.log('劫持到了delete屬性~', prop)
         return Reflect.deleteProperty(target, prop)
       }
    });
   // 讀取屬性值
   //console.log(proxyUser===user)
   //console.log('proxyUser.name:::', proxyUser.name)
   //console.log('proxyUser.user:::', proxyUser.age)
   // 設置屬性值
   //proxyUser.name = 'orange'
   //proxyUser.age = 13
   //console.log('user:::', user)
   // 添加屬性
   //proxyUser.sex = '男'
   //console.log('user:::', user)
   // 刪除屬性
   //delete proxyUser.sex
   //console.log('user:::', user)
   </script>
  </body>
</html>

5) setup細節(jié)

  • setup執(zhí)行的時機

    • 在beforeCreate之前執(zhí)行(一次), 此時組件對象還沒有創(chuàng)建

    • this是undefined, 不能通過this來訪問data/computed/methods / props

    • 其實所有的composition API相關回調(diào)函數(shù)中也都不可以

  • setup的返回值

    • 一般都返回一個對象: 為模板提供數(shù)據(jù), 也就是模板中可以直接使用此對象中的所有屬性/方法

    • 返回對象中的屬性會與data函數(shù)返回對象的屬性合并成為組件對象的屬性

    • 返回對象中的方法會與methods中的方法合并成功組件對象的方法

    • 如果有重名, setup優(yōu)先

    • 注意:

      • 一般不要混合使用: methods中可以訪問setup提供的屬性和方法, 但在setup方法中不能訪問data和methods

      • setup不能是一個async函數(shù): 因為返回值不再是return的對象, 而是promise, 模板看不到return對象中的屬性數(shù)據(jù)

  • setup的參數(shù)

    • setup(props, context) / setup(props, {attrs, slots, emit})

    • props: 包含props配置聲明且傳入了的所有屬性的對象

    • attrs: 包含沒有在props配置中聲明的屬性的對象, 相當于 this.$attrs

    • slots: 包含所有傳入的插槽內(nèi)容的對象, 相當于 this.$slots

    • emit: 用來分發(fā)自定義事件的函數(shù), 相當于 this.$emit

<template>
   <h2>App</h2>
   <p>msg: {{msg}}</p>
   <button @click="fn('--')">更新</button>

   <child :msg="msg" msg2="cba" @fn="fn"/>
</template>

<script lang="ts">
import { reactive, ref } from 'vue'
import child from './child.vue'

export default {
 components: { child },
 setup () {
   const msg = ref('abc')

   function fn (content: string) {
     msg.value += content
   }
   return {
     msg,
     fn
     }
   }
}
</script>
<template>
 <div>
   <h3>{{n}}</h3>
   <h3>{{m}}</h3>

   <h3>msg: {{msg}}</h3>
   <h3>msg2: {{$attrs.msg2}}</h3>

   <slot name="xxx"></slot>

   <button @click="update">更新</button>
 </div>
</template>

<script lang="ts">

import { ref, defineComponent } from 'vue'

export default defineComponent({
 name: 'child',
 props: ['msg'],

 emits: ['fn'], // 可選的, 聲明了更利于程序員閱讀, 且可以對分發(fā)的事件數(shù)據(jù)進行校驗

 setup (props, {attrs, emit, slots}) {

   console.log(props.msg, attrs.msg2, slots, emit)

   const m = ref(2)
   const n = ref(3)

   function update () {
     m.value += 2
     n.value += 2

     // 分發(fā)自定義事件
     emit('fn', '++')
   }

   return {
     m,
     n,
     update,
     }
   },
})
</script>

6) reactive與ref-細節(jié)

  • 是Vue3的 composition API中2個最重要的響應式API

  • ref用來處理基本類型數(shù)據(jù), reactive用來處理對象(遞歸深度響應式)

  • 如果用ref對象/數(shù)組, 內(nèi)部會自動將對象/數(shù)組轉(zhuǎn)換為reactive的代理對象

  • ref內(nèi)部: 通過給value屬性添加getter/setter來實現(xiàn)對數(shù)據(jù)的劫持

  • reactive內(nèi)部: 通過使用Proxy來實現(xiàn)對對象內(nèi)部所有數(shù)據(jù)的劫持, 并通過Reflect操作對象內(nèi)部數(shù)據(jù)

  • ref的數(shù)據(jù)操作: 在js中要.value, 在模板中不需要(內(nèi)部解析模板時會自動添加.value)

<template>
  <h2>App</h2>
  <p>m1: {{m1}}</p>
  <p>m2: {{m2}}</p>
  <p>m3: {{m3}}</p>
  <button @click="update">更新</button>
</template>

<script>
import {
  reactive,
  ref
} from 'vue'

export default {

  setup () {
    const m1 = ref('abc')
    const m2 = reactive({x: 1, y: {z: 'abc'}})

    // 使用ref處理對象  ==> 對象會被自動reactive為proxy對象
    const m3 = ref({a1: 2, a2: {a3: 'abc'}})
    console.log(m1, m2, m3)
    console.log(m3.value.a2) // 也是一個proxy對象

    function update() {
      m1.value += '--'
      m2.x += 1
      m2.y.z += '++'

      m3.value = {a1: 3, a2: {a3: 'abc---'}}
      m3.value.a2.a3 += '==' // reactive對對象進行了深度數(shù)據(jù)劫持
      console.log(m3.value.a2)
    }

    return {
      m1,
      m2,
      m3,
      update
    }
  }
}
</script>

7) 計算屬性與監(jiān)視

  • computed函數(shù):

    • 與computed配置功能一致

    • 只有g(shù)etter

    • 有g(shù)etter和setter

  • watch函數(shù)

    • 與watch配置功能一致

    • 監(jiān)視指定的一個或多個響應式數(shù)據(jù), 一旦數(shù)據(jù)變化, 就自動執(zhí)行監(jiān)視回調(diào)

    • 默認初始時不執(zhí)行回調(diào), 但可以通過配置immediate為true, 來指定初始時立即執(zhí)行第一次

    • 通過配置deep為true, 來指定深度監(jiān)視

  • watchEffect函數(shù)

    • 不用直接指定要監(jiān)視的數(shù)據(jù), 回調(diào)函數(shù)中使用的哪些響應式數(shù)據(jù)就監(jiān)視哪些響應式數(shù)據(jù)

    • 默認初始時就會執(zhí)行第一次, 從而可以收集需要監(jiān)視的數(shù)據(jù)

    • 監(jiān)視數(shù)據(jù)發(fā)生變化時回調(diào)

<template>
  <h2>App</h2>
  fistName: <input v-model="user.firstName"/><br>
  lastName: <input v-model="user.lastName"/><br>
  fullName1: <input v-model="fullName1"/><br>
  fullName2: <input v-model="fullName2"><br>
  fullName3: <input v-model="fullName3"><br>

</template>

<script>

import {
  reactive,
  ref,
  computed,
  watch,
  watchEffect
} from 'vue'

export default {

  setup () {
    const user = reactive({
      firstName: 'A',
      lastName: 'B'
    })

    // 1.只有g(shù)etter的計算屬性
    const fullName1 = computed(() => {
      console.log('fullName1')
      return user.firstName + '-' + user.lastName
    })

    // 2.有g(shù)etter與setter的計算屬性
    const fullName2 = computed({
      get () {
        console.log('fullName2 get')
        return user.firstName + '-' + user.lastName
      },

      set (value) {
        console.log('fullName2 set')
        const names = value.split('-')
        user.firstName = names[0]
        user.lastName = names[1]
      }
    })

    const fullName3 = ref('')

    /* 使用watch的2個特性:深度監(jiān)視和初始化立即執(zhí)行 */
    watch(user, () => {
      fullName3.value = user.firstName + '-' + user.lastName
    }, {
      immediate: true,  // 是否初始化立即執(zhí)行一次, 默認是false
      deep: true, // 是否是深度監(jiān)視, 默認是false
    })

    /* 
    watch一個ref對象數(shù)據(jù)
      默認在數(shù)據(jù)發(fā)生改變時執(zhí)行回調(diào)
    */
    watch(fullName3, (value) => {
      console.log('watch')
      const names = value.split('-')
      user.firstName = names[0]
      user.lastName = names[1]
    })

    /* 
    watch多個數(shù)據(jù): 
      使用數(shù)組來指定
      如果是ref對象, 直接指定
      如果是reactive對象中的屬性,  必須通過函數(shù)來指定
    */
    watch([() => user.firstName, () => user.lastName, fullName3], (values) => {
      console.log('監(jiān)視多個數(shù)據(jù)', values)
    })
       /* 
    watchEffect: 監(jiān)視所有回調(diào)中使用的數(shù)據(jù)
    */
    /* 
    watchEffect(() => {
      console.log('watchEffect')
      fullName3.value = user.firstName + '-' + user.lastName
    }) 
    */

    return {
      user,
      fullName1,
      fullName2,
      fullName3
    }
  }
}
</script>

8) 生命周期

vue2.x的生命周期

[圖片上傳失敗...(image-3484e0-1644895211640)]

vue3的生命周期

[圖片上傳失敗...(image-cb9666-1644895211640)]

與 2.x 版本生命周期相對應的組合式 API

  • beforeCreate -> 使用 setup()

  • created -> 使用 setup()

  • beforeMount -> onBeforeMount

  • mounted -> onMounted

  • beforeUpdate -> onBeforeUpdate

  • updated -> onUpdated

  • beforeDestroy -> onBeforeUnmount

  • destroyed -> onUnmounted

  • errorCaptured -> onErrorCaptured

新增的鉤子函數(shù)

組合式 API 還提供了以下調(diào)試鉤子函數(shù):

  • onRenderTracked

  • onRenderTriggered

<div class="about">
  <h2>msg: {{msg}}</h2>
  <hr>
  <button @click="update">更新</button>
</div>
</template>

<script lang="ts">
import {
  ref,
  onMounted,
  onUpdated,
  onUnmounted, 
  onBeforeMount, 
  onBeforeUpdate,
  onBeforeUnmount
} from "vue"

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

  created () {
    console.log('created')
  },

  beforeMount () {
    console.log('beforeMount')
  },

  mounted () {
    console.log('mounted')
  },

  beforeUpdate () {
    console.log('beforeUpdate')
  },

  updated () {
    console.log('updated')
  },

  beforeUnmount () {
    console.log('beforeUnmount')
  },

  unmounted () {
     console.log('unmounted')
  },

  setup() {

    const msg = ref('abc')

    const update = () => {
      msg.value += '--'
    }

    onBeforeMount(() => {
      console.log('--onBeforeMount')
    })

    onMounted(() => {
      console.log('--onMounted')
    })

    onBeforeUpdate(() => {
      console.log('--onBeforeUpdate')
    })

    onUpdated(() => {
      console.log('--onUpdated')
    })

    onBeforeUnmount(() => {
      console.log('--onBeforeUnmount')
    })

    onUnmounted(() => {
      console.log('--onUnmounted')
    })

    return {
      msg,
      update
    }
  }
}
</script>
  <h2>App</h2>
  <button @click="isShow=!isShow">切換</button>
  <hr>
  <Child v-if="isShow"/>
</template>

<script lang="ts">
import Child from './Child.vue'
export default {

  data () {
    return {
      isShow: true
    }
  },

  components: {
    Child
  }
}
</script>

9) toRefs

把一個響應式對象轉(zhuǎn)換成普通對象前弯,該普通對象的每個 property 都是一個 ref

應用: 當從合成函數(shù)返回響應式對象時,toRefs 非常有用焦辅,這樣消費組件就可以在不丟失響應式的情況下對返回的對象進行分解使用

問題: reactive 對象取出的所有屬性值都是非響應式的

解決: 利用 toRefs 可以將一個響應式 reactive 對象的所有原始屬性轉(zhuǎn)換為響應式的 ref 屬性

  <h2>App</h2>
  <h3>foo: {{foo}}</h3>
  <h3>bar: {{bar}}</h3>
  <h3>foo2: {{foo2}}</h3>
  <h3>bar2: {{bar2}}</h3>

</template>

<script lang="ts">
import { reactive, toRefs } from 'vue'
/*
toRefs:
  將響應式對象中所有屬性包裝為ref對象, 并返回包含這些ref對象的普通對象
  應用: 當從合成函數(shù)返回響應式對象時博杖,toRefs 非常有用,
        這樣消費組件就可以在不丟失響應式的情況下對返回的對象進行分解使用
*/
export default {

  setup () {

    const state = reactive({
      foo: 'a',
      bar: 'b',
    })

    const stateAsRefs = toRefs(state)

    setTimeout(() => {
      state.foo += '++'
      state.bar += '++'
    }, 2000);

    const {foo2, bar2} = useReatureX()

    return {
      // ...state,
      ...stateAsRefs,
      foo2, 
      bar2
    }
  },
}

function useReatureX() {
  const state = reactive({
    foo2: 'a',
    bar2: 'b',
  })

  setTimeout(() => {
    state.foo2 += '++'
    state.bar2 += '++'
  }, 2000);

  return toRefs(state)
}

</script>

10) provide和inject

利用ref函數(shù)獲取組件中的標簽元素

provide :向子組件以及子孫組件傳遞數(shù)據(jù)筷登。接收兩個參數(shù)剃根,第一個參數(shù)是 key,即數(shù)據(jù)的名稱前方;第二個參數(shù)為 value狈醉,即數(shù)據(jù)的值 inject :接收父組件或祖先組件傳遞過來的數(shù)據(jù)。接收一個參數(shù) key惠险,即父組件或祖先組件傳遞的數(shù)據(jù)名稱

import {provide} from 'vue'
export default {
    setup() {
        const obj= {
            name: 'apple',
            color: 'red'
        }

        // 向子組件以及子孫組件傳遞名為info的數(shù)據(jù)
        provide('info', obj)
    }
}

// B.vue
<div>{{ form.name }}</div>

import {inject} from 'vue'
export default {
    setup() {   
        // 接收A.vue傳遞過來的數(shù)據(jù)
        const form= inject('info')  // { name: 'apple', color: 'red'}
    }
}

11) ref獲取元素

利用ref函數(shù)獲取組件中的標簽元素

功能需求: 讓輸入框自動獲取焦點

<template>
  <h2>App</h2>
  <input type="text">
  <input type="text" ref="inputRef">
</template>

<script>
import { onMounted, ref } from 'vue'
/* 
ref獲取元素: 利用ref函數(shù)獲取組件中的標簽元素
功能需求: 讓輸入框自動獲取焦點
*/
export default {
  setup() {
    const inputRef = ref(null)

    onMounted(() => {
      inputRef.value && inputRef.value.focus()
    })

    return {
      inputRef
    }
  },
}
</script>

4. 新組件

1) Fragment(片斷)

  • 在Vue2中: 組件必須有一個根標簽

  • 在Vue3中: 組件可以沒有根標簽, 內(nèi)部會將多個標簽包含在一個Fragment虛擬元素中

  • 好處: 減少標簽層級, 減小內(nèi)存占用

<template>
    <h2>aaaa</h2>
    <h2>aaaa</h2>
</template>

2) Teleport(瞬移)

  • Teleport 提供了一種干凈的方法, 讓組件的html在父組件界面外的特定標簽(很可能是body)下插入顯示

ModalButton.vue

<template>
  <button @click="modalOpen = true">
      Open full screen modal! (With teleport!)
  </button>

  <teleport to="body">
    <div v-if="modalOpen" class="modal">
      <div>
        I'm a teleported modal! 
        (My parent is "body")
        <button @click="modalOpen = false">
          Close
        </button>
      </div>
    </div>
  </teleport>
</template>

<script>
import { ref } from 'vue'
export default {
  name: 'modal-button',
  setup () {
    const modalOpen = ref(false)
    return {
      modalOpen
    }
  }
}
</script>

<style>
.modal {
  position: absolute;
  top: 0; right: 0; bottom: 0; left: 0;
  background-color: rgba(0,0,0,.5);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

.modal div {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background-color: white;
  width: 300px;
  height: 300px;
  padding: 5px;
}
</style>

App.vue

<template>
  <h2>App</h2>
  <modal-button></modal-button>
</template>

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

export default {
  setup() {
    return {
    }
  },

  components: {
    ModalButton
  }
}
</script>

3) Suspense(不確定的)

  • 它們允許我們的應用程序在等待異步組件時渲染一些后備內(nèi)容苗傅,可以讓我們創(chuàng)建一個平滑的用戶體驗
<template>
  <Suspense>
    <template v-slot:default>
      <AsyncComp/>
      <!-- <AsyncAddress/> -->
    </template>

    <template v-slot:fallback>
      <h1>LOADING...</h1>
    </template>
  </Suspense>
</template>

<script lang="ts">
/* 
異步組件 + Suspense組件
*/
// import AsyncComp from './AsyncComp.vue'
import AsyncAddress from './AsyncAddress.vue'
import { defineAsyncComponent } from 'vue'
const AsyncComp = defineAsyncComponent(() => import('./AsyncComp.vue'))
export default {
  setup() {
    return {

    }
  },

  components: {
    AsyncComp,
    AsyncAddress
  }
}
</script>
  • AsyncComp.vue
<template>
  <h2>AsyncComp22</h2>
  <p>{{msg}}</p>
</template>

<script lang="ts">

export default {
  name: 'AsyncComp',
  setup () {
    // return new Promise((resolve, reject) => {
    //   setTimeout(() => {
    //     resolve({
    //       msg: 'abc'
    //     })
    //   }, 2000)
    // })
    return {
      msg: 'abc'
    }
  }
}
</script>
  • AsyncAddress.vue
<template>
<h2>{{data}}</h2>
</template>

<script lang="ts">
import axios from 'axios'
export default {
  async setup() {
    const result = await axios.get('/data/address.json')
    return {
      data: result.data
    }
  }
}
</script>
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市班巩,隨后出現(xiàn)的幾起案子渣慕,更是在濱河造成了極大的恐慌,老刑警劉巖抱慌,帶你破解...
    沈念sama閱讀 212,222評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件逊桦,死亡現(xiàn)場離奇詭異,居然都是意外死亡抑进,警方通過查閱死者的電腦和手機强经,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,455評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來寺渗,“玉大人匿情,你說我怎么就攤上這事兰迫。” “怎么了炬称?”我有些...
    開封第一講書人閱讀 157,720評論 0 348
  • 文/不壞的土叔 我叫張陵汁果,是天一觀的道長。 經(jīng)常有香客問我玲躯,道長须鼎,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,568評論 1 284
  • 正文 為了忘掉前任府蔗,我火速辦了婚禮,結(jié)果婚禮上汞窗,老公的妹妹穿的比我還像新娘姓赤。我一直安慰自己,他們只是感情好仲吏,可當我...
    茶點故事閱讀 65,696評論 6 386
  • 文/花漫 我一把揭開白布不铆。 她就那樣靜靜地躺著,像睡著了一般裹唆。 火紅的嫁衣襯著肌膚如雪誓斥。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,879評論 1 290
  • 那天许帐,我揣著相機與錄音劳坑,去河邊找鬼。 笑死成畦,一個胖子當著我的面吹牛距芬,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播循帐,決...
    沈念sama閱讀 39,028評論 3 409
  • 文/蒼蘭香墨 我猛地睜開眼框仔,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了拄养?” 一聲冷哼從身側(cè)響起离斩,我...
    開封第一講書人閱讀 37,773評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎瘪匿,沒想到半個月后跛梗,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,220評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡柿顶,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,550評論 2 327
  • 正文 我和宋清朗相戀三年茄袖,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片嘁锯。...
    茶點故事閱讀 38,697評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡宪祥,死狀恐怖聂薪,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情蝗羊,我是刑警寧澤藏澳,帶...
    沈念sama閱讀 34,360評論 4 332
  • 正文 年R本政府宣布,位于F島的核電站耀找,受9級特大地震影響翔悠,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜野芒,卻給世界環(huán)境...
    茶點故事閱讀 40,002評論 3 315
  • 文/蒙蒙 一蓄愁、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧狞悲,春花似錦撮抓、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,782評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至荸恕,卻和暖如春乖酬,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背融求。 一陣腳步聲響...
    開封第一講書人閱讀 32,010評論 1 266
  • 我被黑心中介騙來泰國打工咬像, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人双肤。 一個月前我還...
    沈念sama閱讀 46,433評論 2 360
  • 正文 我出身青樓施掏,卻偏偏與公主長得像,于是被迫代替她去往敵國和親茅糜。 傳聞我的和親對象是個殘疾皇子七芭,可洞房花燭夜當晚...
    茶點故事閱讀 43,587評論 2 350

推薦閱讀更多精彩內(nèi)容

  • vite腳手架創(chuàng)建項目 1、全局安裝vite腳手架 2蔑赘、使用腳手架創(chuàng)建項目 3狸驳、進入項目文件夾 4、安裝依賴 5缩赛、...
    微芒不朽閱讀 5,354評論 0 19
  • 前言 Vue3.0的步伐越來越近了耙箍,是時候了解起來了,雖然嘴上還喊學不動了酥馍,但是辩昆,身體還得誠實起來,接著學旨袒。汁针。术辐。通...
    Mstian閱讀 9,944評論 1 9
  • vue3 中的setup vue3中所有的屬性、方法施无、生命周期等皆定義在setup函數(shù)中辉词,可以說setup是vue...
    sosoYU閱讀 1,049評論 0 0
  • 這是我第21篇簡書。 咳咳猾骡,進入正題瑞躺。 Vue3新增了 Performance:性能更強,比Vue 2.0快了接近...
    東西里閱讀 1,352評論 0 3
  • 1.setup() setup() 函數(shù)是我們使用vue3的Composition API新特性提供了統(tǒng)一的入口兴想。...
    遇一頑石閱讀 1,398評論 0 2