马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
一、开辟环境搭建:基石奠定
- Node 环境安装:
- Vue 3 的开辟离不开 Node.js,它为项目提供了运行时环境与丰富的包管理能力。
- 开辟编辑工具:
- Visual Studio Code(Vscode)是当下热门且功能强大的前端开辟工具。
- 浏览器环境:
- 谷歌浏览器(Google Chrome)依附出色的调试功能与对前端技术的良好支持,成为 Vue 开辟的首选浏览器。
二、初窥 Vue 3:创建首个应用
- 通过 CDN 使用 Vue:
- 在 HTML 文件中引入 Vue 3 的 CDN 链接,如:
- <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
- <div id="app">{{ message }}</div>
- <script type="module">
- import { createApp, ref } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js'
- createApp({
- setup() {
- const message = ref('Hello Vue!')
- return {
- message
- }
- }
- }).mount('#app')
- </script>
复制代码
- 这里先引入 Vue 全局脚本,然后使用 createApp 函数创建 Vue 应用实例,在 setup 函数中定义相应式数据 message,末了通过 .mount('#app') 将应用挂载到指定 DOM 节点(即 id 为 app 的 div)上,页面便能展示出 Hello Vue!。
- 还可以创建交互组件,如:
- <div id="app">
- <button @click="count++">{{ count }}</button>
- </div>
- <script type="module">
- import { createApp, ref } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js'
- createApp({
- setup() {
- const count = ref(0)
- return {
- count
- }
- }
- }).mount('#app')
- </script>
复制代码
- 点击按钮,count 值会自动更新并在页面表现,展示了 Vue 的相应式特性。
- 通过 Vite 或者官方的命令行创建 Vue 3 项目:
- 使用 Vite:
- 首先确保已安装 Node.js,在终端实行 npm init vite@latest my-vue3-app -- --template vue(my-vue3-app 为项目名称,可自定义),这会创建一个基于 Vue 3 和 Vite 的初始项目布局。
- 进入项目目录 cd my-vue3-app,实行 npm install 安装依赖,然后 npm run dev 启动开辟服务器,即可在浏览器访问 http://localhost:3000 检察初始页面,后续可在此底子上进行组件开辟、路由配置等操纵。
- 使用官方命令行工具(需先全局安装 @vue/cli:npm install -g @vue/cli):
- 实行 vue create my-vue3-project(my-vue3-project 为自定义项目名),按提示选择 Vue 3 相关预设,如默认配置或手动选择功能插件(如路由、状态管理等),完成项目创建。同样进入项目目录后 npm run serve 启动开辟服务器,开启开辟流程。
三、核心知识剖析:语法与特性
- 模板语法:
- 文本插值:使用双大括号 {{}},如 <span>Message: {{ msg }}</span>,msg 为 Vue 实例中的相应式数据,能及时将数据渲染到页面。
- 插入 HTML:
- 插值语法插入 HTML 字符串时,会以文本情势表现,如 <p>插值语法插入html: {{ <span style="color: red">drogen</span> }}</p>,只会表现 HTML 代码文本。
- 若要正确渲染 HTML,需使用 v-html 指令,如 <p>v-html指令: <span v-html="rawHtml"></span></p>,此中 rawHtml 应为包罗合法 HTML 标签的字符串变量,要注意制止 XSS 攻击,审慎使用。
- Attribute 绑定:
- 使用 v-bind 指令,可简写为 :,如 <div v-bind:id="cxy"></div> 或 <div :id="cxy"></div>,cxy 为 Vue 实例中的数据,能动态绑定元素属性。常用于按钮禁用状态绑定 <button :disabled="isDisabled"> 按钮 </button>,或链接跳转地点绑定 <a :href="https://chenxuyuan.net"> drogen官网 </a>。
- 相应式原理:
- ref():通过 ref 函数创建相应式数据,如 const count = ref(0),在 JavaScript 中访问其值需使用 .value,即 count.value,但在模板中使用时无需加 .value,Vue 会自动处理惩罚。当 count.value 发生变化,使用该数据的 DOM 地区会自动更新。
- DOM 更新时机:Vue 采用异步更新策略,修改相应式状态时,DOM 不会立刻更新,而是在“next tick”更新周期中缓冲全部状态修改,确保每个组件只更新一次。若需等待 DOM 更新完成后实行额外代码,可使用 nextTick 全局 API,如:
- import { nextTick } from 'vue'
- async function increment() {
- count.value++
- await nextTick()
- // 现在 DOM 已经更新了
- }
复制代码
- reactive():用于创建相应式对象,如 const state = reactive({ count: 0 }),但它有一定局限性:
- 只能用于对象范例(对象、数组和如 Map、Set 这样的集合范例),不能持有如 string、number 或 boolean 这样的原始范例。
- 不能替换整个对象,否则相应性连接将丢失,如 state = reactive({ count: 1 }) 会导致原 state 的相应性失效。
- 对解构操纵不友好,解构后的数据与原相应式对象断开连接,如 const { count } = state,修改 count 不会影响原 state.count,若要保持相应性,需传入整个对象。
四、进阶特性:提拔开辟效能
- 盘算属性:
- <script setup>
- import { ref } from "vue";
- const list = ref({
- books: [
- "语文",
- "数学",
- "英语",
- ],
- });
- </script>
- <template>
- <p>是否拥有书籍:</p>
- <span>{{ list.books.length > 0? "Yes" : "No" }}</span>
- </template>
复制代码
- 但这样会使模板逻辑复杂,不易维护。
- 有盘算属性:使用 computed 函数创建盘算属性,如:
- <script setup>
- import { ref, computed } from "vue";
- const list = ref({
- books: [
- "语文",
- "数学",
- "英语",
- ],
- });
- // 一个计算属性 ref
- const booksLength = computed(() => {
- return list.value.books.length > 0? "Yes" : "No";
- });
- </script>
- <template>
- <p>拥有书籍的个数:</p>
- <span>{{ booksLength }}</span>
- </template>
复制代码
- 盘算属性会基于其依赖的数据自动缓存结果,当依赖数据稳固时,不会重复盘算,提拔性能,且在模板中使用如同平凡数据,简洁清楚。
- 可写盘算属性:
- <script setup>
- import { ref, computed } from "vue";
- const firstName = ref("老");
- const lastName = ref("王");
- const fullName = computed({
- // getter
- get() {
- return firstName.value + " " + lastName.value;
- },
- // setter
- set(newValue) {
- // 注意:我们这里使用的是解构赋值语法
- [firstName.value, lastName.value] = newValue.split(" ");
- },
- });
- // fullName.value = "范 冰冰";
- </script>
- <template>
- <p>Has published books:</p>
- <span>{{ fullName }}</span>
- </template>
复制代码
- 通过定义 get 和 set 方法,既能像平凡属性读取,又能在赋值时实行自定义逻辑,实现数据双向关联。
- 类与样式绑定:
- 类绑定:
- 绑定 HTML class:使用 :class 指令,可绑定对象或盘算属性,如:
- <script setup>
- import { ref, computed } from "vue";
- const isActive = ref(true);
- const isTitle = ref(true);
- const computedClass = computed(() => ({ active: isActive, title: isTitle }));
- </script>
- <template>
- <div :class="computedClass">drogen</div>
- </template>
复制代码
- <script setup>
- import { ref } from "vue";
- const active = ref("active");
- const title = ref("title");
- const isActive = ref(true);
- </script>
- <template>
- <div :class="[isActive? active : '', title]">drogen</div>
- </template>
复制代码
- 绑定内联样式:使用 :style 指令,可绑定对象,对象属性为 CSS 样式名与对应值,如:
- <script setup>
- import { ref } from "vue";
- const color = ref("red");
- const fontSize = ref(40);
- const styleObject = ref({
- color: "red",
- fontSize: "40px",
- });
- </script>
- <template>
- <div :style="styleObject">drogen</div>
- </template>
复制代码
- 条件渲染与列表渲染:
- 条件渲染:
- v-if+v-else:根据条件决定元素是否渲染,如:
- <script setup>
- import { ref } from "vue";
- const title = ref(true);
- </script>
- <template>
- <h1 v-if="title">drogen</h1>
- <h2 v-else>chenxuyuan.net</h2>
- </template>
复制代码
- <script setup>
- import { ref } from "vue";
- const type = ref(1);
- </script>
- <template>
- <h1 v-if="type === 1">drogen</h1>
- <h2 v-else-if="type === 2">html</h2>
- <h2 v-else-if="type === 3">css</h2>
- <h2 v-else-if="type === 4">js</h2>
- <h2 v-else>chenxuyuan.net</h2>
- </template>
复制代码- - `v-show`:元素始终渲染,通过 `display` 属性控制显示隐藏,如:
复制代码- <script setup>
- import { ref } from "vue";
- const title = ref(true);
- </script>
- <template>
- <h1 v-show="title">drogen</h1>
- </template>
复制代码
- <script setup>
- import { ref } from "vue";
- const courseList = ref(["html", "css", "js"]);
- </script>
- <template>
- <ul>
- <li v-for="item in courseList">{{ item }}</li>
- </ul>
- </template>
复制代码
- 也可使用 of 关键字,如 <li v-for="item of courseList">{{ item }}</li>,结果类似。
- 嵌套遍历:
- <script setup>
- import { ref } from "vue";
- const courseList = ref([
- { name: "html", list: ["h1", "h2", "h3"] },
- { name: "css", list: ["color", "fontSize", "display"] },
- { name: "js", list: ["var", "const", "let"] },
- ]);
- </script>
- <template>
- <ul>
- <li v-for="item in courseList">
- {{ item.name }}
- <div v-for="childItem in item.list">{{ childItem }}</div>
- </li>
- </ul>
- </template>
复制代码
- 注意:不保举 v-if 和 v-for 同时用在同一标签,因为 v-if 优先级高于 v-for,会导致 v-if 条件无法访问 v-for 作用域内变量别名,如:
- <script setup>
- import { ref } from "vue";
- const courseObject = ref({ front: "js", back: "java" });
- </script>
- <template>
- <ul>
- <li v-for="(value, key, index) in courseObject" v-if="!value">
- {{ value }} - {{ key }} -{{ index }}
- </li>
- </ul>
- </template>
复制代码
- 事件处理惩罚与表单输入绑定:
- 事件处理惩罚:
- 监听事件:使用 v-on:click 或简写 @click,如:
- <script setup>
- import { ref } from "vue";
- const count = ref(0);
- const addClick = () => {
- count.value++;
- };
- </script>
- <template>
- <div @click="addClick()">计数器:{{ count }}</div>
- </template>
复制代码
- 事件修饰符:如 .stop 阻止冒泡、.prevent 阻止默认活动、.self 仅当事件目标是自身时触发、.capture 使用捕获模式、.once 只触发一次、.passive 提拔移动端滚动性能;按键修饰符如 .enter、.tab 等用于特定按键监听,体系按键修饰符 .ctrl、.alt 等可组合使用。
- 表单输入绑定:
- 未使用 Vue 时,需手动处理惩罚双向数据绑定,如:
- <input
- :value="text"
- @input="event => text = event.target.value"
- >
复制代码
- <p>Message is: {{ message }}</p>
- <input v-model="message" placeholder="edit me" />
复制代码- <input type="checkbox" id="checkbox" v-model="checked" />
- <label for="checkbox">{{ checked }}</label>
复制代码- <div>Picked: {{ picked }}</div>
- <input type="radio" id="one" value="One" v-model="picked" />
- <label for="one">One</label>
- <input type="radio" id="two" value="Two" v-model="picked" />
- <label for="two">Two</label>
复制代码- <div>Selected: {{ selected }}</div>
- <select v-model="selected">
- <option disabled value="">Please select one</option>
- <option>A</option>
- <option>B</option>
- <option>C</option>
- </select>
复制代码
- 侦听器:
- <script setup>
- import { ref, watch } from 'vue';
- const question = ref('');
- const answer = ref('答案');
- const loading = ref(false);
- // 可以直接侦听一个 ref
- watch(question, (newQuestion) => {
- if (newQuestion.includes('?')) {
- loading.value = true;
- answer.value = 'Thinking...';
- setTimeout(() => {
- answer.value = '是的';
- }, 1000);
- }
- });
- </script>
- <template>
- <p>
- 提问问题
- <input v-model="question" :disabled="loading" />
- </p>
- <p>{{ answer }}</p>
- </template>
复制代码
- 这里侦听 question 数据变化,当输入包罗 ? 时,更新 loading 和 answer 状态模拟异步获取答案过程。
- 侦听数据源范例:
- 可侦听 ref(包括盘算属性)、相应式对象、getter 函数、多个数据源构成的数组。注意不能直接侦听相应式对象的属性值,需通过 getter 函数,如:
- const obj = ref({ count: 0 });
- // 错误,因为 watch() 得到的参数是一个 number
- watch(obj.value, (count) => {
- console.log(`count is: ${count}`);
- });
- // 提供一个 getter 函数
- watch(
- () => obj.value.count,
- (count) => {
- console.log(`count is: ${count}`);
- }
- );
复制代码
- const obj = ref({ count: 0 });
- watch(obj.value, (newValue, oldValue) => {
- // 在嵌套的属性变更时触发
- // 注意:`newValue` 此处和 `oldValue` 是相等的
- // 因为它们是同一个对象!
- });
- obj.count++;
复制代码
- 侦听返反相应式对象的 getter 函数(开销大,慎用):
- watch(
- () => state.someObject,
- (newValue, oldValue) => {
- // 注意:`newValue` 此处和 `oldValue` 是相等的
- // *除非* state.someObject 被整个替换了
- },
- { deep: true }
- );
复制代码
- watch(
- source,
- (newValue, oldValue) => {
- // 立即执行,且当 `source` 改变时再次执行
- },
- { immediate: true }
- );
复制代码
- watch(
- source,
- (newValue, oldValue) => {
- // 当 `source` 变化时,仅触发一次
- },
- { once: true }
- );
复制代码
- watchEffect():会在副作用发生期间追踪依赖,自动追踪全部能访问到的相应式属性,代码简洁但相应性依赖关系有时不明确,如:
- import { ref } from 'vue';
- const count = ref(0);
- WatchEffect(() => {
- console.log(`当前 count 的值为 ${count.value}`);
- });
复制代码
- 模板引用:
- <script setup>
- import { ref, onMounted } from 'vue';
- // 声明一个 ref 来存放该元素的引用
- // 必须和模板里的 ref 同名
- const input = ref(null);
- onMounted(() => {
- input.value.focus();
- });
- </script>
- <template>
- <input ref="input" />
- </template>
复制代码
- 这里获取输入框元素引用,在组件挂载后使其获取焦点。
- 函数的模板引用:
- <input :ref="(el) => { /* 将 el 赋值给一个数据属性或 ref 变量 */ }">
复制代码
- <script setup>
- import { ref, onMounted } from 'vue';
- const list = ref([
- /*... */
- ]);
- const itemRefs = ref([]);
- onMounted(() => console.log(itemRefs.value));
- </script>
- <template>
- <ul>
- <li v-for="item in list" ref="itemRefs">
- {{ item }}
- </li>
- </ul>
- </template>
复制代码
- <script setup>
- import { ref, onMounted } from 'vue';
- import Child from './Child.vue';
- const child = ref(null);
- onMounted(() => {
- // child.value 是 <Child /> 组件的实例
- });
- </script>
- <template>
- <Child ref="child" />
- </template>
复制代码
五、生命周期:组件的生命轨迹
- 认识 Vue 3 当中的生命周期函数:
- <script setup>
- import { ref, onMounted } from 'vue';
-
- const data = ref('');
-
- // 挂载时机生命周期函数;
- onMounted(() => {
- setTimeout(() => {
- data.value = 'drogen';
- }, 100);
- });
- </script>
-
- <template>
- <div>接口 100ms 后请求数据:</div>
- <span>{{ data }}</span>
- </template>
复制代码
- 这里使用 onMounted 在组件挂载完成后,通过定时器模拟异步请求数据并更新 data 展示。
- onMounted:常用于实行定时器、绑定事件、订阅消息等操纵,此时组件已挂载到 DOM,可访问真实 DOM 元素。
- onUnMounted:组件卸载之后,用于扫除定时器、取消订阅消息等,防止内存走漏。
- 概览 Vue 3 的全部生命周期函数流程:
- 组件生命周期图示清楚展示各阶段,从初始化开始,历经挂载、更新、卸载等环节,各阶段有对应的生命周期函数被调用。
- 详解生命周期的初始化流程:组件加载前进行底子数据初始化等操纵,为后续挂载做准备。
- 详解生命周期的挂载流程:
- onBeforeMount:在组件即将挂载到 DOM 之前被调用,模板已编译完成但未渲染,可在此预处理惩罚数据。
- onMounted:组件挂载到 DOM 后立刻调用,常用于 DOM 操纵。
- 详解生命周期的更新 + 烧毁流程:
- onBeforeUpdate:组件数据更新前调用,可保存状态等。
- onUpdated:数据更新并重新渲染完成后调用,可查抄更新后的 DOM。
- onBeforeUnmount:组件即将卸载前调用,清算资源。
- onUnmounted:组件从 DOM 中卸载后调用,标记生命周期结束。
六、组件开辟:构建 Vue 应用基石
- Vue 3 单页面组件开辟底子 - 组件定义 + 使用:
- <script setup>
- import { ref } from 'vue';
- const count = ref(0);
- </script>
- <template>
- <button @click="count++">You clicked me {{ count }} times.</button>
- </template>
复制代码
- <script setup>
- import ButtonCounter from './ButtonCounter.vue';
- </script>
- <template>
- <h1>Here is a child component!</h1>
- <ButtonCounter />
- </template>
复制代码
- 在父组件中导入并使用子组件,可多次重用。
- 闭合写法:使用自定义标署名调用组件,如 <button-counter></button-counter>,需在父组件正确注册。
- 传递 props:
- <script setup>
- defineProps(['title']);
- </script>
- <template>
- <h4>{{ title }}</h4>
- </template>
- - 在子组件通过 `defineProps` 接收父组件传入属性,父组件使用时:
- <ChildComponent title="drogen" />
复制代码
- Vue 3 单页面组件开辟底子 - 监听事件:
- defineEmits(["childClick"]);
- @click="$emit('childClick')"
复制代码- - 父组件:
- ```html
- @childClick="()=>{}"
- ```
复制代码
- 传递参数:
- defineEmits(["childClick"]);
- @click="$emit('childClick','chenxuyuan.net')"
复制代码
- @childClick="(n)=>{console.log(n)}"
复制代码
- 还可在子组件通过 emit 函数触发:
- <script setup>
- import { ref } from 'vue';
- const emit = defineEmits(["childClick"]);
- onMounted(() => {
- emit("childClick", "声明式触发事件");
- });
- </script>
复制代码
- Vue 3 单页面组件开辟底子 - 插槽:
- <script setup>
- const cxy = ref(0);
- defineExpose({ cxy });
- </script>
复制代码
- <script setup>
- const childRef = ref('');
- <child-component ref='childRef' />
- <span>{{ childRef.cxy }}<span/>
- </script>
复制代码
- <template>
- <slot></slot>
- </template>
复制代码
- <child-component>
- drogen
- </<child-component>
复制代码
七、组件进阶:优化与拓展组件功能
- Vue 3 单页面组件开辟进阶 - 组件注册 + 定名:
- // main.js
- import { createApp } from 'vue';
- import App from './App.vue';
- import ChildComponent from './ChildComponent.vue';
- const app = createApp(App);
- app.component('ChildComponent', ChildComponent);
- app.mount('#app');
复制代码
- 全局注册虽方便,但存在题目:不必要的文件体积,未使用组件无法 tree - shaking;难维护,依赖关系不明确。
- 局部注册:在使用组件的父组件中通过 import 导入并在 components 选项注册,更利于大型项目维护。
- 组件名格式:保举大驼峰(ChildComponent)或连字符格式(child-component),遵照同一规范利于代码可读性与维护性。
- Vue 3 单页面组件开辟进阶 - props:
- <script setup>
- const props = defineProps(['cxy']);
- console.log(props.cxy);
- </script>
- <script setup>
- defineProps({
- cxy: String,
- name: String
- });
- </script>
复制代码
- 通过 defineProps 声明接收父组件传入属性,指定范例利于开辟时错误排查。
- props 名字格式:建议小驼峰定名,符合 JavaScript 变量定名风俗。
- 静态和动态:
- 静态:<ChildComponent title="drogen" />。
- 动态:<ChildComponent :title="cxy" />,通过 : 绑定动态数据。
- 单项数据流:
- const props = defineProps(['cxy']);
- // ❌ 警告!prop 是只读的!
- props.cxy = 'chenxuyuan.net';
复制代码
- const props = defineProps(['cxy']);
- // 计数器只是将 props.cxy 作为初始值
- // 像下面这样做就使 prop 和后续更新无关了
- const counter = ref(props.cxy);
复制代码- const props = defineProps(['cxy']);
- // 该 prop 变更时计算属性也会自动更新
- const newcxy = computed(() => props.cxy + '老王');
复制代码
- Vue 3 单页面组件开辟进阶 - defineModel:
- <script setup>
- const model = defineModel();
- </script>
- <template>
- <h2>子组件</h2>
- <input v-model="model" />
- </template>
复制代码
- <script setup>
- import ChildComponent from "./ChildComponent.vue";
- import { ref } from "vue";
- const cxy = ref("drogen");
- </script>
- <template>
- <h1>父组件</h1>
- <span>{{ cxy }}</span>
- <ChildComponent v-model="cxy"></ChildComponent>
- </script>
复制代码
- 还可多属性双向绑定:
- <ChildComponent v-model:cxy="cxy" v-model:aa="aa"></ChildComponent>
复制代码
- const cxy = defineModel("cxy");
- const aa = defineModel("aa");
- <input type="text" v-model="cxy" />
- <input type="text" v-model="aa" />
复制代码
- Vue 3 单页面组件开辟进阶 - 依赖注入:
- 依赖注入:用于跨组件层级传递数据,无需层层传递 props。
- provide + inject:
- 供给方组件:
- <script setup>
- import { provide } from 'vue';
- provide(/* 注入名 */ 'message', /* 值 */ 'hello!');
- </script>
复制代码 - 注入方组件:
- <script setup>
- import { inject } from 'vue';
- const message = inject('message');
- </script>
复制代码 - 和相应式数据共同:
- <script setup>
- import { provide, ref } from 'vue';
- const cxy = ref('drogen');
- function updatecxy() {
- cxy.value = 'chenxuyuan.net';
- }
- provide('cxy', {
- cxy,
- updatecxy
- });
- </script>
复制代码
- <script setup>
- import { inject } from 'vue';
- const { cxy, updatecxy } = inject('cxy');
- </script>
- <template>
- <button @click="updatecxy">{{ cxy }}</button>
- </template>
复制代码
- 注意:注入的数据默认只读,防止不测修改导致数据紊乱。
- Vue 3 单页面组件开辟进阶 - KeepAlive:
- 是内置组件,用于在多个组件间动态切换时缓存被移除的组件实例:
- <script setup>
- import ChildComponent1 from "./ChildComponent1.vue";
- import ChildComponent2 from "./ChildComponent2.vue";
- import { ref } from "vue";
- const cxy = ref(true);
- </script>
- <template>
- <h1>父组件</h1>
- <button @click="() => (cxy =!cxy)">切换组件</button>
- <KeepAlive><ChildComponent1 v-if="cxy" /></KeepAlive>
- <ChildComponent2 v-if="!cxy" />
- </template>
复制代码
- 如切换回缓存组件,其状态(如计数器值)保持稳固,提拔用户体验。
八、路由应用:构建单页面应用导航
- Vue 3 单页面实现规模化 Vue Router 底子 - 入门使用:
- 安装:实行 pnpm install vue-router@4 安装 Vue Router 4。
- 使用:
- import { createRouter, createWebHashHistory } from 'vue-router';
- import ChildComponent1 from './ChildComponent1.vue';
- import ChildComponent2 from './ChildComponent2.vue';
- const routes = [
- { path: '/one', component: ChildComponent1 },
- { path: '/two', component: ChildComponent2 },
- ];
- const router = createRouter({
- history: createWebHashHistory(),
- routes,
- });
- export default router;
复制代码- <script setup>
- import { ref } from 'vue';
- const cxy = ref(true);
- </script>
- <template>
- <h1>父组件</h1>
- <p>
- <!-- 通过传递 `to` 来指定链接 -->
- <router-link to="/one">去组件1</router-link> <br />
- <router-link to="/two">去组件2</router-link>
- </p>
- <div>
- <!-- 路由出口 -->
- <router-view></router-view>
- </div>
- </template>
复制代码
- 这里创建路由实例,定义路由路径与对应组件,在父组件通过 <router-link> 实现导航链接,<router-view> 展示当前路由匹配组件内容。
- Vue 3 单页面实现规模化 Vue Router 底子 - 嵌套路由 + 编程式导航:
- import { createRouter, createWebHashHistory } from 'vue-router';
- import ChildComponent1 from './ChildComponent1.vue';
- import ChildComponent2 from './ChildComponent2.vue';
- import ChildComponent3 from './ChildComponent3.vue';
- const routes = [
- {
- path: '/one',
- component: ChildComponent1,
- },
- {
- path: '/two',
- 'two',
- component: ChildComponent2,
- children: [
- {
- path: 'aa',
- component: ChildComponent3,
- },
- ],
- },
- ];
- const router = createRouter({
- history: createWebHashHistory(),
- routes,
- });
- export default router;
复制代码
- 上述代码定义了嵌套路由,当访问 /two/aa 时,会在 ChildComponent2 的 <router-view> 子路由出口中展示 ChildComponent3 组件,实现更复杂的页面布局与导航布局。
- 编程式导航:
- <script setup>
- import router from "./router.js";
- const routerChange = (n) => {
- router.push(n);
- };
- </script>
- <template>
- <h1>父组件</h1>
- <p>
- <button @click="routerChange('/one')">打开组件1</button> <br />
- <button @click="routerChange('/two')">打开组件2</button><br />
- <button @click="routerChange('/two/aa')">打开组件3</button>
- </p>
- <div>
- <router-view></router-view>
- </div>
- </template>
复制代码
- 通过 router.push 方法实现编程式导航,可在 JavaScript 代码中根据业务逻辑灵活切换路由,好比点击按钮时触发相应路由跳转。
- Vue 3 单页面实现规模化 Vue Router 底子 - 定名 + 重定向:
- import { createRouter, createWebHashHistory } from 'vue-router';
- import ChildComponent1 from './ChildComponent1.vue';
- import ChildComponent2 from './ChildComponent2.vue';
- import ChildComponent3 from './ChildComponent3.vue';
- const routes = [
- {
- path: '/',
- redirect: '/one',
- },
- {
- path: '/one',
- name: 'one',
- component: ChildComponent1,
- },
- {
- path: '/two',
- name: 'two',
- component: ChildComponent2,
- children: [
- {
- path: 'three',
- name: 'three',
- component: ChildComponent3,
- },
- ],
- },
- ];
- const router = createRouter({
- history: createWebHashHistory(),
- routes,
- });
- export default router;
复制代码
- 为路由定名方便后续编程式导航引用,如 router.push({ name: 'one' }) 。设置重定向可在用户访问根路径 "/" 时自动跳转到指定路由,优化用户初始访问体验。
- Vue 3 单页面实现规模化 Vue Router 底子 - 路由传参:
- <router-link
- :to="{ path: '/one', query: { cxy: 'drogen', state: 'chenxuyuan' } }"
- >打开组件1</router-link
- >
复制代码
- 通过 query 参数传递数据,在目标组件可通过 $route.query 获取,如 this.$route.query.cxy ,常用于携带一些非关键、临时性的搜索条件等信息,参数会表现在 URL 中。
- params:
- <router-link :to="{ name: 'one', params: { cxy: 'drogen' } }"
- >打开组件1</router-link
- >
- path: "/one/:cxy"
复制代码
- 先在路由定义中声明参数占位符 :cxy ,然后通过 params 传递,在目标组件通过 $route.params 获取,参数不会表现在 URL 中,适合传递一些敏感或对 URL 美观有要求的数据,如用户 ID 等。
- 编程式导航传参:
- const routerChange = (n, obj) => {
- router.push({ path: n, query: obj });
- };
复制代码
- 以编程方式跳转路由并传参,灵活实现业务逻辑中的数据传递需求。
- Vue 3 单页面实现规模化 Vue Router 进阶 - 汗青记载模式 + 导航守卫:
- 不同的汗青记载模式:
- 哈希模式:createWebHashHistory() ,此模式 URL 带有 # 符号,如 http://localhost:3000/#/one ,兼容性好,服务器无需特别配置,是保举的入门模式。
- html5 模式:createWebHistory() ,使用 HTML5 History API,URL 更简洁美观,如 http://localhost:3000/one ,但需要服务器共同进行 URL 重写,防止革新页面出现 404 错误。
- 导航守卫:
- router.beforeEach((to, from, next) => {
- if (to.meta.isAuth) {
- if (localStorage.getItem("token") === "1") {
- next();
- } else {
- alert("请先登录");
- }
- } else {
- next();
- }
- });
复制代码
- 在路由跳转前进行权限验证等操纵,to 是即将进入的目标路由,from 是当前脱离的路由,next 用于控制导航流程,决定是否继续跳转、重定向或停止导航,保障应用安全性与业务逻辑正确性。
- Vue 3 单页面实现规模化 Vue Router 进阶 - 路由懒加载:
- component: () => import("./ChildComponent1.vue"),
复制代码
- 采用路由懒加载技术,将组件的加载延迟到路由被访问时,而非一次性加载全部组件,优化初始加载性能,尤其在大型项目中有大量组件时,能明显减少初始包体积,加快页面初次加载速率,提拔用户体验。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |