第十三步:vue

Vue

1、上手

1、安裝

  • 使用命令:npm create vue@latest
  • vue文件后綴為.vue
  • const app = createApp(App):初始化根組件
  • app.mount("#app"):掛載根組件到頁面

2、文件

  • script標簽:編寫js
  • template標簽:編寫html
  • style標簽:編寫css

2、樣式

1、樣式設置

  • style標簽內,編寫樣式
  • template標簽內,元素節點通過class定義類名

2、樣式隔離

style標簽通過scoped,能夠進行組件之間的樣式隔離

3、樣式穿透

  • vue2中使用::v-deep前綴修飾

    ::v-deep .box {}
    
  • vue3中使用:deep(.box)進行包裹

    :deep(.box) {}
    

4、使用less

  • 安裝less

  • 修改標簽:<style scoped lang="less"></style>

3、渲染

1、基礎渲染

  • 定義常量:const num = 10
  • 顯示常量:<div>{{ num }}</div>
  • 計算顯示:<div>{{ num - 2 }}</div>
    • 能夠在數據顯示中,進行js邏輯執行
  • 設置動態屬性:
    • 定義屬性:const idName = "box"
    • 綁定屬性:<div v-bind:id="idName">vue</div>
    • 簡寫:<div :id="idName">vue</div>
  • 設置多個屬性:
    • 定義屬性:const attr = { id: "box" }
    • 綁定屬性:<div v-bind="attr"></div>
  • 渲染HTML:
    • 定義:const dom = "<span>vue</span>"
    • 渲染:<div v-html="dom"></div>
    • 注意:此時div不能添加內容
  • 類名綁定:
    • 單類名:<div :class="className">vue</div>
    • 多類名:<div :class="[class1, class2]">vue</vue>
    • 可控類名:<div :class="{ active: isActive }">vue</div>

2、條件渲染

  • 定義變量:const show = false
  • 判斷顯示:<div v-show="show">隱藏</div>
  • 判斷顯示:<div v-if="show">消失</div>
  • 區別:
    • v-show:節點會進行構建、布局和渲染,但是會設置display為none進行隱藏
    • v-if:節點不參與構建、頁面沒有該節點
    • v-else:配合v-if使用,v-ifv-elsev-else-if

3、列表渲染

  • 定義數組:const list = [1, 2, 3]
  • 列表遍歷:<div v-for="(item, index) in list" :key="index">{{item}}</div>
  • 屬性key:提供給vue,方便節點插入刪除,提高性能
  • 空數組時隱藏
  • 優先度小于v-showv-if
  • 不建議和v-if一起使用

4、事件響應

  • 語法:v-on:事件類型="綁定函數名"

  • 簡寫:@:事件類型="綁定函數名"

  • 綁定事件函數:<button @click="fn">按鈕</button>

  • 事件傳值:

    • 調用傳值:<button @click="fn('value')">按鈕</button>
    • 事件對象:
      • <button @click="fn($event)">按鈕</button>
      • <button @click="(e) => fn(e)">按鈕</button>
  • 事件修飾:

    • @click.stop:阻止事件冒泡
    • @click.prevent:阻止默認事件
    • @click.self:事件只作用與本身
    • @click.once:事件只執行一次
    • @click.capture:事件在捕獲階段執行
    • @scroll.passive:先執行滾動,然后再執行監聽函數,避免滾動卡頓
    • 鏈式:
      • @click.stop.prevent:阻止冒泡、阻止默認
      • 需要注意鏈式調用順序
  • 按鍵修飾:

    • @keyup.enter:僅enter按鍵彈起時觸發
    • @keyup.tab
    • @keyup.delete
    • @keyup.esc
    • @keyup.space
    • @keyup.up
    • @keyup.down
    • @keyup.left
    • @keyup.right
    • @keyup.ctrl
    • @keyup.alt
    • @keyup.shift
    • @keyup.meta:菜單鍵
    • 鏈式:@keyup.alt.enter:符合按鍵alt + enter
    • 點擊組合:@click.ctrl:點擊 + ctrl
  • 鼠標修飾

    • @click.exact:沒有任何按鍵時觸發
    • @click.left:鼠標左鍵觸發
    • @click.right:鼠標右鍵觸發
    • @click.middle:鼠標輔助鍵觸發

5、動態數據

1、定義
  • vue3:使用ref定義數據。const count = ref(0)
    • 返回值:初始化的變量
    • 參數:初始化的值
    • 元素內可以直接使用
    • 元素外需要通過count.value訪問
  • vue3:使用reactive定義數據:const data = reactive({ count: 1 })
    • 返回值:初始化的復雜變量
    • 參數:需要代理的對象,數組等。無法代理普通類型數據
    • 元素內外可以直接使用
2、綁定和顯示

和其他常量一樣,直接進行使用

4、修改
  • 節點內:<button @click="count++">{{ count }}</button>
  • 節點外:function fn() { count.value++ }
5、雙向綁定
  • v-model:輸入框數據雙向綁定

    • 使用:<input type="text" v-model="text" />

    • 相當于:

      <inputtype="text":value="text"@input="event => text = event.target.value"
      />
      
  • 修飾:

    • v-model.lazy:相當于綁定@change
    • v-model.number:只輸入數字
    • v-trim:去掉兩端空格
6、計算屬性
  • const num = computed(() => count):獲取計算屬性
    • 只有當count響應變量變化時,才會重新計算num數據。
    • 能夠對數據進行緩存,如computed(() => Date.now())
7、數據監聽
  • watch(data, callback):數據監聽

    • data:監聽的數據
    • callback:監聽函數
      • 參數一:可選,變化后的值
      • 參數二:可選,變化前的值

    • data:監聽多個數據,[data1, data2]

    • callback:監聽函數

      • 參數一:可選,變化后的值,[data1, data2]
      • 參數二:可選,變化前的值,[data1, data2]
  • watchEffect(callback):數據監聽

    • 組件中,多個響應數據發生變化,組件會等待所有數據變化完后,統一刷新一次
    • 觸發條件:
      • 響應數據發送變化
      • callback函數中,只用使用到的數據才會被監聽。
      • 組件掛載完成后,也會被觸發
8、強行刷新
  • 由于統一刷新機制,某個響應變量需要提前響應,需要強行刷新
  • nextTick():強行刷新函數

6、插槽

slot組件:定義插槽,就是子元素渲染位置

1、渲染內容
<template><h3>Box</h3><slot />
</template>
2、默認內容
<template><h3>Box</h3><slot>這里是插槽默認內容</slot>
</template>
3、具名插槽
  • <slot name="header"></slot>:定義插槽名稱
  • <template v-slot:name>插入內容</template>
4、動態插槽名
  • <template v-slot:[動態響應變量]>插入內容</template>
5、插槽傳值
  • 普通插槽

    • 傳值:<slot :text="傳值"></slot>

    • 讀取:

      <template v-slot="slotProps"><p>插槽 {{ slotProps.text }}</p></template>
      
  • 具名插槽:

    • 傳值:<slot name="header" :text="傳值"></slot>

    • 讀取:

      <template v-slot:header="slotProps"><p>插槽 {{ slotProps.text }}</p>
      </template>
      

7、動態組件

  • 使用component組件動態加載不同組件
  • 使用:<component :is="組件名" />

4、組件傳值

1、父傳子

  • 傳值

    • 通過屬性之間傳值
    • 通過v-bind傳遞動態屬性變量,或者方法
  • 讀取

    • 子組件通過:const props = defineProps(["屬性名"]) 讀取屬性、方法

    • props只讀,無法修改

    • defineProps:

      • 參數為數組:讀取屬性名
      • 參數為對象:設置props的數據類型,必填、默認值
        • 屬性名稱:值可以為數據類型,可以為對象
          • type:數據類型
          • required:是否必填
          • default:默認值
          • validator:自定義校驗
      const props = defineProps({propA: Number,propB: [Number, String],propC: Function,propD: {type: String,required: true,default: "必填"},propF: {validator(value, props) {return ["success", "error"].includes(value);}}
      })
      

  • 綁定事件:<Box @submit="callback" />

  • 觸發事件:

    • <button @click="$emit('submit')">按鈕</button>

    • 使用const emit = defineEmits(['事件名'])接受事件

      • emit('事件名'):調用事件
    • 傳值:

      • $emit("事件名", arg1, arg2)
      • emit("時間嗎", arg1, arg2)

  • 單個v-model

    • 綁定v-model:<Box v-model="text" />
    • 獲取model:const model = defineModel([optons])
      • options:可選
        • required:是否必填
  • 具名v-model

    • 綁定v-model:<Box v-model:title="text" />
    • 獲取model:const title = defineModel('title'[, options])
      • 參數一:名稱
      • options:可選,同上
  • 多個v-model

    • 綁定多個v-model

      <Box v-model:title="title" v-model:text="text" />
      
    • 獲取model

      const title = defineModel("title")
      const text = defineModel("text")
      

  • 讀取attrs
    • 使用$attrs直接進行讀取
    • 使用:const attrs = useAttrs() 獲取
  • 讀取slots
    • 使用$slots直接進行讀取
    • 使用:const solts = useSlots() 獲取

2、父讀子

  • 子組件通過defineExpose({ 變量, 方法 }),暴漏自身變量和方法
  • 父組件通過const child = useTemplateRef(refName)獲取綁定ref的子組件
  • 父組件通過ref屬性綁定refName:<Box ref="refName" />
  • 父組件讀取:child.value.名稱
  • 父組件調用:child.value.名稱()

  • 如果ref綁定的是html標簽元素,直接通過 refName.名稱 進行讀取和調用

3、兄弟傳值

  • 共享父組件響應變量傳值
  • 使用pinia狀態管理傳值

4、上下文

  • 單個數據
    • 父組件提供:provide(key, value)
    • 子組件注入:const value = inject(key)
  • 多個數據
    • 父組件提供:provide(key, value, setValue)
    • 子組件注入:const { value, setValue } = inject(key)
  • provide可以多次調用,inject也可以多次調用

