国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Vue3基礎(chǔ)看這一篇就夠了(萬(wàn)字長(zhǎng)篇,附實(shí)例代碼及效果演示)

這篇具有很好參考價(jià)值的文章主要介紹了Vue3基礎(chǔ)看這一篇就夠了(萬(wàn)字長(zhǎng)篇,附實(shí)例代碼及效果演示)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

目錄

前言

概述

Vue3組合式api? VS? Vue2選項(xiàng)式api

基礎(chǔ)部分

setup

選項(xiàng)式api的風(fēng)格

組合式api的風(fēng)格

區(qū)別

?響應(yīng)式數(shù)據(jù)

ref

reactive

shallowReactive 與 shallowRef?

?計(jì)算屬性和監(jiān)聽

?computed 函數(shù)

?watch 函數(shù)

?watchEffect

生命周期

?響應(yīng)式數(shù)據(jù)只讀

toRaw 返回代理的源

markRaw 標(biāo)記對(duì)象拒絕代理

provide 與 inject 跨組件傳值

判斷是否為響應(yīng)式數(shù)據(jù)

toRef 和 toRefs 解構(gòu)響應(yīng)式數(shù)據(jù)

?新組件

Fragment

Teleport?

Suspense

組合式函數(shù)?

全局的api及指令的變動(dòng)

結(jié)語(yǔ)


前言

vue3已經(jīng)出了好長(zhǎng)一段時(shí)間了,最近閑來(lái)無(wú)事簡(jiǎn)單學(xué)習(xí)了一下,新增的東西還是挺多的,寫一篇文章來(lái)記錄一下。

概述

Vue3組合式api? VS? Vue2選項(xiàng)式api

談到 vue3,首先想到的就是組合式api,很大程度的解決了vue2選項(xiàng)式api的缺點(diǎn),那有啥缺點(diǎn)?當(dāng)文件中的業(yè)務(wù)代碼非常多的時(shí)候,閱讀修改代碼的時(shí)候是非常痛苦的,data,method,watch還有計(jì)算屬性之間來(lái)回跳轉(zhuǎn), 我已經(jīng)準(zhǔn)備拔刀了。

下面這些圖被瘋轉(zhuǎn),很形象的展現(xiàn)了vue2和vue3的區(qū)別,可以看到組合式api就是將單個(gè)功能的狀態(tài),方法,計(jì)算屬性等等需要用到的東西都組合在一起抽離成一個(gè)hook,也就是對(duì)應(yīng)圖4的function,最終再統(tǒng)一引入組合到一起。這樣做的好處就是單個(gè)功能的代碼都在一起,方便調(diào)式修改。

vue3,vue,前端?vue3,vue,前端

?vue3,vue,前端vue3,vue,前端

基礎(chǔ)部分

setup

setup是vue3的一個(gè)新的配置項(xiàng),只在初始化的時(shí)候執(zhí)行一次,所有的組合式函數(shù)都在此使用。setup可以在選項(xiàng)式api的風(fēng)格中使用也可以通過(guò)組合式api的風(fēng)格?。通過(guò)代碼簡(jiǎn)單對(duì)比一下。vue3推薦使用組合式。

選項(xiàng)式api的風(fēng)格

<script>
import { ref } from 'vue'
export default {
  setup() {
    const sum = ref(1)
    return {
      sum,
    }
  },
}
</script>

<template>
  <div>
    <h1>v3</h1>
    <h3>{{ sum }}</h3>
    <button @click="sum++">+1</button>
  </div>
</template>

<style scoped></style>

組合式api的風(fēng)格

<script setup>
import { ref } from 'vue'
const sum = ref(1)
</script>

<template>
  <div>
    <h1>v3</h1>
    <h3>{{ sum }}</h3>
    <button @click="sum++">+1</button>
  </div>
</template>

<style scoped></style>

區(qū)別

  1. <script setup>中的導(dǎo)入和頂層變量/函數(shù)都能夠在模板中直接使用, 選項(xiàng)式則需要導(dǎo)出
  2. <script setup>打包出來(lái)的體積更小
  3. <script setup>對(duì)ts更友好

官網(wǎng)介紹的比較詳細(xì),感興趣可以查看組合式 API 常見問(wèn)答 | Vue.js?

?響應(yīng)式數(shù)據(jù)

vue2中 data 函數(shù)返回的對(duì)象就是響應(yīng)式的數(shù)據(jù),但是在增加刪除對(duì)象屬性時(shí)不是響應(yīng)式的,當(dāng)然vue2中也有對(duì)應(yīng)的解決方法,this.$set(), this.$delete(), 其實(shí)這也能夠理解,畢竟vue2的響應(yīng)式式基于?Object.defineProperty?實(shí)現(xiàn)的,這個(gè)函數(shù)只提供了 get 和 set 以及一些描述符?descriptor,并沒有提供 add 和 delete 方法。

