零基礎、大白話,Vue3全篇通俗療法(上):基礎知識【看得懂】

前言

????????

????????最近有個小朋友想了解Vue前端技術,但他只懂一些HTML基礎,讓我用最簡單的方式講解。于是就有了這篇面向初學者的博文。

????????老手請繞行,本文專為新手準備。如果發現用詞不當的地方歡迎留言指正,覺得對新手有幫助的話請收藏點贊。

基礎

  • 什么是Vue

它是一個前端框架、目前最新版本是Vue3、本質上就是在單個頁面上進行組件渲染。

  • 為什么是Vue

原因很多,但最重要的是生態好,學、用的人多;(參照來源各招聘平臺對于前端的要求)

  • Vue 版本選擇

作為技術,當然選擇新版本了,但相對舊版本有一些變化,新版本同時支持組合式API與選項式API,目前官方推薦采用組合式API(用到什么就引用什么速度更快)

項目\版本

VUE2

VUE3

構建工具

Vue CLI

Vite

狀態管理

VueX

Pinia

IDE 增強插件

Vetur

vue-official

靜態生成

VuePress

VitePress

  • Vue 引擎選TS還是JS

JavaScript (JS):簡單、廣泛。TypeScript(TS):類型安全、更好的可維護性。同樣都是要花精力學習的話還是推薦TS,盡管你學習了JS,還是建議你慢慢接受TS。

  • Vue Router

VUE Router 官言路由,用于跳轉用;之前用MVC是用后端Controller層控制路由跳轉,現在由前端控制。

  • Vue Panner

基于Vue3.0 狀態管理工具

  • VitePress

靜態網站成生器:VUE本質上就是在單個頁面上組裝拆解,所以它不利于SEO優化(換言之搜索引擎的網站爬不到),現在有了它就解決了這個問題。

  • 開發工具選擇

這個因人而異、可以是VSCode(免費)、也可以是WebStorm(收費),以下是常見的工具對比。

類型/常用工具

VSCode

HBuilder

WebStrom

Trae

cursor

費用

免費

免費

收費

免費

免費

插件生態評分(個人)

95

60

95

80

80

智能化(個人)

80

60

70

90

90

  • 準備

在開發的電腦上必有安裝好Node,推薦使用新版本。

  • 創建

npm init vue@3
npm init vue@3
Need to install the following packages:
create-vue@3.16.4
Ok to proceed? (y) y  //是否要創建版本為3.16.4 的VUE┌  Vue.js - The Progressive JavaScript Framework
│
◆  請輸入項目名稱:
│  demo█
  • 選擇

Need to install the following packages:
create-vue@3.16.4
Ok to proceed? (y) y
┌  Vue.js - The Progressive JavaScript Framework
│
◇  請輸入項目名稱:
│  demo
│
◆  請選擇要包含的功能: (↑/↓ 切換,空格選擇,a 全選,回車確認)
│  ? TypeScript
│  ? JSX 支持
│  ? Router(單頁面應用開發)
│  ? Pinia(狀態管理)
│  ? Vitest(單元測試)
│  ? 端到端測試
│  ? ESLint(錯誤預防)
│  ? Prettier(代碼格式化)
  • 目錄

node_modules/ 存放NPM下載的依賴包
package.json 項目依賴配置文件
index.html VUE項目的入口文件
vite.config.ts vue的構建、打包配置文件
env.d.ts TypeScri環境變量,全局類型聲明
public/ 靜態資源目錄
src/源碼目錄app.vue 應該主組件main.ts 應該入口文件,創建Vue實例與掛載assets/ 靜態資源文件components/通常存放復用組件目錄
main.css 全局樣式文件
base.css 基礎樣式文件

項目運行流程

1.main.ts里聲明一個VUE項目中的唯一一個實例