5、生命周期

  • onBeforeMount(fn):加載前
  • onMounted(fn):加載后
  • onBeforeUpdate(fn):數據變化前
  • onUpdated(fn):數據變化后
  • onBeforeUnmount(fn):卸載前
  • onUnmounted(fn):卸載后
  • onErrorCaptured(fn):子組件出現錯誤鉤子函數
  • onActivated(fn):
    • 首次掛載時調用
    • 每次從緩存中重新插入
  • onDeactivated(fn):
    • 卸載時調用
    • 從緩存中卸載時調用
  • onServerPrefetch(fn):異步組件在服務器上渲染之前觸發

1、加載前

  • script標簽內,直接執行的代碼就是組件加載前執s行
  • onBeforeMount(callback):加載前執行

2、加載后

  • onMounted(callback):加載后執行

3、變化后

  • watch:監聽數據變化完成
  • watchEffect:監聽數據變化完成

4、卸載前

  • onBeforeUnmount(callback):卸載前執行

5、進出動畫

1、條件渲染
  • 使用v-ifv-show等控制組件進入進出時,渲染動畫

  • 使用組件Transition完成動畫

    <Transition><div v-if="show">內容</div>
    </Transition>
    
  • 基于css過度

    • Transition默認會給包裹子節點添加6個類名
      • .v-enter-from:渲染前className,定義元素進入頁面前的樣式
      • .v-enter-active:渲染中className,定義元素進入頁面時的CSS動畫
      • .v-enter-to:渲染后className,定義元素進入頁面后的樣式
      • .v-leave-from:卸載前className,定義元素退出頁面前的樣式
      • .v-leave-active:卸載時className,定義元素退出頁面時的CSS動畫
      • .v-leave-to:卸載后className,定義元素退出頁面后的樣式
    • Transition設置name屬性:<Transition name="fade">
      • .v-enter-from就需要改為.fade-enter-from
  • 自定義css

    • Transition可以自定義類名
      • enter-from-class:重定義.v-enter-from類名
      • enter-active-class:重定義.v-enter-active類名
      • enter-to-class:重定義.v-enter-to類名
      • leave-from-class:重定義.v-leave-from:類名
      • leave-active-class:重定義.v-leave-active類名
      • leave-to-class:重定義.v-leave-to類名
  • 動畫鉤子函數

    • Transition每個動畫階段都有鉤子事件函數

      • @before-enter:進入頁面前觸發事件
      • @enter:進入頁面時觸發事件
      • @after-enter:進入頁面后觸發事件
      • @enter-cancelled:進入動畫完成后,觸發事件
      • @before-leave:退出頁面前觸發事件
      • @leave:退出頁面時觸發事件
      • @after-leave:退出頁面后觸發事件
      • @leave-cancelled:退出動畫完成后,觸發事件
    • Transition組件在使用鉤子函數時,建議設置css屬性為false

    • 事件綁定函數,參數一為當前元素指向

    • @enter@leave還有參數二,為動畫完成后回調函數。告訴vue動畫以及完成

      <template><div><h1>app</h1><button @click="toggle">按鈕</button><Transitionname="fade"@enter="activeEnter"@leave="leaveEnter"><div v-if="show">內容</div></Transition></div>
      </template><script setup>
      import { ref } from 'vue'
      import { gsap } from 'gsap'const show = ref(false)
      function toggle() {show = !show
      }function activeEnter(el, done) {gsap.fromTo(el,{ x: -100, opacity: 0 },{ x: 0, opacity: 1, duration: 1 }).then(done)
      }function leaveEnter(el, done) {gsap.fromTo(el,{ x: 0, opacity: 1 },{ x: 100, opacity: 0, duration: 1 }).then(done)
      }
      </script>
      
  • 渲染時動畫

    • 不依靠v-ifv-show控制,而是組件mount時進行動畫
    • Transition組件添加appear屬性
  • 替換動畫

    • 當使用v-ifv-else進行組件替換時,需要設置model
    • Transition組件添加設置model="out-in"
  • 組件替換

    • 當使用component 組件進行動態組件替換時
    • Transition組件添加設置model="out-in"
2、列表渲染
  • 使用組件TransitionGroup完成v-for的動畫渲染

  • 組件TransitionGroupTransition擁有基本相同的props

    • 多一個.v-move的類名,用于元素的過度
    • 多一個tag屬性,用于創建一個元素標簽
    .list-move, /* 對移動中的元素應用的過渡 */
    .list-enter-active,
    .list-leave-active {transition: all 0.5s ease;
    }.list-enter-from,
    .list-leave-to {opacity: 0;transform: translateX(30px);
    }/* 確保將離開的元素從布局流中刪除以便能夠正確地計算移動的動畫。 */
    .list-leave-active {position: absolute;
    }
    

6、Pinia

1、使用

  • 入口文件main.js,添加使用中間件

    import { createPinia } from 'pinia'// ...
    app.use(createPinia())
    
  • 定義數據

    • 創建文件:src/stores/counter

    • 使用響應式定義數據

      import { ref, computed } from 'vue'
      import { defineStore } from 'pinia'export const useCounterStore = defineStore('counter', () => {const count = ref(0)count doubleCount = computed(() => count.value * 2)function add() {count.value++}return { count, doubleCount, add }
      })
      
  • createPinie:函數,返回一個中間件

  • defineStore(key, callback):函數

    1. key:唯一標識
    2. callback:使用響應式創建數據和方法