vue3中的響應(yīng)式包含了兩種形態(tài), ref(底層還是Object.defineProperty進(jìn)行數(shù)據(jù)劫持, 處理簡(jiǎn)單數(shù)據(jù)類型)reactive(使用es6的Proxy進(jìn)行數(shù)據(jù)劫持,處理復(fù)雜數(shù)據(jù)類型),完全修復(fù)了vue2響應(yīng)式的痛點(diǎn),vue3的響應(yīng)式更加的友好。

ref

ref 接受一個(gè)值,返回一個(gè)響應(yīng)式對(duì)象,一般用來(lái)處理簡(jiǎn)單數(shù)據(jù)類型的響應(yīng)式,但如果傳入的值是對(duì)象 ref 會(huì)求助 reactive,返回RefImpl的實(shí)例簡(jiǎn)稱ref對(duì)象。?此時(shí)可能會(huì)有疑惑,既然ref是一個(gè)響應(yīng)式的對(duì)象,為什么模板中能正常解析。這是因?yàn)樵诮馕鰐emplete時(shí)遇到ref對(duì)象會(huì)自動(dòng)取其value屬性,但是如果要在方法中修改ref創(chuàng)建的響應(yīng)式數(shù)據(jù),你的寫法應(yīng)該是這樣的 state.value = xxx

<script setup>
import { ref } from 'vue'
const sum = ref(1)
function add() {
  sum.value++
}
</script>

<template>
  <div>
    <h1>v3</h1>
    <h3>{{ sum }}</h3>
    <button @click="add">+1</button>
  </div>
</template>

<style scoped></style>

reactive

為對(duì)象做深層!!!!響應(yīng)式代理, 也就是如果對(duì)象有多層依舊是響應(yīng)式的,返回一個(gè)Proxy實(shí)例, 如果傳入一個(gè)字符串或者數(shù)字,它將不是響應(yīng)式的。Proxy?對(duì)象用于創(chuàng)建一個(gè)對(duì)象的代理,從而實(shí)現(xiàn)基本操作的攔截和自定義(如屬性查找、賦值、枚舉、函數(shù)調(diào)用等)Proxy - JavaScript | MDN。Vue使用 Proxy 進(jìn)行數(shù)據(jù)劫持, Reflect 進(jìn)行反射修改?Reflect - JavaScript | MDN

vue3,vue,前端

<script setup>
import { reactive } from 'vue'
const person = reactive({
  name: '張三',
  age: 12,
  job: {
    j1: {
      jname: '前端開發(fā)',
    },
  },
})

function add() {
  person.hobby = ['唱', '跳', 'rap']
}
function deleteHB() {
  delete person.hobby
}
</script>

<template>
  <div>
    <h1>v3</h1>
    <h1>{{ sum }}</h1>
    <h3>姓名:{{ person.name }}</h3>
    <h3>年齡:{{ person.age }}</h3>
    <h3>工作:{{ person.job.j1.jname }}</h3>
    <h3 v-if="person.hobby">愛好: {{ person.hobby }}</h3>
    <button @click="person.name += '-'">修改姓名</button>
    <button @click="person.age++">修改年齡</button>
    <button @click="person.job.j1.jname += '!'">修改工作</button>
    <button @click="add">增加愛好</button>
    <button @click="deleteHB">刪除愛好</button>
  </div>
</template>

<style scoped></style>

shallowReactive 與 shallowRef?

shallowRef 直譯過(guò)來(lái)意思是淺層的 ref,shallowRef 傳入對(duì)象不會(huì)求助?reactive,僅僅對(duì)ref對(duì)象的 value 屬性具有響應(yīng)式。

shallowReactive 只處理對(duì)象第一層的響應(yīng)式,? 如果修改了深層的數(shù)據(jù)頁(yè)面是不會(huì)響應(yīng)的,但是會(huì)在下次頁(yè)面更新中渲染出來(lái)。

vue3,vue,前端

<script setup>
import { shallowReactive, shallowRef, ref, reactive } from 'vue'
const shallowRef_jack = shallowRef({ name: 'jack', sex: '女' })
const shallowReactive_ben = shallowReactive({
  name: 'ben',
  sex: '女',
  child: {
    son: {
      name: '張三',
    },
  },
})

const ref_jack = ref({ name: 'jack', sex: '女' })
const reactive_ben = reactive({
  name: 'ben',
  sex: '女',
  child: {
    son: {
      name: '張三',
    },
  },
})
</script>

<template>
  <div>
    <h1>v3</h1>
    <h3>
      shallowRef_jack: {{ shallowRef_jack }}
      <button @click="shallowRef_jack = {}">修改整個(gè)對(duì)象</button>
      <button @click="shallowRef_jack.name += '!'">修改對(duì)象屬性</button>
    </h3>
    <h3>
      ref_jack: {{ ref_jack }}
      <button @click="ref_jack = {}">修改整個(gè)對(duì)象</button>
      <button @click="ref_jack.name += '!'">修改對(duì)象屬性</button>
    </h3>
    <h3>
      shallowReactive_ben: {{ shallowReactive_ben }}
      <button @click="shallowReactive_ben.child.son.name = '!'">
        修改對(duì)象的第三層屬性
      </button>
      <button @click="shallowReactive_ben.name += '!'">
        修改對(duì)象第一層屬性
      </button>
    </h3>
    <h3>
      reactive_ben: {{ reactive_ben }}
      <button @click="reactive_ben.child.son.name += '!'">
        修改對(duì)象的第三層屬性
      </button>
      <button @click="reactive_ben.name += '!'">修改對(duì)象第一層屬性</button>
    </h3>
  </div>