import './assets/main.css'import { createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app')

2.index.html 引用main.ts的實例,去掛載主組合app.vue

    <!DOCTYPE html>
    <html lang=""><head><meta charset="UTF-8"><link rel="icon" href="/favicon.ico"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Vite App</title></head><body><div id="app"></div><script type="module" src="/src/main.ts"></script></body>
    </html>

    3.app.vue 總父組件去掛載各種子組件

      <!DOCTYPE html>
      <html lang=""><head><meta charset="UTF-8"><link rel="icon" href="/favicon.ico"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Vite App</title></head><body><div id="app"></div><script type="module" src="/src/main.ts"></script></body>
      </html>

      VUE模板

      app.vue是主組件,以下相關功能演示都在這個組件中測試。

      一個完整Vue文件必須包含script與模板template,且忽略前后順序(前后位置不影響)

      <script setup lang="ts">//數據業務處理層
      </script><template>//數據呈現
      </template>

      數據綁定渲染示例

      <script setup lang="ts">const msg = 'Hello World'
      </script><template><h1>{{ msg }}</h1>
      </template>

      組合式API

      選項式API網上教程太多了不再說明,我這里只對ts下的組合式API進行示例。

      <script setup lang="ts">
      // setup 相關于 選項式中的default....那一套,setup 函數  ;lang="ts" 告訴編譯器,這個文件是ts文件//推薦使用ref()來定義響應式數據import {computed, onMounted, onUnmounted, ref, watch} from "vue";const msg=ref('這是一個消息');let msg2="這也是一個消息"//定義方法function changeMsg(){msg.value="這是修改后的消息";msg2="這也是修改后的消息";}//監聽msg數據watch(msg, (newVal) => {alert(newVal);})watch(() => msg2, (newVal) => {alert(newVal);})// 計算屬性const Isok = computed(() => {return msg.value === "這是一個消息" ? "這是一個消息" : "";});// 生命組件周期..........onMounted(() => {alert("組件已掛載");});onUnmounted(() => {alert("組件已卸載");});</script><template><div><h1>{{msg}}</h1><h1>{{msg2}}</h1><button @click="changeMsg">修改消息</button></div>
      </template>
      


      VUE的基本操作

      • 渲染?

      ? ? ? ? 條件渲染

      ????????

      <script setup lang="ts">const code='A';const isShow=true;
      </script><template><div ><!-- 條件渲染:if ---><h1 v-if="code  === 'A'">A</h1><h1 v-else-if="code  === 'B'">B</h1><h1 v-else>C</h1><!-- 條件渲染顯示控制 ---><h1 v-show="isShow">isShow</h1></div></template>

      ? ? ? ? 列表渲染

      ? 可以將List和對象渲染出來,原理是:For循環方式處理

      <script setup lang="ts">const list  = [{id: 1,name: 'Todo 1',completed: false},{id: 2,name: 'Todo 2',completed: true},{id: 3,name: 'Todo 3',completed: false}];const obj={name:'test',age:18,sex:'男',height:1.8};
      </script><template><div ><li v-for="(item,index) in list" :key="item.id">{{index}} - {{ item.name }}</li><li v-for="(item,index) in obj" :key="index">{{ item }}</li></div></template>
      • 事件

      ? ? ? ? 無參
      <script setup lang="ts">const showMessageWithParam = (message: string) => {alert(message);
      };</script><template><div ><button  @click="showMessageWithParam('TEST!')">點擊我</button></div></template>
      ? ? ? ? 有參? ?
      <script setup lang="ts">
      const msg="";
      const showMessageWithParam = (message: string) => {alert(message);
      };
      </script>
      <template><div ><input v-model="msg" placeholder="請輸入內容" /><button @click="showMessageWithParam(msg)">傳遞輸入內容</button></div>
      </template>
      ? ? ? ? Event處理? ??
      <script setup lang="ts">
      const list = ["1", "2", "3"];
      const showMessageWithParam = (e: Event, message: string) => {(e.target as HTMLButtonElement).innerHTML = "已點擊";alert(message);
      };
      </script>
      <template><div ><li v-for="item in list" :key="item" @click="showMessageWithParam($event,item)">{{ item }}</li></div>
      </template>
      ? ? ? ? 事件修飾

      對事件進行修飾以達到阻止事件或事件冒泡等問題

      <script setup lang="ts">
      const message = "hello world";
      const showMessageWithParam = (e: Event, message: string) => {(e.target as HTMLButtonElement).innerHTML = "已點擊";alert(message);
      };
      </script>
      <template><div ><a href="https://www.baidu.com" @click.prevent="showMessageWithParam($event,message)">測試一下</a></div>
      </template>
      • 屬性

      ? ? ? ? class

      在TS中定義一個變量去指向一個樣式類,再模板中用這個定義的變量去渲染就實現了屬性綁定;綁定方式以『:』+屬性="定義變量的名"形式實現,如下所示。

      <script setup lang="ts">
      const classObj = 'test';
      const demoid=11;
      const msg = 'Hello World!';
      </script><template><div :class="classObj" :id="demoid.toString()">    <h1>{{ msg }}</h1></div></template><style scoped>
      .test {color: red;font-size: 50px;
      }
      </style>

      以上可以把一組綁定直接封裝一個對象進行綁定

      <script setup lang="ts">
      const msg = 'Hello World!';
      const obj={class:'test',id:'abc'
      };
      </script><template><!-- 綁定對象 ---><div v-bind="obj"><h1>{{ msg }}</h1></div></template><style scoped>
      .test {color: red;font-size: 50px;
      }
      </style>

      以數組形式綁定

      <script setup lang="ts">
      const classObj = 'test';
      const demoid=11;
      const msg = 'Hello World!';
      const t1="test2";
      const t2="test3";
      </script><template><!--- 以對象形式綁定 --><div :class="classObj" :id="demoid.toString()"><h1>{{ msg }}</h1></div><!--- 以數組形式綁定 --><div :class="[t1,t2]"><h1>{{ msg }}</h1></div></template><style scoped>
      .test {color: red;font-size: 50px;
      }
      .test2{color: blue;
      }
      .test3{font-size: 30px;
      }
      </style>

      ? ? ? ? style

      以:style='類'進行綁定,也可以通過:style='[類1、類2]'以數組進行綁定

      <script setup lang="ts">
      const msg = 'Hello World!';
      const obj={color :'red',fontSize :'30px'
      };
      const ob2={backgroundColor :'yellow'
      };
      </script><template><!--- 以對象形式綁定 --><div :style="obj"><h1>{{ msg }}</h1></div><div :style="[obj,ob2]"><h1>{{ msg }}</h1></div>
      </template>
      • 數組

      方法

      解釋

      push()

      向數組中添加數據

      pop()

      刪除數組中的數據

      shift()

      刪除第一個

      unshift()

      向數組中添加數據并放在第一位

      splice()

      splice(開始刪除的位置, 數量(可選擇), 刪除的元素1(可選擇), ..., 刪除的元素N(可選擇))

      sort()

      排序(升)

      reverse()

      反轉數組

      concat()

      以替換數組形式添加數據

      filter()

      <script setup lang="ts">
      import { ref } from "vue";const newItem = ref("");
      const list = ref(["a", "b", "c"]); // 使用 ref 包裹 list 以保證響應性
      const addItem = () => {if (newItem.value.trim()) {list.value.push(newItem.value); // 向數組中添加數據newItem.value = "";}
      };
      const addItem2 = () => {if (newItem.value.trim()) {list.value = list.value.concat([newItem.value]);//以替換的方式添加到數組中newItem.value = "";}
      };
      </script><template><div><div><input v-model="newItem" placeholder="輸入新項" /><button @click="addItem">添加</button><button @click="addItem2">添加2</button></div><ul><li v-for="item in list" :key="item">{{ item }}</li></ul></div>
      </template>
      • 偵聽

      通過watch定義要監聽的對象實現更多實用的功能

      <script setup lang="ts">
      import { ref,watch } from 'vue';
      const msg = ref('Hello World!');
      function changeMsg() {msg.value = 'Hello TONGYI Lingma!';
      }watch(() => msg.value,(newVal, oldVal) => {alert(`msg 從 ${oldVal} 變為 ${newVal}`);}
      );</script><template><!--- 以對象形式綁定 --><div ><h1>{{ msg }}</h1>  <button @click="changeMsg">change</button></div></template>
      • 計算屬性

      為了解決復雜的計算,讓代碼具備一定的可維護性

      <script setup lang="ts">
      import { computed, ref } from "vue";const newItem = ref("");
      //  計算屬性
      const Isok = computed(() => {return newItem.value === "ok" ? "ok" : "";
      });</script><template><div><div><input v-model="newItem" placeholder="輸入新項" /><!---  計算屬性 ---><p v-text="Isok"></p></div></div>
      </template>
      • 表單

      表單:v-mode="數據"可以對數據進行雙向綁定

      <script setup lang="ts">
      import { ref } from 'vue';
      const msg = ref('Hello World!');
      function changeMsg() {msg.value = 'Hello TONGYI Lingma!';
      }
      </script><template><!--- 以對象形式綁定 --><div ><h1>{{ msg }}</h1></div><div><form><input type="text" v-model="msg"></input></form></div>
      </template>
      • DOM操作

      盡管不提倡直接操作DOM,也有時我們需要對DOM進行操作;通過refs的方式就能實現;

      <script setup lang="ts">
      import { ref, onMounted } from 'vue';
      const msg = ref('Hello World!');
      const testRef = ref<HTMLElement | null>(null);const sendMessage = () => {if (testRef.value) {testRef.value.innerHTML = '修改了!';}
      };
      </script><template><div ref="testRef"><h1>{{ msg }}</h1><button @click="sendMessage">操作</button></div>
      </template>

      組件

      • 生命周期

      組件類似于當年我在做CS程序的時候,窗口有創建事件、顯示事件、關閉事件等,在相應的事件里寫相應的代碼;VUE也是同理,生命周期如下圖所示。根據這些生命周期去處理相應周期的代碼去實現相應的邏輯功能。

      <script setup lang="ts" xmlns="http://www.w3.org/1999/html">
      import {ref, onMounted, onUpdated, onUnmounted, onBeforeMount, onBeforeUnmount, onBeforeUpdate} from 'vue';const msg = ref('199991111');
      //組件創建前
      onBeforeMount(() => {console.log('組件創建前');
      })
      // 組件創建后示例
      onMounted(() => {console.log('組件創建后示例');
      })
      //組件掛載前
      onBeforeMount(() => {console.log('組件掛載前');
      })
      //組件掛載后
      onMounted(() => {console.log('組件掛載后');
      })
      //組件更新前
      onUpdated(() => {console.log('組件更新前');
      })
      //組件更新后
      onBeforeUpdate(() => {console.log('組件更新后');
      })
      //組件卸載前
      onBeforeUnmount(() => {console.log('組件卸載前');
      })
      //組件卸載后
      onUnmounted(() => {console.log('組件卸載后');
      })</script>
      <template></template>
      • 構成部分

      ????????前面講過VUE 本質上就是在一個HTML不斷的組拆,而APP.VUE文件是一個入口文件,所以每一個vue文件視作一個組件。

      ????????組件包含必要的<template>負責數據呈現 、<script> 業務邏輯處理(如無邏輯與數據可以不包含)、樣式<style>部分(如無樣式或默認總樣式可以不包含。

      <script setup lang="ts"></script><template></template><style scoped></style>
      • 引用

      定義的組件:test.vue

      <script setup lang="ts">const msg='測試一下';
      </script>
      <template><div><h1>{{msg}}</h1></div>
      </template>

      調用組件:app.vue

      <script setup lang="ts">import Test from '@/com/test.vue'
      </script><template><Test/>
      </template>
      • 嵌套

      下面是一個關系圖:

      人(app.vue)-頭(head.vue)-中部(mind.vue)-左手(leftHand.vue)-胸(chest.vue)-右手(rightHand.vue)-下部(boot.vue)-左腿(leftLeg)-右腿(rightLeg)

      接下來我將用代碼進行實現

      head.vue:頭部代碼

      <template><div><h1>------頭部-------</h1></div>
      </template>

      leftHand.vue:左手

      <template><div><h1>左手</h1></div>
      </template>

      chest.vue:胸

      <template><div><h1>這是胸部</h1></div>
      </template>

      rightHand.vue:右手

      <template><div><h1>右手</h1></div>
      </template>

      mind.vue:中部

      <script setup lang="ts">
      import LeftHand from "@/com/leftHand.vue";
      import Chest from "@/com/chest.vue";
      import RightHand from "@/com/rightHand.vue";
      </script><template><div><h1>-----中部-------</h1><LeftHand /><Chest /><RightHand /></div>
      </template>

      leftLeg.vue:左腿

      <template><div><h1>左腿</h1></div>
      </template>

      rightLeg.vue:右腿

      <template><div><h1>右腿</h1></div>
      </template>

      boot.vue:下部

      <script setup lang="ts">
      import LeftLeg from "@/com/leftLeg.vue";
      import RightLeg from "@/com/rightLeg.vue";
      </script>
      <template><h1>---下部------</h1><LeftLeg /><RightLeg />
      </template>

      app.vue:整體

      <script setup lang="ts">import Head from "@/com/head.vue";import Mind from "@/com/mind.vue";import Boot from "@/com/boot.vue";
      </script><template><div><Head/><Mind/><Boot/></div></template>
      • 全局注冊

      ????????以上是做了個示例,如果你想不引用,實現處理調用那就要配置相應組為全局組件,那需要在main.ts里聲明組件。以下是把test.vue注冊為全局,然后用app.vue直接調用。

      ? ? ? ? ps:非必要不提供注冊全局組件

      main.ts

      import './assets/main.css'import { createApp } from 'vue'
      import App from './App.vue'
      import Test from "@/com/test.vue";createApp(App).mount('#app')

      app.vue

      <script setup lang="ts">import Head from "@/com/head.vue";import Mind from "@/com/mind.vue";import Boot from "@/com/boot.vue";import Test from "@/com/test.vue";
      </script><template><div><test/><Head/><Mind/><Boot/></div></template>
      • 傳值

      父傳子
      方案1:props 逐級傳值

      在父組件上調用子組件以:傳遞名="數據"的形式進行傳值;在子組件上的props上用傳遞名接收,且接收到的數據無法被修改。

      父組件

      <script setup lang="ts">
      import LeftLeg from "@/com/leftLeg.vue";
      import RightLeg from "@/com/rightLeg.vue";
      import {ref} from "vue";// 自定義事件函數
      const handleCustomEvent = (data :any) => {msgFormLeft.value  = data;
      };
      const msgFormLeft=ref('空');
      const test2="test2";
      const test3={name : "test3",age : 18,
      }
      </script><template><!--- 只用test傳數據 test2傳綁定數據  test3傳對象---><LeftLeg test="msg" :test2="test2" :test3="test3"/><a>{{msgFormLeft}}</a><RightLeg />
      </template>

      子組件

      <script setup lang="ts">
      import { defineEmits, ref, watch } from 'vue';// 定義 props 接收父組件傳遞的 PMSG 參數
      const props = defineProps({test: {type: String,required: true},test2: {type: String},test3: {type: Object,default: () => ({ name: '', age: 0 })}
      });// 將 PMSG 參數賦值給 msg
      const msg = ref(props.test);</script>
      <template><div><h1>左腿</h1><a>{{ msg }}</a><a>{{ test2 }}</a><a>{{ test3.name }}</a><a>{{ test3.age }}</a></div>
      </template> 
      方案2:依賴注入

      上面的方案雖然可以解決父傳子,但很多項目是組件間層層嵌套。想像一下如果通過上述方式傳值不僅代碼量變大,而且可維護性也差。那么通過依賴注入的方式就可以實現父組件直傳到基于父組件下的任何一個組件中。

      首先provide在父組件中定義,子組件中用inject接收就可以了。

      app.vue

      <script setup lang="ts">import Boot from "@/com/boot.vue";import {provide} from "vue";
      const myValue = "Hello from provide/inject";
      const obj={name: 'John',age: 30
      };
      provide('myKey', myValue);
      provide('myObj', obj);
      </script><template><div><Boot/></div></template>

      子子組件rightLeg.vue

      <script setup lang="ts">
      import {inject} from "vue";
      const msg = inject<string>("myKey");
      const obj = inject<{ name: string, age: number}>("myObj");
      </script>
      <template><div><h1>右腿</h1><hr><h1> {{ inject<string>("myKey") }} </h1><hr><h1>{{ msg }}</h1><hr><h1>{{ obj?.name }}</h1><hr><h1>{{ obj?.age }}</h1></div>
      </template>

      子傳父
      ? ? ? ? 方案1:自定義事件傳遞
      1. 子組件里定義一個方法

      2. 在子組排方法里以emit('標識')的方式命名一個標識

      3. 父組件里在調用子組件那里用@標識名綁定個這標識并在后面對應父組件對應的事件

      ? ? ? ? 無參

      ? ? ? ? 子組件

      ????????

      <script setup lang="ts">import { defineEmits } from 'vue';const emit = defineEmits(['fTest']);const test = () => {emit('fTest');}
      </script>
      <template><div><h1>左腿</h1><button @click="test">回傳調用父組件</button></div>
      </template>

      ? ? ? ? 父組件

      <script setup lang="ts">
      import LeftLeg from "@/com/leftLeg.vue";
      import RightLeg from "@/com/rightLeg.vue";// 自定義事件函數
      const handleCustomEvent = () => {alert("來自子數據的調用")
      };
      </script><template><LeftLeg @fTest="handleCustomEvent"/><RightLeg />
      </template>

      ? ? ? ? 有參????????

      ????????子組件

      <script setup lang="ts">import { defineEmits } from 'vue';const emit = defineEmits(['fTest']);const test = () => {emit('fTest',  '左腿');}
      </script>
      <template><div><h1>左腿</h1><button @click="test">回傳調用父組件</button></div>
      </template>

      ? ? ? ? 父組件

      ????????

      <script setup lang="ts">
      import LeftLeg from "@/com/leftLeg.vue";
      import RightLeg from "@/com/rightLeg.vue";// 自定義事件函數
      const handleCustomEvent = (data :any) => {alert(data)
      };
      </script><template><LeftLeg @fTest="handleCustomEvent"/><RightLeg />
      </template>

      ? ? ? ? 時時傳

      ????????子組件

      <script setup lang="ts">
      import { defineEmits, ref, watch } from 'vue';const emit = defineEmits(['fTest']);
      const msg = ref('');const test = () => {emit('fTest', msg.value);
      };watch(msg, (newVal) => {// 當msg值發生變化時執行test方法test();
      });
      </script>
      <template><div><h1>左腿</h1><input type="text" v-model="msg" @change="test"></div>
      </template>

      ? ? ? ? 父組件

      <script setup lang="ts">
      import LeftLeg from "@/com/leftLeg.vue";
      import RightLeg from "@/com/rightLeg.vue";
      import {ref} from "vue";// 自定義事件函數
      const handleCustomEvent = (data :any) => {msgFormLeft.value  = data;
      };
      const msgFormLeft=ref('空');
      </script><template><LeftLeg @fTest="handleCustomEvent"/><a>{{msgFormLeft}}</a><RightLeg />
      </template>
      ? ? ? ? 方案2:利用props傳事件實現

      父組件

      <script setup lang="ts">
      import LeftLeg from "@/com/leftLeg.vue";
      import RightLeg from "@/com/rightLeg.vue";
      import {ref} from "vue";
      // 自定義事件函數
      const handleCustomEvent = (data :any) => {msgFormLeft.value  = data;
      };
      const msgFormLeft=ref('空');
      </script><template><!--- 只用test傳數據 test2傳綁定數據  test3傳對象---><LeftLeg test="msg" :handleCustomEvent="handleCustomEvent"/><a>{{msgFormLeft}}</a><RightLeg />
      </template>

      子組件

      <script setup lang="ts">
      import { ref, watch } from 'vue';
      const props = defineProps({handleCustomEvent: {type: Function,required: true}
      });
      const msg = ref('');watch(() => msg.value, (newValue, oldValue) => {props.handleCustomEvent(newValue)
      });
      // 如果需要在子組件中直接調用父組件函數,可以通過以下方式:
      // 例如:props.handleCustomEvent('aaaaaaaaa');
      </script>
      <template><div><h1>左腿</h1><input type="text" v-model="msg"></div>
      </template>
      • 插槽

      以<slot>為標簽顯示,把帶有引用的子組件內容塊顯示

      直接插

      父組件

      <script setup lang="ts">
      import LeftLeg from "@/com/leftLeg.vue";
      import RightLeg from "@/com/rightLeg.vue";
      import { ref } from "vue";const msgFormLeft = ref('空1111111');</script><template><LeftLeg><!-- 插槽A用于傳遞父組件的固定內容 --><div><h2>這是傳過來的內容</h2></div></LeftLeg><RightLeg />
      </template>

      子組件

      <script setup lang="ts" xmlns="http://www.w3.org/1999/html">
      import { ref, watch } from 'vue';const msg = ref('');</script>
      <template><div><h1>左腿</h1><slot ></slot><hr/></div>
      </template>
      插進去帶數

      ?父組件

      <script setup lang="ts">
      import LeftLeg from "@/com/leftLeg.vue";
      import RightLeg from "@/com/rightLeg.vue";
      import { ref } from "vue";const msgFormLeft = ref('空1111111');</script><template><LeftLeg><!-- 插槽A用于傳遞父組件的固定內容 --><div><a>{{ msgFormLeft }}</a></div></LeftLeg><RightLeg />
      </template>

      子組件

      <script setup lang="ts" xmlns="http://www.w3.org/1999/html">
      import { ref, watch } from 'vue';const msg = ref('');</script>
      <template><div><h1>左腿</h1><slot ></slot><hr/></div>
      </template>

      一次插入多個,分別顯示

      ?父組件

      <script setup lang="ts">
      import LeftLeg from "@/com/leftLeg.vue";
      import RightLeg from "@/com/rightLeg.vue";
      import { ref } from "vue";const msgFormLeft = ref('空1111111');</script><template><LeftLeg><!-- 插槽A用于傳遞父組件的固定內容 --><template #A><div><h2>這是傳過來的內容</h2></div></template><!-- 插槽B用于傳遞父組件的數據內容 --><template #B><div><a>{{ msgFormLeft }}</a></div></template></LeftLeg><RightLeg />
      </template>

      子組件

      <script setup lang="ts" xmlns="http://www.w3.org/1999/html">
      import { ref, watch } from 'vue';const msg = ref('');</script>
      <template><div><h1>左腿</h1><slot name="A"></slot><hr/><slot name="B"></slot><hr/></div>
      </template>

      插進去的數據混合父數據與子數據

      子組件

      <script setup lang="ts" xmlns="http://www.w3.org/1999/html">
      import { ref, watch } from 'vue';const msg = ref('199991111');</script>
      <template><div><h1>左腿</h1><slot name="A"></slot><hr/><slot name="B"></slot><hr/><slot name="C" :msg="msg"></slot><hr/></div>
      </template>

      ?父組件

      <script setup lang="ts">
      import LeftLeg from "@/com/leftLeg.vue";
      import RightLeg from "@/com/rightLeg.vue";
      import { ref } from "vue";const msgFormLeft = ref('空1111111');</script><template><LeftLeg><!-- 插槽A用于傳遞父組件的固定內容 --><template #A><div><h2>這是傳過來的內容</h2></div></template><!-- 插槽B用于傳遞父組件的數據內容 --><template #B><div><a>{{ msgFormLeft }}</a></div></template><!-- 插槽C用于接收來自子組件的消息 --><template #C="{ msg }"><div><p>來自子組件的消息: {{ msg || '暫無消息' }}</p></div></template></LeftLeg><RightLeg />
      </template>
      • 動態組件

      我們大多數情況下不可能把所有組件都呈現在父組件中,而是希望動態實現它。

      這時我們只需要通過<component :is="組件名或者動態數據中的組件名">就能實現;

      基本動態組件
      <script setup lang="ts">
      import { ref } from "vue";
      import LeftLeg from "@/com/leftLeg.vue";
      import RightLeg from "@/com/rightLeg.vue";// 定義當前激活的組件名稱,類型為組件對象的鍵,初始值為 "LeftLeg"
      const tabComponent = ref<keyof typeof components>("LeftLeg");// 組件對象,包含 LeftLeg 和 RightLeg 兩個組件,并通過 as const 確保其鍵值不可變
      const components = {LeftLeg,RightLeg
      } as const;// 切換組件函數,接收當前組件名稱作為參數,切換為另一個組件
      const switchComponent = (componentName: "LeftLeg" | "RightLeg") => {// 如果當前是 LeftLeg,則切換為 RightLeg,反之亦然tabComponent.value = componentName === "LeftLeg" ? "RightLeg" : "LeftLeg";
      };</script><template><!-- 使用動態組件并確保正確綁定 --><component :is="components[tabComponent]" /><button @click="switchComponent(tabComponent)">切換</button></template>
      動態組件駐留

      以上組件每次加載都會完成一次初始化會讓對應頁面的數據還原,此時在外部增加keep-alive組件包含一下就可以了

      父組件

      父組件

      <script setup lang="ts">
      import { ref } from "vue";
      import LeftLeg from "@/com/leftLeg.vue";
      import RightLeg from "@/com/rightLeg.vue";// 定義當前激活的組件名稱,類型為組件對象的鍵,初始值為 "LeftLeg"
      const tabComponent = ref<keyof typeof components>("LeftLeg");// 組件對象,包含 LeftLeg 和 RightLeg 兩個組件,并通過 as const 確保其鍵值不可變
      const components = {LeftLeg,RightLeg
      } as const;// 切換組件函數,接收當前組件名稱作為參數,切換為另一個組件
      const switchComponent = (componentName: "LeftLeg" | "RightLeg") => {// 如果當前是 LeftLeg,則切換為 RightLeg,反之亦然tabComponent.value = componentName === "LeftLeg" ? "RightLeg" : "LeftLeg";
      };</script><template><!-- 使用動態組件并確保正確綁定 --><keep-alive><component :is="components[tabComponent]" /></keep-alive><button @click="switchComponent(tabComponent)">切換</button></template>

      子組件

      <script setup lang="ts">
      import { ref } from "vue";const tttt = ref("左腿");function updateMsg(newMsg: string) {tttt.value = newMsg;
      }
      </script><template><h1>{{ tttt }}</h1><button @click="updateMsg('1111111')">更新</button>
      </template>
      動態組件懶加載

      動態組件時會一次性把組件所有組件進行渲染,而用到什么就渲染什么其實才科學。

      <script setup lang="ts">
      import {defineAsyncComponent, ref} from "vue";
      // 異步組件
      const LeftLeg = defineAsyncComponent(() => import("@/com/leftLeg.vue"));
      const RightLeg = defineAsyncComponent(() => import("@/com/rightLeg.vue"));// 定義當前激活的組件名稱,類型為組件對象的鍵,初始值為 "LeftLeg"
      const tabComponent = ref<keyof typeof components>("LeftLeg");// 組件對象,包含 LeftLeg 和 RightLeg 兩個組件,并通過 as const 確保其鍵值不可變
      const components = {LeftLeg,RightLeg
      } as const;// 切換組件函數,接收當前組件名稱作為參數,切換為另一個組件
      const switchComponent = (componentName: "LeftLeg" | "RightLeg") => {// 如果當前是 LeftLeg,則切換為 RightLeg,反之亦然tabComponent.value = componentName === "LeftLeg" ? "RightLeg" : "LeftLeg";
      };</script><template><!-- 使用動態組件并確保正確綁定 --><keep-alive><component :is="components[tabComponent]" /></keep-alive><button @click="switchComponent(tabComponent)">切換</button></template>

      指令

      所謂指令是指操作DOM元素的命令,VUE有內置的v-if、v-show就是指令;

      自定義指令

      • 以變量形式以對象方式出現,具有固定的生命周期

      • 變量名命名以駝峰方式進行命令。

      • 使用則駝峰以'-'拆分且全部小寫。

      示例

      <script setup lang="ts">
      import LeftHand from "@/com/leftHand.vue";
      import Chest from "@/com/chest.vue";
      import RightHand from "@/com/rightHand.vue";
      const vTest={create:()=>{console.log("創建")},mounted:()=>{console.log("掛載")},unmounted:()=>{console.log("卸載")},beforeUpdate:()=>{console.log("更新前")},updated:()=>{console.log("更新")},update:() => {console.log("更新")},beforeUnmount:()=>{console.log("卸載前")}
      }
      </script><template><div><!-- 測試 --><h1 v-test>-----中部-------</h1>
      <!--    <LeftHand />-->
      <!--    <Chest />-->
      <!--    <RightHand />--></div>
      </template>

      相應的周期函數都包含el對象,利用el對象可以實現具體的功能。

      <script setup lang="ts">
      import LeftHand from "@/com/leftHand.vue";
      import Chest from "@/com/chest.vue";
      import RightHand from "@/com/rightHand.vue";
      const vTest = {created() {console.log("創建");},mounted(element, binding, vnode) {element.innerHTML=element.innerHTML+"眾納原創";},unmounted() {console.log("卸載");},beforeUpdate() {console.log("更新前");},updated() {console.log("更新");},beforeUnmount() {console.log("卸載前");}
      };
      </script><template><div><!-- 測試 --><h1 v-test>-----中部-------</h1>
      <!--    <LeftHand />-->
      <!--    <Chest />-->
      <!--    <RightHand />--></div>
      </template>

      以上定義的指令都是局部指令,如果想整體項目都要用到需要到main.ts里進行定義

      import './assets/main.css'import { createApp } from 'vue'
      import App from './App.vue'
      const app = createApp(App)
      app.directive('focus', {mounted(element) {element.style.color='red';element.style.fontSize='90px';}
      })
      app.mount('#app')

      使用時則以v-"定義的名稱"進行綁定使用

      ```typescript
      import './assets/main.css'import { createApp } from 'vue'
      import App from './App.vue'
      const app = createApp(App)
      app.directive('focus', {mounted(element) {element.style.color='red';element.style.fontSize='90px';}
      })
      app.mount('#app')
      ```> 使用時則以v-"定義的名稱"進行綁定使用```html
      <script setup lang="ts">
      import LeftHand from "@/com/leftHand.vue";
      import Chest from "@/com/chest.vue";
      import RightHand from "@/com/rightHand.vue";
      const vTest = {created() {console.log("創建");},mounted(element, binding, vnode) {element.innerHTML=element.innerHTML+"眾納原創";},unmounted() {console.log("卸載");},beforeUpdate() {console.log("更新前");},updated() {console.log("更新");},beforeUnmount() {console.log("卸載前");}
      };
      </script><template><div><!-- 測試 --><h1 v-test v-focus>-----中部-------</h1>
      <!--    <LeftHand />-->
      <!--    <Chest />-->
      <!--    <RightHand />--></div>
      </template>
      ```
      

      本篇完成 ,下篇會涉及路由、狀態管理、Axios通信、Element UI等擴展知識,請關注博主,第一時間獲取高品質的技術文章。

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

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

      相關文章

      JavaScript性能優化實戰

      JavaScript性能優化實戰技術文章大綱 性能優化的重要性 解釋為什么性能優化對用戶體驗和業務指標至關重要討論核心Web指標&#xff08;LCP、FID、CLS&#xff09;與JavaScript性能的關系 代碼層面優化 減少DOM操作&#xff0c;使用文檔片段或虛擬DOM避免頻繁的重繪和回流&a…

      考研英語作文評分標準專業批改

      考研英語作文專業批改經過官方評分標準嚴格對標&#xff0c;徹底改變你的作文提升方式&#xff0c;打開 懂試帝小程序 直達批改。 &#x1f3af; 批改服務核心優勢 ? 官方標準嚴格對標 完全按照考研英語官方五檔評分制&#xff0c;從內容完整性、組織連貫性、語言多樣性到語…

      智能群躍小助手發布說明

      1.初次登陸需要授權碼 2.社群維護頁面 3.產品營銷頁面

      SAM2論文解讀-既實現了視頻的分割一切,又比圖像的分割一切SAM更快更好

      code&#xff1a;https://github.com/facebookresearch/sam2/tree/main demo:https://sam2.metademolab.com/ paper:https://ai.meta.com/research/publications/sam-2-segment-anything-in-images-and-videos/ 這是SAM 這是SAM2 Facebook出品&#xff0c;繼SAM在圖像上分割…

      WPF 的RenderTransform使圖標旋轉180°

      只是記錄一下思想&#xff1a; 本來想找兩個對稱的圖標給按鈕用&#xff0c;但是另一個找不到&#xff0c;就想到可不可以旋轉180實現另一個圖標的效果&#xff0c;問了一下DeepSeek&#xff1a; <Path Width"30" Height"30" Margin"1"Data…

      Matplotlib 繪圖庫使用技巧介紹

      目錄 前言 Matplotlib 簡介 快速入門 圖形結構解剖 常用繪圖函數 子圖與布局 單行多列子圖&#xff1a; 網格布局&#xff1a; 自定義位置&#xff1a; 樣式與標注 中文字體與科學計數 圖例、網格、坐標軸 動態圖與動畫 三維繪圖 常見問題與技巧 前言 Matplotli…

      【Java基礎算法】1.相向指針練習

      ??博客主頁:程序員葵安 ??感謝大家點贊????收藏?評論??? 一、兩數之和 Ⅱ(167) 1.1 題目介紹 給你一個下標從 1 開始的整數數組 numbers ,該數組已按 非遞減順序排列 ,請你從數組中找出滿足相加之和等于目標數 target 的兩個數。如果設這兩個數分別是 nu…

      “開放原子園區行”太原站:openKylin以開源之力,賦能產業發展

      在數字化與智能化浪潮驅動下&#xff0c;開源技術已成為全球科技創新與產業升級的核心引擎&#xff0c;并為培育新質生產力開辟關鍵路徑。為加速開源生態建設&#xff0c;賦能區域經濟高質量發展&#xff0c;由開放原子開源基金會、山西省工業和信息化廳、山西轉型綜合改革示范…

      【Elasticsearch】自定義相似性算法

      在 Elasticsearch 中&#xff0c;可以通過自定義相似度算法來優化搜索結果的相關性。以下是幾種常見的自定義相似度算法的方法&#xff1a; 1. 使用內置相似度算法 Elasticsearch 默認使用 BM25 算法&#xff0c;但也可以切換到其他內置的相似度算法&#xff0c;如 TF-IDF 或布…

      【對比】DeepAR 和 N-Beats

      1. DeepAR 1.1 核心思想 提出者&#xff1a;亞馬遜&#xff08;Amazon&#xff09;團隊于2018年提出。目標&#xff1a;針對多變量時間序列進行概率預測&#xff08;Probabilistic Forecasting&#xff09;&#xff0c;輸出預測值的分布&#xff08;如均值、方差、置信區間&a…

      Spring Boot單元測試終極指南:從環境搭建到分層測試實戰

      Spring Boot測試終極指南&#xff1a;從環境搭建到分層測試實戰 掌握MockMvc與分層測試策略&#xff0c;讓你的代碼質量提升一個維度 一、環境搭建&#xff1a;Maven依賴深度解析 Spring Boot測試的核心依賴在pom.xml中配置如下&#xff1a; <dependencies><!-- 核心…

      卷積類型總結

      1. 標準卷積 (Convolution) 原理&#xff1a; 一個包含 K 個濾波器的卷積層&#xff08;每個濾波器大小為 FxF x C_in&#xff09;在輸入特征圖上滑動。在每個位置&#xff0c;濾波器與輸入圖像的局部區域進行逐元素相乘再求和&#xff08;點積運算&#xff09;&#xff0c;得到…

      HP iLO使用實例:Integrated Lights-Out

      文章目錄 參考名詞解釋iLODMTF SMASH CLP命令HP提供的命令VSPBIOS啟動順序BIOS指令啟動時報的電源錯誤如果ilo登陸不上去參考 ilo命令 https://support.hpe.com/hpesc/public/docDisplay?docId=c03334058 名詞解釋 iLO 從字面理解:Integrated Lights-Out,就是整合燈出;…

      【前端隱蔽 Bug 深度剖析:SVG 組件復用中的 ID 沖突陷阱】

      前端隱蔽 Bug 深度剖析&#xff1a;SVG 組件復用中的 ID 沖突陷阱 創建時間: 2025/6/20 類型: &#x1f50d; Bug 深度分析 難度: ????? 高級 關鍵詞: SVG、ID 沖突、Vue 組件、隱蔽 Bug、技術分析 &#x1f4d6; 引言 在前端開發的世界里&#xff0c;有一類 Bug 特別令…

      IDEA 中 Tomcat 部署 Java Web 項目(Maven 多模塊 非 Maven 通用版)

      引言 Java Web 開發中&#xff0c;Tomcat 是最常用的 Servlet 容器&#xff0c;而項目類型通常分為 Maven 管理&#xff08;依賴自動處理、多模塊聚合&#xff09; 和 非 Maven 純手工管理&#xff08;手動引入 jar 包、配置項目結構&#xff09;。本文覆蓋 兩種項目類型 的 T…

      當建筑學會“行走”:MiC建筑如何重塑醫療空間

      當塔吊林立的工地被智能化工廠取代&#xff0c;當混凝土現澆的轟鳴被精密模塊的無聲拼接覆蓋&#xff0c;建筑行業正經歷著自鋼筋混凝土革命以來最深刻的范式轉移。模塊化集成建筑&#xff08;MiC&#xff09;技術&#xff0c;這場以“制造組裝”為核心的新型工業化浪潮&#x…

      計算機網絡八股第二期

      計算機網絡八股第二期 1.講一講從輸入網址到網頁顯示之間發生了什么&#xff08;從網絡的角度&#xff09; 想想一下你從網店買一本書&#xff0c;從輸入網址到網頁顯示其實和你從網店買一本書差不多&#xff0c;網店發給你的是實體而網絡傳輸的是文字&#xff0c;圖片等等資…

      FPGA基礎 -- Verilog 的值變轉儲文件(VCD:Value Change Dump)

      Verilog 的“值變轉儲文件&#xff08;VCD&#xff1a;Value Change Dump&#xff09;”&#xff0c;這是一項在仿真調試中至關重要的技術&#xff0c;可以幫助你“看見”RTL中每個信號隨時間的變化過程。 一、什么是 Verilog 的值變轉儲文件&#xff08;VCD&#xff09; VCD …

      流水燈芯片74HC138 → 74HC164 → 74HC595核心功能、引腳作用及芯片定位

      一、74HC138&#xff1a;精準的“8選1開關” 核心作用 用3根控制線&#xff08;A0-A2&#xff09;實現8路嚴格單選&#xff0c;同一時刻僅1路輸出低電平&#xff08;其他7路高電平&#xff09;。 &#x1f4cc; 本質&#xff1a;二進制地址譯碼器&#xff0c;不是數據寄存器。…

      鴻蒙Next倉頡語言開發實戰教程:懶加載

      今天要分享的是倉頡開發語言中的懶加載。 先和初學者朋友們解釋一下什么是懶加載。懶加載在代碼中叫做LazyForEach&#xff0c;看到名字你一定能猜到它和ForEach的功能類似。只不過和ForEach的一次性加載所有數據不同&#xff0c;懶加載會根據屏幕可使區域按需加載數據&#x…