2、數據使用

  • 引入Store:import { useCounterSotre } from "@/stores/counter"

  • 使用:

    <template><div>{{ counter.count }}</div><button @click="counter.add">按鈕</button>
    </template><script setup>
    import { useCounterStore } from "@/stores/counter"
    const counter = useCounterStore()
    </script>
    
  • 注意:

    • 不要對counter進行結構,否則無法進行數據響應變化
    • 原因:結構后相當于重新賦值,所以結構后的值不會發生任何變化

3、數據監聽

  • store內監聽

    • 直接使用watchwatchEffect進行數據監聽即可
    • 然后使用sessionStorage或者loactStorage完成數據持久化
  • 組件內監聽

    • 也使用watchwatchEffect進行數據監聽,需要深層次監聽

      watch(() => store.count,() => {// 數據變化時觸發}
      )
      

4、異步修改

  • 直接在方法里,進行數據異步修改即可

5、模塊化

  • 直接修改defineStore的key值,實現不過store不同唯一標識

6、外部使用

  • 直接在外部js文件中引入store,然后使用store方法即可

7、路由

1、路由使用

  • const router = createRouter(options):創建路由配置

  • app.use(router):中間件的方式使用router

  • RouterView:渲染路由頁面組件

  • options配置項

    • history:定義路由模式

      • createWebHistory(import.meta.env.BASE_URL):定義history模式
      • createWebHashHistory(import.meta.env.BASE_URL):定義hash模式
    • routers:定義路由列表

      • router-item配置
        • path:路由地址
        • name:路由別名
        • meta:原信息
        • component:組件
        • redirect:路由重定向
        • children:子路由列表
    • 404

      routes: [{ path: '/:catchAll(.*)', component: Error }
      ]
      

2、路由跳轉

  • const router = useRouter():獲取router操作
    • router.back():返回上一個路由
    • router.go(number):返回數值步路由
      • number可以為負
        • 1,向前1步。
        • -1,向后1步。
        • 0,刷新路由
    • router.push(path):路由跳轉
      • 參數為字符串時,直接進行路由跳轉
      • 參數為對象時
        • path:路由路徑
        • query:路由query傳遞參數

3、子路由

  • 定義子路由

    const router = createRouter({history: createWebHistory(import.meta.env.BASE_URL),routes: [{ path: "/", redirect: "/home" },{path: "/home",component: Home,children: [{ path: "/home/one", component: HomeOne },{ path: "/home/two", component: HomeTwo },]}]
    })
    
  • 使用子路由

    <template><h1>home</h1><RouterView />
    </template>
    

5、路由傳值

  • 路由傳值,也就是get請求傳參。
    • params:url/:id,需要對路由路徑進行修改
    • query:url?a=1&b=2
    • hash:url#123
  • 傳值參數
    • 獲取路由操作:const router = useRouter()
    • params傳遞:router.push("url/123456")
    • query傳遞:
      • router.push("url?a=10&b=10")
      • router.push({ path: "url", query: { a: 10, b: 10 } })
    • hash傳值:router.push("url#123456")
  • 讀取參數
    • 獲取路由讀取:const route = useRoute()
    • 讀取param:const param = route.param
    • 讀取query:const query = route.query
    • 讀取hash:const hash = route.hash
    • 讀取meta:const meta = route.meta
    • 讀取完整路徑:const fullPath = route.fullPath

6、路由懶加載

const router = createRouter({history: createWebHistory(import.meta.env.BASE_URL),routes: [{path: "/home",component: () => import("@/view/Home.vue")}]
})

7、跳轉守衛

  • 跳轉前攔截:router.beforeEach((to, from ,next) => {})
  • 跳轉后攔截:router.afterEach((to, from) => {})

8、路由進度條

  • 插件:nprogress
  • 引入:
    • 引入組件:import NProgress from 'nprogress';
    • 引入樣式:import 'nprogress/nprogress.css';
  • 使用:
    • 開啟:NProgress.start()
    • 結束:NProgress.done()
    • 設置進度:
      • NProgress.set(0.4):0~1之間
      • NProgress.inc():設置隨機進度
  • 配置:NProgress.config(options)
    • minimum:進度條的最小百分比,默認0.08
    • easing:動畫動作 [ease、linear]
    • speed:動畫速度,默認200
    • showSpinner:是否顯示旋轉加速器,默認true
    • parent:進度條父容器,默認body

9、進出動畫

  • 首先創建store,存儲路由變化狀態,默認為false
  • 路由跳轉前,修改狀態為true
    • 注意:必須在router.beforeEach回調內使用useStore,否則報錯
    • 原因:在外面使用,路由組件還未進行掛載,pinia也為進行掛載
  • 路由跳轉后,修改狀態為false
  • 在layout組件,也就是使用RouterView組件內,監聽狀態
  • 如果狀態為true,控制RouterView外殼元素進行gsap離開動畫
  • 如果狀態為false,控制RouterView外殼元素進行gsao進入動畫

10、路由封裝

  • 自動讀取views文件內的index.vue
  • 自動構建路由
import { createRouter, createWebHistory } from 'vue-router'const history = createWebHistory(import.meta.env.BASE_URL)
const routes = [{ path: '/', redirect: '/home' }]
const globModel = import.meta.glob(`@/views/**/index.vue`)Object.entries(globModel).forEach(([file, model]) => {const segments = file.split('/')let current = {}let path = ''for (let i = 3; i < segments.length; i++) {const segment = segments[i]if (segment === 'index.vue') {current.component = model} else {let list = routesif (i !== 3) {if (!current.children) current.children = []list = current.children}path += '/' + segmentconst child = list.find((child) => child.path === path)if (child) current = childelse {current = { path }list.push(current)}}}
})routes.push({path: '/:catchAll(.*)',component: () => import('@/views/ErrorView.vue'),
})export default createRouter({ history, routes })

8、指令

1、v-html

正常渲染的數據都是字符串,v-html能把html字符串渲染成html節點

2、v-bind

  • 動態綁定屬性:<div v-bind:id="idName">vue</div>
  • 簡寫:<div :id="idName">vue</div>
  • 綁定多個屬性:<div v-bind="attr"></div>

3、v-show

  • 控制隱藏:<div v-show="show">vue</div>
  • 通過變量,控制display樣式,進行顯示或隱藏

4、v-if

  • 控制渲染:<div v-if="show">vue</div>
  • 通過變量,控制節點是否渲染,進行顯示或隱藏

5、v-for

  • 列表渲染:<div v-for="(item, index) in list" :key="index">{{ item }}</div>
  • 進行遍歷,可以結構出下標
  • 需要綁定key屬性,讓vue能夠更好進行節點計算,提高性能
  • 空數組時隱藏
  • 優先度小于v-ifv-show
  • 不建議和v-if一起使用
  • 配套使用:v-ifv-elsev-else-if

6、v-on

  • 綁定事件

7、v-model

  • 雙向綁定
  • 相當于:v-bind:value + v-on:input

8、v-slot

  • 使用具名插槽:<template v-slot:插槽名稱>內容</template>
  • 簡寫:<template #插槽名稱>內容</template>

9、v-pre

  • 所有 Vue 模板語法都會被保留并按原樣渲染
  • 如:<span v-pre>{{ 123 }}</span>
  • 渲染成:<span>{{ 123 }}</span>

10、自定義

  • app.directive(name, callback):自定義指令

    • app:createApp創建的根節點

    • name:指令名稱,使用為v-名稱

    • callback:

      • 函數時

        • 參數一:使用的元素

        • 參數二:賦值的參數

        • 案例:

          <div v-color="color"></div>app.dircetive('color', (el, binding) => {el.style.color = binding.value
          })
          
      • 對象時:

        • created(el, binding, vnode):創建節點后

        • beforeMount(el, binding, vnode):掛載前

        • mounted(el, binding, vnode):掛載后

        • beforeUpdate(el, binding, vnode, prevVnode):更新前

        • update(el, binding, vnode, prevVnode):更新后

        • beforeUnmount(el, binding, vnode):卸載前

        • unmounted(el, binding, vnode):卸載后

        • el:使用的元素

        • binding:賦值的參數

        • vnode:綁定元素的底層vnode

        • prevVNode,代表之前的渲染中指令所綁定元素的 VNode

        • 案例:

          <div v-color="color"></div>app.dircetive('color', {mounted(el, binding) {el.style.color = binding.value}
          })
          

9、組件

  • template:空標簽組件

  • computed:組件加載空標簽

  • Transition:過度動畫標簽

  • TransitionGroup:列表過度動畫標簽

  • KeepAlive:

    • 緩存組件

      <KeepAlive><component :is="activeComponent" />
      </KeepAlive>
      
    • 排除:include

      <KeepAlive :include="['a', 'b']"><component :is="view" />
      </KeepAlive>
      
    • 最大緩存數:max

      <KeepAlive :max="10"><component :is="activeComponent" />
      </KeepAlive>
      
    • 生命周期

      • onActivated:掛載時,從緩存中重新掛載時,觸發
      • onDeactivated:卸載時,從緩存中卸載時,調用
  • Teleport:選擇掛載節點

    <Teleport to="body"><div>該節點將添加掛載到body上</div>
    </Teleport>
    
  • 組件全局注冊

    • vue3中,局部組件之間引入即可使用
    • vue3中,全局組件注冊:app.component(組件名, 組件)

10、API

  • app.use():使用插件

  • app.mount():掛載節點

  • app.directive(name, options):自定義指令

  • app.component(name, component):注冊全局組件

  • h:渲染函數,創建虛擬dom

    • 參數一:標簽、或者組件名稱
    • 參數二:標簽的屬性,事件
    • 參數三:子節點
  • ref:定義并初始化響應數據

  • nextTick:響應數據變化后,強行刷新組件函數

  • reactive:定義并初始化復雜類型數據

  • readonly:設置并返回響應數據只讀

    import {ref, readonly} from "vue"
    const count = ref(0)
    const copyCount = readonly(count)
    
  • computed:定義并通過函數處理獲取數據

  • watch:對數據進行監聽

  • watchEffect:對使用數據進行監聽

  • defineProps:讀取props

  • defineEmits:讀取組件綁定事件

  • defineModel:讀取v-model

  • defineOptions:設置組件

    • inheritAttrs:是否Attributes繼承
  • defineExpose:拋給ref變量,方法,函數

  • provide:提供上下文

  • inject:注冊上下文

11、變量

  • $attrs:讀取組件被設置的屬性
  • $event:讀取事件綁定元素本身的事件對象
  • $slot:讀取組件的所有slot
    • 具名插槽:$slot.名稱
    • 非具名:$slot.default
  • $emit("事件名稱"):觸發組件綁定的事件

12、函數與插件

1、函數

  • 在pinia中,就能看到vue的api是可以單獨在函數中使用

  • 所以vue的script標簽內部的重復邏輯可以提取到外部

  • 組合式函數約定駝峰命名,并以use開頭

  • import { ref } from 'vue'function useCount(init) {const count = ref(init)functoin add() {count++}return { count, add }
    }export default useCount
    
  • 使用:const { count, addCount } = useCount()

2、插件

  • 插件本質是一個函數

  • 定義一個插件:

    function addDir(app) {app.directive('color', (el, binding) => {el.style.color = binding.value})
    }
    
  • 使用插件:app.use(addDir)

13、請求

// src/utils/api.js 封裝class Api {constructor(baseurl, timeOut) {this.baseurl = baseurl;this.timeOut = timeOut || 10000;}async #request(url, method = "GET", data, json = false, fileName) {const path = this.baseurl + url;const controller = new AbortController();const config = { method, signal: controller.signal };const timeoutPromise = new Promise((_, reject) =>setTimeout(() => {controller.abort();reject(new Error("請求超時"));}, this.timeOut));if (data) {config.body = json ? JSON.stringify(data) : data;if (json) config.headers = { "Content-Type": "application/json" };}try {const res = await Promise.race([fetch(path, config), timeoutPromise]);if (!res.ok) throw new Error(res.statusText);// 進行接口響應后攔截邏輯 - 可通過響應頭獲取登錄狀態等const contentType = res.headers.get("content-type").split(";")[0].trim();if (!contentType) throw new Error("Unknown content type");// 處理文件下載if (fileName) {const resData = await res.arrayBuffer();this.#downloadFile(resData, contentType, fileName);return { success: true };}// 返回請求結果return contentType === "application/json"? await res.json(): await res.text();} catch (error) {throw new Error(`請求失敗: ${error.message}`);}}#downloadFile(res, contentType, fileName) {const blob = new Blob([res], { type: contentType });const url = URL.createObjectURL(blob);const a = document.createElement("a");a.href = url;a.download = fileName;a.click();URL.revokeObjectURL(url);a.remove();}get(url, query, param) {let path = url;if (query) path += "?" + new URLSearchParams(query).toString();if (param) path += "/" + param;return this.#request(path);}post(url, data) {return this.#request(url, "POST", data, true);}postByFormData(url, data) {let formData = new FormData();for (const key in data) {formData.append(key, data[key]);}return this.#request(url, "POST", formData);}download(url, fileName = "file") {this.#request(url, "GET", null, false, fileName);}upload(url, file, key = "file") {const formData = new FormData();formData.append(key, file);return this.#request(url, "POST", formData);}uploads(url, files, key = "files") {const formData = new FormData();for (const file of files) {formData.append(key, file);}return this.#request(url, "POST", formData);}
}let baseurl = import.meta.env.MODE === "production" ? "" : "/api";
let api = new Api(baseurl);
export default api;