</template>

<style scoped>
h3 {
  font-size: 26px;
  border: 1px solid #ccc;
  padding: 20px;
  margin: 20px;
}
button {
  float: right;
  padding: 10px;
  font-size: 20px;
}
</style>

?計(jì)算屬性和監(jiān)聽

?computed 函數(shù)

計(jì)算屬性有兩種寫法,作用和vue2一樣,通過(guò)監(jiān)聽某個(gè)值的變化計(jì)算出一個(gè)新值

  • 只讀的寫法 :computed(() => xxxxxx),
  • 可讀可寫的寫法:? computed({ get: () => xxxx, set: (val) => { xxxx } })
<script setup>
import { ref, computed } from 'vue'
const count = ref(1)
const num1 = computed(() => count.value + 1)
const num2 = computed({
  get() {
    return count.value + 1
  },
  set(val) {
    count.value = val + 1
  },
})
</script>

<template>
  <div>
    <h1>v3</h1>
    <h2>
      ref 定義的 count: {{ count }} <button @click="count++">count++</button>
    </h2>
    <h2>計(jì)算屬性 num1: {{ num1 }} <button @click="num1++">num1++</button></h2>
    <h2>計(jì)算屬性 num2: {{ num2 }} <button @click="num2++">num2++</button></h2>
  </div>
</template>

<style scoped></style>

vue3,vue,前端

?watch 函數(shù)

watch 函數(shù)用來(lái)監(jiān)聽數(shù)據(jù)的變化,和vue2大體上都是相同的。

參數(shù)列表:

  1. 參數(shù)1為需要監(jiān)聽的響應(yīng)式對(duì)象(可以是單個(gè)對(duì)象,也可以是一個(gè)數(shù)組,也可以是一個(gè)getter函數(shù)),
  2. 參數(shù)2為監(jiān)聽對(duì)象發(fā)生變化時(shí)所執(zhí)行的回調(diào)
  3. 參數(shù)3是一些配置項(xiàng):immediate是否開啟立即監(jiān)聽,deep是否開啟深度監(jiān)聽,flush回調(diào)的觸發(fā)時(shí)機(jī),onTrack / onTrigger用于調(diào)試的兩個(gè)函數(shù)

?vue3,vue,前端

注意點(diǎn):?

  1. 直接監(jiān)聽 reactive 定義的響應(yīng)式對(duì)象默認(rèn)開啟了深度監(jiān)聽
  2. 通過(guò) getter 形式監(jiān)聽響應(yīng)式對(duì)象默認(rèn)是淺層監(jiān)聽
<script setup>
import { reactive, ref, watch } from 'vue'
const count = ref(1)
const person = reactive({
  name: 'ben',
  child: {
    son: {
      name: 'zs',
    },
  },
})
// 監(jiān)聽 ref 對(duì)象
watch(count, (val, preVal) => {
  console.log('count變化了', val, preVal)
})
// 監(jiān)聽 reactive  定義的響應(yīng)式對(duì)象
watch(person, (val, preVal) => {
  console.log('person變化了', val, preVal)
})
watch([count, person], (val, preVal) => {
  console.log('person變化了或count變化了', val, preVal)
})
</script>

<template>
  <div>
    <h1>v3</h1>
    <h2>
      ref 定義的 count: {{ count }} <button @click="count++">count++</button>
    </h2>
    <h2>
      reactive 定義的 person: {{ person }}
      <button @click="person.name += '!'">修改姓名</button>
      <button @click="person.child.son.name += '___'">修改兒子姓名</button>
    </h2>
  </div>
</template>

<style scoped></style>

?watchEffect

watchEffect 函數(shù)用于監(jiān)聽傳入的函數(shù)內(nèi)訪問(wèn)的所有響應(yīng)式數(shù)據(jù)的變化。白話一點(diǎn)就是回調(diào)里我用了誰(shuí)我就監(jiān)聽誰(shuí),監(jiān)聽ref定義的響應(yīng)式數(shù)據(jù)時(shí),不要忘記 .value?,哥們就是這么智能。

watch 和?watchEffect 都是監(jiān)聽數(shù)據(jù)變化的函數(shù),和 react 中的 useState 放入依賴項(xiàng)有著異曲同工之妙。

例子:切換下拉框中的 name ,模擬請(qǐng)求后臺(tái)接口?

<script setup>
import { onMounted, reactive, ref, watchEffect } from 'vue'
const name = ref('jack')
const info = [
  {
    id: 1,
    name: 'jack',
    child: {
      son: {
        name: 'zs',
      },
    },
  },
  {
    id: 2,
    name: 'ben',
    child: {
      son: {
        name: 'zs',
      },
    },
  },
]
let data = ref([])
async function getInfoByName(name) {
  const res = await new Promise((reslove) => {
    setTimeout(() => {
      reslove(info.filter((item) => item.name === name))
    }, 500)
  })
  data.value = res
}

watchEffect(async () => {
  getInfoByName(name.value)
})
</script>

<template>
  <div>
    <h1>v3</h1>
    <el-select v-model="name" placeholder="請(qǐng)選擇">
      <el-option
        v-for="item in info"
        :key="item.name"
        :label="item.name"
        :value="item.name"
      >
      </el-option>
    </el-select>
    <div v-for="item in data" :key="item.id">
      {{ item.name }}的個(gè)人信息 {{ item }}
    </div>
  </div>
</template>

<style scoped></style>

vue3,vue,前端

生命周期

vue3的生命周期稍有變動(dòng),增加了 setup 鉤子,且銷毀前和銷毀后的鉤子命名更改為?beforeUnmount 和?unmounted,以下代碼是驗(yàn)證的一些示例

App.vue?

<script setup>
import Demo from './Demo.vue'
import Demo2 from './Demo2.vue'
import { ref } from 'vue'
const isComDestory = ref(true)
const isOptionDestory = ref(true)
</script>

<template>
  <div>
    <h1>
      v3
      <button @click="isComDestory = false">引入組合式子組件</button>
      <button @click="isComDestory = true">銷毀組合式子組件</button>
      <button @click="isOptionDestory = false">引入選項(xiàng)式子組件</button>
      <button @click="isOptionDestory = true">銷毀選項(xiàng)式子組件</button>
    </h1>
    <Demo v-if="!isComDestory"></Demo>
    <Demo2 v-if="!isOptionDestory"></Demo2>
  </div>
</template>

<style scoped>
button {
  padding: 20px;
  font-size: 16px;
}
</style>

Demo.vue?

<script setup>
import {
  onMounted,
  onBeforeMount,
  onBeforeUpdate,
  onUpdated,
  onBeforeUnmount,
  onUnmounted,
  ref,
} from 'vue'
const sum = ref(1)
console.log('子組件1 setup')
onBeforeMount(() => {
  console.log('子組件1 onBeforeMount')
})
onMounted(() => {
  console.log('子組件1 onMounted')
})
onBeforeUpdate(() => {
  console.log('子組件1 onBeforeUpdate')
})
onUpdated(() => {
  console.log('子組件1 onUpdated')
})
onBeforeUnmount(() => {
  console.log('子組件1 onBeforeUnmount')
})
onUnmounted(() => {
  console.log('子組件1 onUnmounted')
})
</script>

<template>
  <div>
    <h2>我是子組件1</h2>
    <h2>{{ sum }} <button @click="sum++">+1</button></h2>
  </div>
</template>

<style scoped>
div {
  border: 1px solid #ccc;
}
</style>

Demo2.vue

<script>
import { ref } from 'vue'

export default {
  setup() {
    const sum = ref(1)
    console.log('子組件2 setup')
    return { sum }
  },
  beforeCreate() {
    console.log('子組件2 beforeCreate')
  },
  created() {
    console.log('子組件2 created')
  },
  beforeMount() {
    console.log('子組件2 beforeMount')
  },
  mounted() {
    console.log('子組件2 mounted')
  },
  beforeUpdate() {
    console.log('子組件2 beforeUpdate')
  },
  updated() {
    console.log('子組件2 updated')
  },
  beforeUnmount() {
    console.log('子組件2 beforeUnmount')
  },
  unmounted() {
    console.log('子組件2 unmounted')
  },
}
</script>

<template>
  <div>
    <h2>我是子組件2</h2>
    <h2>{{ sum }} <button @click="sum++">+1</button></h2>
  </div>
</template>

<style scoped>
div {
  border: 1px solid #ccc;
}
</style>

vue3,vue,前端

由于錄頻錄不了控制臺(tái),打印結(jié)果看下圖

vue3,vue,前端

vue3,vue,前端?vue3,vue,前端

?響應(yīng)式數(shù)據(jù)只讀

vue3提供了兩個(gè)api,限制響應(yīng)式數(shù)據(jù)為只讀,不可修改。分別為?readonly(深層只讀) 和shallowReadonly?(淺層只讀)

vue3,vue,前端

<script setup>
import { ref, reactive, readonly, shallowReadonly } from 'vue'
const sum = readonly(ref(1))
const p1 = readonly(
  reactive({
    name: 'ben',
    child: {
      son: {
        name: 'jack',
      },
    },
  })
)
const p2 = shallowReadonly(
  reactive({
    name: 'ben',
    child: {
      son: {
        name: 'jack',
      },
    },
  })
)
function edit() {
  sum.value = 2
  p1.name += '!'
  p1.child.son.name += '&'
}
function editShallow() {
  p2.name += '!'
  p2.child.son.name += '&'
}
</script>