14、服務代理

// vite.config.js
// ...const default defineConfig({// ...server: {proxy: {'/api': {target: 'http://localhost:3000',changeOrigin: true,rewrite: (path) => path.replace(/^\/api/, '')},'/bpi': {target: 'http://localhost:3001',changeOrigin: true,rewrite: (path) => path.replace(/^\/bpi/, '')}}}
})

15、環境變量

  • 讀取環境變量:import.meta.env
  • 環境判斷
    • import.meta.env.MODE === development:開發環境
    • import.ment.env.MODE === production:生產環境
  • 設置變量
    • 創建.env文件
    • 創建變量:VITE_NAME=hello
    • 變量前綴需為:VITE_
  • env文件
    • .env文件:所有環境都能訪問
    • .env.development:開發環境才能訪問
    • .env.production:生產環境才能訪問

16、別名配置

  • resolve-alias:配置別名

    // vite.config.js
    import { fileURLToPath, URL } from 'node:url'
    import { defineConfig } from 'vite'export default defineConfig({resolve: {alias: {"@": fileURLToPath(new URL('./src', import.meta.url))}}
    })
    

17、靜態資源

  • 樣式使用
    • public:background: url("/public/images/bg.jpg")
    • src/assets:background: url("./assets/images/bg.jpg")
  • src使用
    • public:<img alt="#" src="/public/images/bg.jpg" />
    • src/assets:<img alt="#" src="./assets/images/bg.jpg" />
  • 打包:
    • public:文件會被復制
    • src/assets:文件會被編譯,壓縮(需要配置),文件名會發生變化