<template>
  <div>
    <h1>v3</h1>
    <h2>readonly: {{ sum }}</h2>
    <h2>readonly: {{ p1 }}</h2>
    <h2>shallowReadonly: {{ p2 }}</h2>
    <button @click="edit">修改深層只讀數(shù)據(jù)</button>
    <button @click="editShallow">修改淺層只讀數(shù)據(jù)</button>
  </div>
</template>

<style scoped></style>

toRaw 返回代理的源

toRaw的功能官網(wǎng)的解釋很清晰,?可以返回由?reactive()、readonly()、shallowReactive()?或者?shallowReadonly()?創(chuàng)建的代理對(duì)應(yīng)的原始對(duì)象

<script setup>
import {
  ref,
  reactive,
  readonly,
  shallowReadonly,
  shallowReactive,
  toRaw,
} from 'vue'
const p1 = readonly(
  reactive({
    name: 'a',
    child: {
      son: {
        name: 'as',
      },
    },
  })
)
const p2 = shallowReadonly(
  reactive({
    name: 'b',
    child: {
      son: {
        name: 'bs',
      },
    },
  })
)
const p3 = reactive({
  name: 'c',
  child: {
    son: {
      name: 'cs',
    },
  },
})
const p4 = shallowReactive({
  name: 'd',
  child: {
    son: {
      name: 'ds',
    },
  },
})
console.log('toRaw p1 readonly', toRaw(p1))
console.log('toRaw p2 shallowReadonly', toRaw(p2))
console.log('toRaw p3 reactive', toRaw(p3))
console.log('toRaw p4 shallowReactive', toRaw(p4))
</script>

<template>
  <div></div>
</template>

<style scoped></style>

vue3,vue,前端

markRaw 標(biāo)記對(duì)象拒絕代理

markRaw()將對(duì)象標(biāo)記為不可代理,返回其本身。本身上多了一個(gè)?__v_skip 屬性表示忽略代理。強(qiáng)行代理代理是無(wú)效的,返回的還是其本身而不是響應(yīng)式對(duì)象。

<script setup>
import { markRaw, reactive } from 'vue'
const p1 = {
  name: 'a',
  child: {
    son: {
      name: 'as',
    },
  },
}
const noProxy_p1 = markRaw(p1)
console.log('不可代理對(duì)象', noProxy_p1)
console.log('reactive 代理不可代理對(duì)象', reactive(noProxy_p1))
</script>

<template>
  <div></div>
</template>

<style scoped></style>

vue3,vue,前端

?provide 與 inject 跨組件傳值

使用 provide 與 inject 進(jìn)行跨組件傳值十分方便。以父子孫為例,父組件?provide ('name',value) 子組件?inject ('name') 即可

vue3,vue,前端

?父組件

<script setup>
import { reactive, provide } from 'vue'
import Demo from './Demo.vue'
const obj = {
  name: 'a',
  child: {
    son: {
      name: 'as',
    },
  },
}
const person = reactive(obj)
provide('person', person)
</script>

<template>
  <div class="father">
    <h1>父組件</h1>
    <h3>{{ person }}</h3>
    <Demo></Demo>
  </div>
</template>

<style scoped>
.father {
  padding: 10px;
  background: orange;
}
</style>

?子組件

<script setup>
import Demo2 from './Demo2.vue'
</script>

<template>
  <div>
    <h2>子組件</h2>
    <Demo2></Demo2>
  </div>
</template>

<style scoped>
div {
  padding: 10px;
  background: salmon;
  border: 1px solid #ccc;
}
</style>

孫組件

<script>
import { ref, inject } from 'vue'
export default {
  setup() {
    const person = inject('person')
    return { person }
  },
}
</script>

<template>
  <div class="sonson">
    <h2>孫組件</h2>
    <h3>{{ person }}</h3>
  </div>
</template>

<style scoped>
.sonson {
  background: sandybrown;
  border: 1px solid #ccc;
}
</style>

判斷是否為響應(yīng)式數(shù)據(jù)

  • isRef(data)判斷data是否是通過(guò)ref創(chuàng)建的響應(yīng)式數(shù)據(jù)
  • isReactive(data)判斷data是否是通過(guò)reactive創(chuàng)建的響應(yīng)式數(shù)據(jù)
  • isReadonly(data)判斷data是否是通過(guò)readOnly創(chuàng)建的只讀數(shù)據(jù)
  • isProxy(data)判斷data是否為Proxy代理對(duì)象

vue3,vue,前端

<script setup>
import {
  reactive,
  readonly,
  ref,
  isProxy,
  isReactive,
  isRef,
  isReadonly,
} from 'vue'
const person = reactive({
  name: 'a',
  child: {
    son: {
      name: 'as',
    },
  },
})
const num = ref(1)
const str = readonly(ref('str'))
console.log(isRef(num))
console.log(isReactive(person))
console.log(isReadonly(str))
console.log(isProxy(person), isProxy(str))
</script>

<template></template>

<style scoped></style>

toRef 和 toRefs 解構(gòu)響應(yīng)式數(shù)據(jù)