18、校驗規則

  • 腳手架創建項目時,能夠選擇eslint

  • 對eslint微調

    • eslint.config.js中,添加對象

    • // eslint.config.js
      // ...
      export default defineConfig([// ...{rules: {'no-console': 'off'}}
      ])
      
  • 對prettier微調

    • 在.prottierrc.json內直接修改

19、渲染函數

  • 導入渲染函數:import { h } from 'vue'

  • 創建dom

    import { h } from 'vue'
    const vnode = h('div', { class: 'box' }, 'hello world vue3')
    
  • 配置attr

    • 配置id:h('div', { id: 'box' })
    • 配置class:h('div', { class: 'box' })
    • 配置style:h('div', { style: { color: 'red' } })
  • 事件綁定

    • import { h } from 'vue'
      const handleClick = () => alert('hello world')
      const vnode = h('div', { onClick: handleClick })
      
    • 綁定其他事件:使用jsx的形式綁定,如onInput

    • v-model:

      import { h, ref } from 'vue'
      const text = ref('')
      const vnode = h('input',{type: 'text',value: text.value,onInput: (e) => {text.value = e.target.value}}
      )
      
  • 子節點

    • 單個子節點:h('div', vnode)
    • 多個子節點:h('div', [vnode1, vnode2])
  • 組件

    • 創建組件節點

      import Home from "@/views/Home.vue"
      import { h } from 'vue'
      const vnode = h('Home', { class: 'home' })
      

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/80914.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/80914.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/80914.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Pytest-mark使用詳解(跳過、標記、參數 化)

1.前言 在工作中我們經常使用pytest.mark.XXXX進行裝飾器修飾&#xff0c;后面的XXX的不同&#xff0c;在pytest中有不同的作 用&#xff0c;其整體使用相對復雜&#xff0c;我們單獨將其抽取出來做詳細的講解。 2.pytest.mark.skip()/skipif()跳過用例 import pytest #無條…

基于 Spring Boot 的井字棋游戲開發與實現

目錄 引言 項目概述 項目搭建 1. 環境準備 2. 創建 Spring Boot 項目 3. 項目結構 代碼實現 1. DemoApplication.java 2. TicTacToeController.java 3. pom.xml 電腦落子策略 - Minimax 算法 findBestMove 方法 minimax 方法 運行游戲 總結 引言 在軟件開發領域&…

【算法筆記】貪心算法

一、什么是貪心算法&#xff1f; 貪心算法是一種在每一步選擇中都采取當前看起來最優&#xff08;最“貪心”&#xff09;的策略&#xff0c;從而希望得到全局最優解的算法設計思想。 核心思想&#xff1a;每一步都做出局部最優選擇&#xff0c;不回退。適用場景&#xff1a;…

現代c++獲取linux所有的網絡接口名稱

現代c獲取linux所有的網絡接口名稱 前言一、在linux中查看網絡接口名稱二、使用c代碼獲取三、驗證四、完整代碼如下五、總結 前言 本文介紹一種使用c獲取本地所有網絡接口名稱的方法。 一、在linux中查看網絡接口名稱 在linux系統中可以使用ifconfig -a命令列舉出本機所有網絡…

打印及判斷回文數組、打印N階數組、蛇形矩陣

打印回文數組 1 1 1 1 1 1 2 2 2 1 1 2 3 2 1 1 2 2 2 1 1 1 1 1 1方法1&#xff1a; 對角線對稱 左上和右下是對稱的。 所以先考慮左上打印&#xff0c; m i n ( i 1 , j 1 ) \text min(i1,j1) min(i1,j1)&#xff0c;打印出來&#xff1a; 1 1 1 1 1 2 2 2 1 2 3 3 1 2 …

詳解UnityWebRequest類

什么是UnityWebRequest類 UnityWebRequest 是 Unity 引擎中用于處理網絡請求的一個強大類&#xff0c;它可以讓你在 Unity 項目里方便地與網絡資源進行交互&#xff0c;像發送 HTTP 請求、下載文件等操作都能實現。下面會詳細介紹 UnityWebRequest 的相關內容。 UnityWebRequ…

UE5 在旋轉A的基礎上執行旋轉B

用徑向slider實現模型旋轉時&#xff0c;得到的結果與ue編輯器里面的結果有很大出入。 問題應該是 兩個FRotator&#xff08;0&#xff0c;10&#xff0c;0&#xff09;和&#xff08;10&#xff0c;20&#xff0c;30&#xff09;&#xff0c; 兩個FRotator的加法結果為&…

4.2 Prompt工程與任務建模:高效提示詞設計與任務拆解方法

提示詞工程&#xff08;Prompt Engineering&#xff09;和任務建模&#xff08;Task Modeling&#xff09;已成為構建高效智能代理&#xff08;Agent&#xff09;系統的核心技術。提示詞工程通過精心設計的自然語言提示詞&#xff08;Prompts&#xff09;&#xff0c;引導大型語…