當(dāng)響應(yīng)式對(duì)象的屬性過(guò)多且頁(yè)面用到很多次的時(shí)候,?toRef 和 toRefs 可以進(jìn)行響應(yīng)式解構(gòu),解構(gòu)出來(lái)的數(shù)據(jù)依舊具備響應(yīng)式的能力。下面的例子是在?<script setup>?中進(jìn)行演示的,setup()中的需要顯示的返回

?toRef

<script setup>
import { reactive, toRef } from 'vue'
const person = reactive({
  name: 'a',
  age: 18,
  child: {
    son: {
      name: 'as',
    },
  },
})
const personName = toRef(person, 'name')
const personAge = toRef(person, 'age')
const personSonName = toRef(person.child.son, 'name')
</script>

<template>
  <div>
    <h3>toRef 解構(gòu)出 person的name ----- {{ personName }}</h3>
    <h3>toRef 解構(gòu)出 person的age ----- {{ personAge }}</h3>
    <h3>toRef 解構(gòu)出 person的child的son的name ----- {{ personSonName }}</h3>
    <h3>toRef 解構(gòu)出 person的name ----- {{ personName }}</h3>
    <h3>toRef 解構(gòu)出 person的age ----- {{ personAge }}</h3>
    <h3>toRef 解構(gòu)出 person的child的son的name ----- {{ personSonName }}</h3>
    <h3>toRef 解構(gòu)出 person的name ----- {{ personName }}</h3>
    <h3>toRef 解構(gòu)出 person的age ----- {{ personAge }}</h3>
    <h3>toRef 解構(gòu)出 person的child的son的name ----- {{ personSonName }}</h3>
    <button @click="personName += '!'">修改person的name</button>
    <button @click="personAge += 1">修改person的age</button>
    <button @click="personSonName += '*'">person的child的son的name</button>
  </div>
</template>

<style scoped></style>

?vue3,vue,前端

?toRefs

<script setup>
import { reactive, toRefs } from 'vue'
const person = reactive({
  name: 'a',
  age: 18,
  child: {
    son: {
      name: 'as',
    },
  },
})
const { name, age, child } = toRefs(person)
</script>

<template>
  <div>
    <h3>toRefs 解構(gòu)出 person的name ----- {{ name }}</h3>
    <h3>toRefs 解構(gòu)出 person的age ----- {{ age }}</h3>
    <h3>toRefs 解構(gòu)出 person的child的son的name ----- {{ child.son.name }}</h3>
    <h3>toRefs 解構(gòu)出 person的name ----- {{ name }}</h3>
    <h3>toRefs 解構(gòu)出 person的age ----- {{ age }}</h3>
    <h3>toRefs 解構(gòu)出 person的child的son的name ----- {{ child.son.name }}</h3>
    <h3>toRefs 解構(gòu)出 person的name ----- {{ name }}</h3>
    <h3>toRefs 解構(gòu)出 person的age ----- {{ age }}</h3>
    <h3>toRefs 解構(gòu)出 person的child的son的name ----- {{ child.son.name }}</h3>
    <button @click="name += '!'">修改person的name</button>
    <button @click="age += 1">修改person的age</button>
    <button @click="child.son.name += '*'">person的child的son的name</button>
  </div>
</template>

<style scoped></style>

vue3,vue,前端

?新組件

Fragment

在vue2中模板標(biāo)簽內(nèi)必須包裹一層根標(biāo)簽,vue3中則不需要。vue3會(huì)為多個(gè)跟標(biāo)簽包裹一層Fragment。這是寫法上的優(yōu)化。前面很多例子的代碼中我都包裹了一層根標(biāo)簽,這是由于我的編輯器的eslint的問(wèn)題,去掉根標(biāo)簽也可以正常運(yùn)行。

有根標(biāo)簽的編譯結(jié)果

vue3,vue,前端?沒有根標(biāo)簽的編譯結(jié)果

vue3,vue,前端

Teleport?

Teleport 組件的功能是將元素渲染到任意的頁(yè)面位置中,直接扣過(guò)來(lái)官網(wǎng)的例子。

下列代碼主要表達(dá)的是:點(diǎn)擊按鈕將彈框插入到 body 標(biāo)簽下?

?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, 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 lang="ts">
import ModalButton from './ModalButton.vue'

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

  components: {
    ModalButton,
  },
}
</script>

?vue3,vue,前端

vue3,vue,前端

Suspense

Suspense?組件用于將異步組件包裹,提供一個(gè)過(guò)渡UI在異步完成之前。

Suspense 組件提供兩個(gè)插槽:

  1. #default? ?默認(rèn)插槽 存放異步組件
  2. #fallback? 備用插槽 存放過(guò)渡UI

異步組件:

  1. 帶有異步?setup()?鉤子的組件。這也包含了使用?<script setup>?時(shí)有頂層?await?表達(dá)式的組件。

  2. defineAsyncComponent

?App.vue

<template>
  <div>
    <h2>App</h2>
    <Suspense>
      <Demo></Demo>
      <template #fallback> 加載中.... </template>
    </Suspense>
  </div>
</template>

<script setup>
import Demo from './Demo.vue'
</script>

?Demo.vue

<script setup>
const res = await new Promise((resolve) => {
  setTimeout(() => {
    resolve({ name: 'zs', age: 12, sex: '男' })
  }, 1000)
})
</script>

<template>
  <div>
    <h2>異步組件</h2>
    <h3>{{ res }}</h3>
  </div>
</template>

<style scoped>
div {
  padding: 10px;
  background: salmon;
  border: 1px solid #ccc;
}
</style>

vue3,vue,前端

組合式函數(shù)?

組合式api的優(yōu)點(diǎn)之一式將單個(gè)功能代碼組合在一起,如果是可以復(fù)用的邏輯,那么可以抽離為一個(gè)組合式函數(shù)或者稱為自定義hook,在需要該邏輯的地方導(dǎo)入即可

例子:提供一個(gè)組合函數(shù),此函數(shù)在當(dāng)前組件中監(jiān)聽鼠標(biāo)移動(dòng)事件,并將坐標(biāo)顯示出來(lái),組件卸載前清掉事件。

App.vue

<template>
  <div>
    <h2>App</h2>
    <h2>
      <button @click="Demo1Visible = false">銷毀子組件1</button>
      <button @click="Demo2Visible = false">銷毀子組件2</button>
    </h2>
    <Demo v-if="Demo1Visible"></Demo>
    <Demo2 v-if="Demo2Visible"></Demo2>
  </div>
</template>

<script setup>
import { ref } from 'vue'
import Demo from './Demo.vue'
import Demo2 from './Demo2.vue'
const Demo1Visible = ref(true)
const Demo2Visible = ref(true)
</script>

Demo1.vue

<template>
  <div class="demo_1">
    <h2>子組件1</h2>
    <p v-if="x && y">x坐標(biāo)為 {{ x }}, y坐標(biāo)為{{ y }}</p>
  </div>
</template>
<script setup>
import useMouse from './mouse'
const { x, y } = useMouse('.demo_1')
</script>

<style scoped>
.demo_1 {
  height: 100px;
  background: salmon;
}
</style>

Demo2.vue?

<template>
  <div class="demo_2">
    <h2>子組件2</h2>
    <p v-if="x && y">x坐標(biāo)為 {{ x }}, y坐標(biāo)為{{ y }}</p>
  </div>
</template>
<script setup>
import useMouse from './mouse'
const { x, y } = useMouse('.demo_2')
</script>

<style scoped>
.demo_2 {
  height: 100px;
  background: salmon;
}
</style>

?vue3,vue,前端

vue3,vue,前端

全局的api及指令的變動(dòng)

API 參考 | Vue.js,大家先自行參考,后續(xù)深入學(xué)習(xí)時(shí)再進(jìn)行更新。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-842902.html

結(jié)語(yǔ)

  • 如果想在 vue3 中使用 element,請(qǐng)下載 element-plus
  • vue3 的文檔是最全的。Vue.js - 漸進(jìn)式 JavaScript 框架 | Vue.js