MySQL 索引的最左前綴匹配原則是什么?

MySQL 索引的最左前綴匹配原則詳解 最左前綴匹配原則&#xff08;Leftmost Prefix Principle&#xff09;是 MySQL 復合索引&#xff08;聯合索引&#xff09;查詢優化中的核心規則&#xff0c;理解這一原則對于高效使用索引至關重要。 核心概念 定義&#xff1a;當查詢條件…

SQL命令

一、控制臺中查詢命令 默認端口號&#xff1a;3306 查看服務器版本: mysql –version 啟動MySQL服務&#xff1a;net start mysql 登錄數據庫&#xff1a;mysql -u root -p 查看當前系統下的數據庫&#xff1a;show databases&#xff1b; 創建數據庫&#xff1a;create…

新增 29 個專業,科技成為關鍵賽道!

近日&#xff0c;教育部正式發布《普通高等學校本科專業目錄&#xff08;2025年&#xff09;》&#xff0c;新增 29 個本科專業&#xff0c;包括區域國別學、碳中和科學與工程、海洋科學與技術、健康與醫療保障、智能分子工程、醫療器械與裝備工程、時空信息工程、國際郵輪管理…

零基礎上手Python數據分析 (23):NumPy 數值計算基礎 - 數據分析的加速“引擎”

寫在前面 —— 超越原生 Python 列表,解鎖高性能數值計算,深入理解 Pandas 的底層依賴 在前面一系列關于 Pandas 的學習中,我們已經領略了其在數據處理和分析方面的強大威力。我們學會了使用 DataFrame 和 Series 來高效地操作表格數據。但是,你是否好奇,Pandas 為何能夠…

Android 13.0 MTK Camera2 設置默認拍照尺寸功能實現

Android 13.0 MTK Camera2 設置默認拍照尺寸功能實現 文章目錄 需求&#xff1a;參考資料架構圖了解Camera相關專欄零散知識了解部分相機源碼參考&#xff0c;學習API使用&#xff0c;梳理流程&#xff0c;偏應用層Camera2 系統相關 修改文件-修改方案修改文件&#xff1a;修改…

HarmonyOS 框架基礎知識

參考文檔&#xff1a;HarmonyOS開發者文檔 第三方庫&#xff1a;OpenHarmony三方庫中心倉 基礎特性 Entry&#xff1a;關鍵裝飾器 Components&#xff1a;組件 特性EntryComponent??作用范圍僅用于頁面入口可定義任意可復用組件??數量限制??每個頁面有且僅有一個無數量…

前端分頁與瀑布流最佳實踐筆記 - React Antd 版

前端分頁與瀑布流最佳實踐筆記 - React Antd 版 1. 分頁與瀑布流對比 分頁&#xff08;Pagination&#xff09;瀑布流&#xff08;Infinite Scroll&#xff09;展示方式按頁分批加載&#xff0c;有明確頁碼控件滾動到底部時自動加載更多內容&#xff0c;無明顯分頁用戶控制用…

Linux網絡編程:TCP多進程/多線程并發服務器詳解

Linux網絡編程&#xff1a;TCP多進程/多線程并發服務器詳解 TCP并發服務器概述 在Linux網絡編程中&#xff0c;TCP服務器主要有三種并發模型&#xff1a; 多進程模型&#xff1a;為每個客戶端連接創建新進程多線程模型&#xff1a;為每個客戶端連接創建新線程I/O多路復用&am…

詳解springcloudalibaba采用prometheus+grafana實現服務監控

文章目錄 1.官網下載安裝 prometheus和grafana1.promethus2.grafana 2. 搭建springcloudalibaba集成prometheus、grafana1. 引入依賴,springboot3.2之后引入如下2. 在yml文件配置監控端點暴露配置3. 在當前啟動的應用代碼中添加&#xff0c;在prometheus顯示的時候附加當前應用…

數據分析1

一、常用數據處理模塊Numpy Numpy常用于高性能計算&#xff0c;在機器學習常常作為傳遞數據的容器。提供了兩種基本對象&#xff1a;ndarray、ufunc。 ndarray具有矢量算術運算和復雜廣播能力的快速且節省空間的多維數組。 ufunc提供了對數組快速運算的標準數學函數。 ndar…

DeepSeek智能時空數據分析(六):大模型NL2SQL繪制城市之間連線

序言&#xff1a;時空數據分析很有用&#xff0c;但是GIS/時空數據庫技術門檻太高 時空數據分析在優化業務運營中至關重要&#xff0c;然而&#xff0c;三大挑戰仍制約其發展&#xff1a;技術門檻高&#xff0c;需融合GIS理論、SQL開發與時空數據庫等多領域知識&#xff1b;空…

2023ICPC合肥題解

文章目錄 F. Colorful Balloons(簽到)E. Matrix Distances(思維小結論)J. Takeout Delivering(最短路)G. Streak Manipulation(二分dp)C. Cyclic Substrings(回文自動機) 題目鏈接 F. Colorful Balloons(簽到) int n;cin>>n;for(int i1;i<n;i) cin>>s[i];map<…