到了這里,關(guān)于Vue3基礎(chǔ)看這一篇就夠了(萬(wàn)字長(zhǎng)篇,附實(shí)例代碼及效果演示)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 【多線程基礎(chǔ)】 線程安全及解決方案(看這一篇就夠了)

    【多線程基礎(chǔ)】 線程安全及解決方案(看這一篇就夠了)

    ?????? 點(diǎn)進(jìn)來(lái)你就是我的人了 博主主頁(yè): ??????戳一戳,歡迎大佬指點(diǎn)! 歡迎志同道合的朋友一起加油喔 ?????? 目錄 前言 1. 造成線程不安全的原因有哪些呢? 1.1什么是原子性 1.2什么是內(nèi)存可見性 1.3共享變量可見性實(shí)現(xiàn)的原理 ?1.4 什么是指令重排序 2.解決線程安全

    2024年02月02日
    瀏覽(25)
  • 【Linux】shell編程基礎(chǔ)(超詳細(xì),入門看這一篇就夠了)

    【Linux】shell編程基礎(chǔ)(超詳細(xì),入門看這一篇就夠了)

    ????【Liunx學(xué)習(xí)記錄篇】???? 篇一:【Linux】VMware安裝unbuntu18.04虛擬機(jī)-超詳細(xì)步驟(附鏡像文件) 篇二:【Linux】ubuntu18.04系統(tǒng)基礎(chǔ)配置及操作 篇三:【Linux】用戶與組的操作詳細(xì)介紹 篇四:【Linux】管理Linux文件權(quán)限屬性介紹 篇五:【Linux】使用數(shù)字表示法和文件表示法修

    2024年02月04日
    瀏覽(41)
  • 【C→C++】打開C++世界的大門(C++基礎(chǔ)入門,看這一篇就夠了)

    【C→C++】打開C++世界的大門(C++基礎(chǔ)入門,看這一篇就夠了)

    這篇文章開始,我們正式進(jìn)入C++的學(xué)習(xí)。 什么是C++ C語(yǔ)言是結(jié)構(gòu)化和模塊化的語(yǔ)言,適合處理較小規(guī)模的程序。 對(duì)于復(fù)雜的問(wèn)題,規(guī)模較大的程序,需要高度的抽象和建模,C語(yǔ)言則不合適。 為了解決軟件危機(jī), 20世紀(jì)80年代, 計(jì)算機(jī)界提出了OOP(object oriented programming:面向?qū)?/p>

    2024年02月07日
    瀏覽(15)
  • 精通線程池,看這一篇就夠了

    精通線程池,看這一篇就夠了

    當(dāng)我們運(yùn)用多線程技術(shù)處理任務(wù)時(shí),需要不斷通過(guò)new的方式創(chuàng)建線程,這樣頻繁創(chuàng)建和銷毀線程,會(huì)造成cpu消耗過(guò)多。那么有沒有什么辦法 避免頻繁創(chuàng)建線程 呢? 當(dāng)然有,和我們以前學(xué)習(xí)過(guò)多連接池技術(shù)類似,線程池通過(guò)提前創(chuàng)建好線程保存在線程池中, 在任務(wù)要執(zhí)行時(shí)取

    2023年04月17日
    瀏覽(97)
  • ElasticSearch常見用法,看這一篇就夠了

    ElasticSearch常見用法,看這一篇就夠了

    2024送書福利正式起航 關(guān)注「哪吒編程」,提升Java技能 文末送3本《一本書講透Elasticsearch:原理、進(jìn)階與工程實(shí)踐》 大家好,我是哪吒。 ElasticSearch是一款由Java開發(fā)的開源搜索引擎,它以其出色的實(shí)時(shí)搜索、穩(wěn)定可靠、快速安裝和方便使用的特性,在Java開發(fā)社區(qū)中贏得了廣

    2024年03月19日
    瀏覽(94)
  • 超圖(HyperGraph)學(xué)習(xí),看這一篇就夠了

    超圖(HyperGraph)學(xué)習(xí),看這一篇就夠了

    最近事多,好久沒更新了,隨便寫寫(Ctrl+V)點(diǎn) 一、超圖定義 通常圖論中的圖,一條edge只能連接2個(gè)vertex,在超圖中,不限量 如何理解呢,就用我正在做的KT問(wèn)題來(lái)看:7道題目-7個(gè)頂點(diǎn);4種概念-4條超邊,其中第1,2,3題都是考察概念1的,則構(gòu)建一個(gè)包含了這仨的超邊,以此類

    2024年02月02日
    瀏覽(27)
  • SourceTree使用看這一篇就夠了

    SourceTree使用看這一篇就夠了

    ?你夢(mèng)想有一天成為git大師,然而面對(duì)復(fù)雜的git命令,你感覺TMD這我能記得住嗎?你曾經(jīng)羨慕從命令行敲git命令,才會(huì)更加炫酷,然而時(shí)間一長(zhǎng),TMD命令我有忘了。那么今天我介紹的這款工具會(huì)讓你從git命令中解救出來(lái),這就是git可視化工具SourcTree。 事實(shí)上Git的功能十分強(qiáng)大

    2024年02月08日
    瀏覽(23)
  • Docker Volume 看這一篇就夠了

    Docker Volume 看這一篇就夠了

    默認(rèn)情況下,在容器內(nèi)創(chuàng)建的所有文件都存儲(chǔ)在可寫容器層上。這意味著: 當(dāng)該容器不再存在時(shí),數(shù)據(jù)不會(huì)持續(xù)存在,并且如果另一個(gè)進(jìn)程需要數(shù)據(jù),則可能很難將數(shù)據(jù)從容器中取出。 容器的可寫層與運(yùn)行容器的主機(jī)緊密耦合。您無(wú)法輕松地將數(shù)據(jù)移動(dòng)到其他地方。 寫入容

    2024年02月02日
    瀏覽(106)
  • CAS自旋鎖,看這一篇就夠了

    前序 時(shí)隔多年,杰倫終于出了新專輯,《最偉大的作品》讓我們穿越到1920年,見到了馬格利特的綠蘋果、大利的超現(xiàn)實(shí)、常玉畫的大腿、莫奈的睡蓮、徐志摩的詩(shī)… 他說(shuō)“最偉大的作品”并不是自己的歌,而是這個(gè)世界上最偉大的藝術(shù)作品們。 為什么要寫CAS自旋鎖呢?最近

    2023年04月08日
    瀏覽(19)
  • 還不會(huì)拓?fù)渑判颍靠催@一篇就夠了

    還不會(huì)拓?fù)渑判??看這一篇就夠了

    拓?fù)渑判蚴且环N有向無(wú)環(huán)圖(DAG)的頂點(diǎn)排序方法,它將一個(gè)有向無(wú)環(huán)圖中的所有頂點(diǎn)排成一個(gè)線性序列,使得圖中 任意一條有向邊上的起點(diǎn)排在終點(diǎn)的前面 。 這樣說(shuō)還不夠具體,我們先來(lái)看一個(gè)例子。假設(shè)某大學(xué)的課程安排如下: 課程編號(hào) 課程名稱 先修課程 1 1 1 高等數(shù)

    2023年04月08日
    瀏覽(74)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包