以前写过html、css、js、jq,刚有vue的时候前端宝子告诉我有基础上手很快的,就一直没补,正好乘着这次看到招聘要求有就补补……
1、什么是vue
一个用于构建用户界面的渐进式 JavaScript 框架。
所谓"渐进式"就是:你可以只拿她最基础的数据绑定功能,也可以把他的路由、状态管理、组件库全部用上,完全按需叠加。
vue 应用的开发构建过程依赖于 Node.js ,但其最终产物运行在浏览器中。
Node.js 是 JavaScript 的运行时。
| 对比维度 | Java JVM | Node.js | Python |
|---|---|---|---|
| 核心运行时 | Java 虚拟机 | Node.js (V8引擎) | CPython 解释器 |
| 语言特性 | 强类型、静态、纯OOP | 弱类型、动态、基于原型 | 强类型、动态、多范式 |
| 编译方式 | 字节码 + JIT编译 | 直接JIT编译为机器码 | 字节码 + 解释执行 |
| 并发模型 | 多线程 (线程安全复杂) | 单线程事件循环 (异步编程难) | GIL限制多线程 (真并行难) |
| 性能特点 | CPU密集型 企业级应用 | I/O密集型 高并发网络应用 | I/O密集型 数据科学、脚本 |
| 学习曲线 | 入门难 • 概念繁多 • 配置复杂 • OOP严格 | 中期难 • 语法简单 • 异步门槛高 • 回调复杂 | 入门易 • 语法简洁 • 动态灵活 • 深入难 |
| 开发速度 | 较慢 编译等待、样板代码多 | 快速 即时运行、热重载 | 极快 解释执行、语法糖多 |
| 典型应用 | 大型企业系统 金融、安卓开发 | REST API、实时应用 微服务、全栈开发 | 数据科学/AI Web后端、自动化 |
| 包管理 | Maven/Gradle | npm/yarn | pip/conda |
| 调试难度 | 中等 IDE支持好,并发问题难 | 较难 异步栈复杂,内存泄漏难 | 容易 错误信息清晰,REPL方便 |
| 市场需求 | 稳定庞大 企业级、金融 | 快速增长 初创、全栈 | 爆发增长 AI、数据科学 |
| 适合人群 | 重视基础 追求稳定性 | 前端转全栈 喜欢快速迭代 | 初学者 数据/AI方向 |
Node.js 官网地址:nodejs.org/en
【确认是否安装】运行cmd打开命令终端,执行命令:node -v npm -v
【检验node.js执行js文件】创建 test.js ,运行 cmd 打开命令终端,执行命令:node test.js
//test.js
function sum(a,b){
return a+b;
}
function main(){
console.log(sum(1,2))
}
main()
【设置镜像】运行cmd打开命令终端,执行命令:npm config set registry 镜像地址
【验证镜像配置是否生效】运行cmd打开命令终端,执行命令:npm config get registry
2、创建vue3工程
使用 Vite 创建 Vue3 工程化项目
(Vite 是一个现代化的前端构建工具,是一个轻量级的 Vue 项目脚手架工具。)
创建文件夹指定目录之后,运行 npm create vite@latest 下载 Vite,输入 y , 输入项目名字 solicitous01,
选择 framework :Vue,选择 variant :JavaScript
查看或者调整项目依赖 solicitous01/package.js 文件,cd 定位到项目文件夹安装依赖,执行 npm i
修改端口号,打开 solicitous01/vite.config.js 文件,在plugins下面增加
,server:{
port:8080
}
执行run + package.js 文件scripts里面具体的key 运行项目,例如:run dev
停止运行:ctrl + c
如果用的VSCode,还可以安装插件 Vue - Official(关键字颜色高亮)、Vetur(关键字提示)
3.目录结构
node_modules:存放项目中的依赖。
public:用于存放一些公共资源,如:html 文件、图像、字体等。
src:存放项目的源代码。
assets:用于存放一些项目中用到的静态资源,如:图片、字体、样式文件等。
components:用于存放组件相关的文件。
……
main.js: js 入口,也可能是 main.ts。
index.html:项目入口文件。
package.js:标准的 Node.js 项目配置文件,包含了项目的基本信息和依赖关系。
vite.config.js:Vite 的配置i文件,可以通过该文件配置项目的参数、插件、打包优化等。
4.单文件组件的理解
【xxx.vue】
<script setup> // 这里有 setup 才可以用 @click 不然只能用 v-on:click
// 这里放以前 js 内容
</script>
<template>
// 这个里面放以前 html 内容,注意只能有一个控件
</template>
<style scoped>
// 这里放以前 css 样式
</style>
5、运行流程
a). 输入正确的地址,访问index.html入口文件
b). index.html文件中DOM元素挂载所有组件中的元素,模块化的方式引入了main.js文件,具体的挂载过程在main.js中执行
挂载:将Vue示例与一个页面上的DOM元素建立关联,使得Vue实力可以接管这个DOM元素及其内容,从而进行渲染和更新
c). main.js文件导入 xxx.css 全局样式,导入 xxx.vue 组件,createApp(xxx).mount('#yyy') 将 xxx.vue 组件通过挂载的形式,将 xxx.vue 组件钟的内容挂载到 index.html 文件中对应的 DOM 元素中
d). 运行 npm run dev
6、Vue3简单的例子
页面输出:hello vue3!
<script>
export default{
setup(){
let x = "hello vue3";
return{
x
}
}
}
</script>
<template>
<div>
<span v-text="x"></span>
</div>
</template>
<style>
// 这里放以前 css 样式
</style>
使用setup(读音:/ˈsetˌʌp/ 谐音:“塞特-阿普”)语法糖语法糖简化:
<script setup>
let x = "hello vue3";
</script>
<template>
<div>
<span v-text="x"></span>
</div>
</template>
<style scoped>
// 这里放以前 css 样式
</style>
【插一嘴】
额 "语法糖",听着有点耳熟,python的装饰器也叫语法糖……好吧他们虽然都叫语法糖,但是他们不是一个东西哟……java原来也有语法糖还很多……啊这……来拆解下这个名词吧……以便只能听懂人话的宝子也能理解……
语法糖的定义:用更甜、更优雅的语法,包裹原本可能复杂、苦涩的底层实现,让代码对开发者更友好。
如何判断他是不是语法糖嘞:
1、功能不变:没有增加新的底层能力。
2、语法更甜:书写更简单、更直观、更易读。
3、编译转换:在编译期或解释期会被转回原始的语法。
7、Vue3常用包
| 包名 | 像什么 | 核心用法 | 关键词 | 官方 / 第三方 |
|---|---|---|---|---|
| vue | 做美食的万能料理台 |
白话:显示动态内容、绑定数据; 术语:提供响应式系统、组件化核心、虚拟 DOM、模板编译 | 数据、模板、挂载、响应式 | Vue 官方 |
| vue-router | 餐厅里的菜品传菜轨道 |
白话:页面跳转、路由规则; 术语:URL 与组件映射、路由守卫、历史记录管理、动态路由 | 路由、跳转、页面、守卫 | Vue 官方 |
| pinia | 餐厅共享的调味台(所有厨师都能取 / 加调料) |
白话:多页面共享数据、修改数据; 术语:集中式状态管理、响应式状态、异步 Action、模块隔离 | 状态、共享、抽屉、Action | Vue 官方 |
| @vue/test-utils | 菜品上桌前的品控检测仪 |
白话:检查组件好不好用、会不会坏; 术语:Vue 组件测试工具,模拟挂载、触发事件、断言验证 | 测试工具、单元测试、断言 | Vue 官方 |
| @vue/server-renderer | 中央厨房的预制菜生产线(提前做好菜品再配送)(SSR) |
白话:先创建子组件,之后拼在父组件里面 术语:Vue 服务端渲染核心,将组件渲染为 HTML 字符串 | SSR(服务端渲染)、HTML | Vue 官方 |
| @vitejs/plugin-vue | 料理台的专用适配配件(让料理台兼容 Vue 食材) |
白话:让 Vite 能识别.vue 文件; 术语:Vite 的 Vue 插件,处理 SFC(单文件组件)编译、热更新 | 开发工具、Vite、SFC 编译 |
Vite 官方 (Vue 生态核心) |
| element-plus | 餐厅现成的精装预制菜(热炒 / 凉菜 / 汤品齐全)(PC 端) |
白话:快速做按钮 / 弹窗 / 表格; 术语:基于 Vue3 的 PC 端 UI 组件库,按需引入、自定义主题、无障碍 | UI、组件、样式、PC 端 |
第三方 (饿了么团队) |
| Vant | 便携的口袋速食包(适合手机端随手吃)(移动端) |
白话:手机端快速做按钮 / 列表 / 弹窗; 术语:基于 Vue3 的移动端 UI 组件库,轻量、适配多端、按需引入 | UI、移动端、轻量 |
第三方 (有赞团队) |
| Naive UI | 可 DIY 的创意轻食套餐(配料 / 口味自由搭)(PC 端) |
白话:PC 端高颜值组件,可自由改样式; 术语:Vue3 专属 PC 端 UI 库,TypeScript 友好、自定义程度高、暗黑模式 | UI、PC 端、自定义 |
第三方 (个人 / 社区) |
| Arco Design Vue | 企业食堂的标准化套餐(大厂风格、品类全)(PC 端) |
白话:大厂风格的 PC 端组件,适合后台系统; 术语:字节跳动出品,企业级 UI 库,支持主题定制、国际化 | UI、PC 端、企业级 |
第三方 (字节跳动) |
| NutUI | 京东便利店的特色速食(京东风格、适配小程序)(移动端) |
白话:京东风格的手机端组件,适配小程序; 术语:京东出品,基于 Vue3 的移动端 UI 库,适配多端(H5 / 小程序) | UI、移动端、京东风格 |
第三方 (京东) |
| Ant Design Vue | 阿里系餐厅的招牌套餐(阿里风格、中后台适配)(PC 端) |
白话:阿里风格的 PC 端组件,适合中后台系统; 术语:蚂蚁集团出品,Vue3 适配版,组件丰富、交互规范 | UI、PC 端、阿里风格 |
第三方 (蚂蚁集团) |
8、官方包的使用
【Vue】
模板指令关键字 → 组合式 API 关键字(Vue3 主流) → 选项式 API 关键字(Vue2 兼容) → Vue3 生命周期钩子 → Vue2 生命周期钩子
一、模板指令关键字
| 关键字 | 核心用法 | 极简示例 |
|---|---|---|
| {{ }} | 插值显示动态数据,关联响应式依赖收集,渲染纯文本 / 表达式,支持三元 / 函数调用等,可能出现插值闪烁 | {{ count }} {{ fn() }} {{ count > 0 ? '是' : '否' }} |
| v-bind / : | 绑定属性,支持动态值 / 对象 / 数组,简写 : 是主流 | <a :href="url"> <div :class="{ active: isShow }"> |
| v-on / @ | 绑定事件,支持简写 @、事件修饰符(.stop/.prevent 等)、自定义事件 | <button @click="handleClick"> <input @input="handleInput"> |
| v-model |
双向绑定,支持表单元素 / 自定义组件,语法糖(v-bind + v-on),Vue3 支持参数修饰符 | <input v-model="value"> <Child v-model:title="title"> |
| v-for | 循环渲染,必须绑定唯一 key,支持遍历数组 / 对象 / 数字 | <div v-for="item in list" :key="item.id">{{ item.name }}</div> |
| v-if / v-else-if / v-else | 条件渲染,惰性渲染(不满足则不创建 DOM),优先级高于 v-show | <div v-if="count > 0">显示</div><div v-else>隐藏</div> |
| v-show | 条件显示,CSS 隐藏(display:none),DOM 始终存在 | <div v-show="isShow">显示/隐藏</div> |
| v-text | 纯文本渲染,无插值闪烁,等价于 {{}},适合整行文本绑定,覆盖元素内所有内容 | <span v-text="text"></span> |
| v-html | 指令式渲染 HTML 内容(不转义),无插值闪烁,覆盖元素内所有内容(有 XSS 风险) | <div v-html="htmlStr"></div> |
| v-once | 仅渲染一次,后续数据变化不更新 | <div v-once>{{ count }}</div> |
| v-cloak | 解决 {{}} 插值闪烁,配合 CSS 隐藏未编译的模板,编译完成后移除指令 | <div v-cloak>{{ count }}</div> + [v-cloak] { display: none } |
| v-pre | 跳过当前元素及子元素的编译,直接显示原始模板(提升性能) | <div v-pre>{{ 1 + 1 }}</div>(显示 {{ 1 + 1 }}) |
例子
<script setup>
import {ref} from 'vue'
let x = "hello vue3";
let y = () => {
return 'hello vue3 , hi~';
}
let z = 3;
let w = "hello ";
let m = "<a href='https://cn.vuejs.org/'>vue</a>";
let n = [{a:"a",b:1},{a:"b",b:2}];
let url = 'https://cn.vuejs.org/';
let url_data = {
url:'https://cn.vuejs.org/'
}
function a(){
alert('hello vue3!');
}
let count = ref(0);
function a(){
count.value++;
console.log(count.value);
}
</script>
<template>
<div>
<span v-text="x"></span><br/>
<span v-text="y()"></span><br/>
<span v-text="z==3 ? 'hello vue3!' : 'bye vue!'"></span><br/>
<span v-text="w.length"></span><br/>
<span v-text="`${w}vue${z}!`"></span><br/>
<span v-text="m"></span><br/>
<hr>
{{x}}<br/>
{{y()}}<br/>
{{z==3 ? 'hello vue3!' : 'bye vue3!'}}<br/>
{{w.length}}<br/>
<br/>
{{m}}<br/>
{{n[0].a}}<br/>
<hr>
<span v-html="m"></span><br/>
<hr>
<a v-bind:href="url">vue</a><br/>
<a :href="url">vue</a><br/>
<a v-bind:href="url_data.url">vue</a><br/>
<a :href="url_data.url">vue</a><br/>
<hr>
<a v-on:click="a()">vue</a><br/>
<a @click="a()">vue</a><br/>
<hr>
<span v-if="z<=2">hello vue2</span><br/>
<span v-else-if="z<=3">hello vue3</span><br/>
<span v-else>bye vue</span><br/>
<!--只有满足的标签 -->
<hr>
<span v-show="z<=2">hello vue2</span><br/>
<span v-show="z<=3 && z>2">hello vue3</span><br/>
<span v-show="z>3">bye vue</span><br/>
<!--show是 style="display:none" 隐藏不满足的 -->
<hr>
<!--key必须是唯一值,不然会报错 -->
<span v-for="i in n" v-bind:key="i.a">{{i.a}},{{i.b}}</span><br/>
<span v-for="i,j in n" v-bind:key="j">{{j+1}}:{{i.a}},{{i.b}};</span><br/>
<hr>
<button v-on:click="a()">+</button>{{ count }}<br/>
<!-- 修改文本框的值,不会影响a()后续的调用结果 -->
<input type="text" v-bind:value="count"/><br/>
<!-- 修改文本框的值,会影响a()后续的调用结果 -->
<input type="text" v-model="count"/><br/>
</div>
</template>
<style scoped>
// 这里放以前 css 样式
</style>
二、组合式API关键字
| 关键字 | 核心用法 | 极简示例 |
|---|---|---|
| setup(Vue3) | Vue3 核心入口,组合式逻辑编写,无 this,替代 beforeCreate/created | setup() { const count = ref(0); return { count } } |
| ref(Vue3) | 包裹基本类型,创建响应式数据,需要导入import {ref} from 'vue',在script要加.value访问 / 修改,但是在template使用的时候不用加.value | const count = ref(0); count.value++ |
| reactive(Vue3) | 代理对象 / 数组,创建复杂类型响应式数据,直接修改属性(需要导入import {reactive} from 'vue') | const user = reactive({ name: '张三' }); user.name = '李四' |
| defineProps(Vue3) | 内置编译宏,定义组件入参(父传子),无需导入,支持类型校验 | const props = defineProps({ title: String, count: { type: Number, default: 0 } }) |
| defineEmits(Vue3) | 内置编译宏,定义自定义事件(子传父),无需导入,支持参数校验 | const emit = defineEmits(['change', 'submit']); emit('change', 123) |
| watchEffect(Vue3) | 自动收集依赖,监听响应式变化,组件卸载自动停止 | watchEffect(() => { console.log(count.value) }) |
| watch(Vue3) | 显式监听指定响应式数据,支持深度监听 / 立即执行 / 取消监听 | watch(count, (newVal) => { console.log(newVal) }, { immediate: true }) |
| slot | 组件插槽,支持具名 / 作用域插槽,实现组件内容自定义 | 组件内:<slot name="footer" :data="count"></slot>;使用:<template #footer="scope">{{ scope.data }}</template> |
| defineExpose(Vue3) | 内置编译宏,暴露组件内部属性 / 方法,供父组件通过 ref 获取 | defineExpose({ count, handleClick });(父组件:childRef.value.count) |
|
withDefaults(Vue3) (TS 项目) | 内置编译宏,为 props 设置默认值(仅配合 TS 接口使用) | interface Props { title?: string }; const props = withDefaults(defineProps<Props>(), { title: '默认标题' }) |
| provide/inject | 跨层级通信,非响应式需包装 ref,适合深层组件传值 | 父:provide('token', ref('123'));子:const token = inject('token') |
| teleport | 渲染到指定 DOM 节点,解决层级 / 样式问题(如弹窗) | <teleport to="body"><div>弹窗</div></teleport> |
| computed(Vue3) | 计算属性,依赖缓存,仅依赖变化时重新计算 | const double = computed(() => count.value * 2) |
| toRef/toRefs(Vue3) | 解构响应式对象,保留响应式,避免解构丢失响应式 | const { name } = toRefs(user); const age = toRef(user, 'age') |
例子1:
<script setup>
import {ref} from 'vue'
import {reactive} from 'vue'
let count = ref(0);
function a(){
count.value++;
console.log(count.value);
}
let o=reactive({a:"a",b:1});
function b(){
o.b++;
console.log(o.b);
}
</script>
<template>
<div>
<button v-on:click="a()">+</button>{{ count }}<br/>
<button v-on:click="b()">+</button>{{ o.b }}
</div>
</template>
<style>
</style>
【插一嘴】
1、有没有发现ref有增加了.value,但是reactive就没有加……
因为一个是基本类型,不可变没有属性。一个是对象本身就有属性。
| 特性 | ref | reactive |
|---|---|---|
| 目标类型 | 基本类型 + 任何类型 | 仅对象类型 |
| 访问方式 | 需要 .value | 直接访问属性 |
| 原理 | 包装对象 + getter/setter | Proxy 代理 |
| 模板中 | 自动解包,无需 .value | 直接使用 |
2、还有没有发现function似乎写法用法有点细微差别
| 写法类型 | 示例代码 | 核心特性 |
|---|---|---|
| 箭头函数(变量赋值) | let fn1 = () => { return 'hi' } | 1. 无独立 this(继承外层作用域);2. 不能作为构造函数;3. 简写灵活 |
| 函数表达式(变量赋值) | let fn2 = function() { return 'hi' } | 1. 有独立 this;2. 变量提升仅提升声明,不提升赋值;3. 可匿名 / 具名 |
| 函数声明(function 关键字) | function fn3() { return 'hi' } | 1. 有独立 this;2. 完全变量提升(可先调用后定义);3. 必须具名 |
用的时候,有括号和没括号的区别:
@click="a":传递函数引用,Vue 会自动传事件对象 e,如 a(e);
@click="a()":立即执行函数,无默认参数,如需传参需手动写 a(123)。
例子2:
首先要补充下组件的概念(组件放在components目录里,也是.vue后缀),之后才可以说组件之间的数据传递(父传子defineProps、子传父defineEmits)
<父组件zero.vue>
<script setup>
import {ref} from 'vue';
//导入3个子组件
import one from './components/one.vue';
import tow from './components/tow.vue';
import three from './components/three.vue';
let x=ref("z");
let x1=ref("");
function a(){
x1.value="z1";
}
let x2=ref("");
function f2(data){
x2.value=data;
}
</script>
<template>
<div>
<button @click="a()">点我会影响one组件的内容</button>
以下是zero组件的子组件
<!-- 将子组件拼凑在父组件zero.vue中 -->
<one class="one" v-bind:y="x" :y1="x1"></one>
{{ x2 }}
<tow class="tow" v-on:aa="f2"></tow>
<three></three>
</div>
</template>
<style scoped>
.one{
height:66px;
}
</style>
<子组件one.vue、tow.vue、three.vue>
<script setup>
//导入函数:defineProps 读音:/dɪˈfaɪn prɒps/ 谐音:"迪-范恩-普绕普斯"
import {defineProps} from 'vue';
//调用defineProps,注意要是多次调用defineProps会覆盖,接受返回值的话
const props = defineProps({
y: String,
y1: String
});
</script>
<template>
<div>
这是子组件-one组件<br/>
{{ y }}:{{ y1 }}
</div>
</template>
<style>
</style>
【插一嘴】
| 关键字 | 重复声明 | 重新赋值 | 作用域 | 变量提升 |
|---|---|---|---|---|
const | ❌ 不允许 | ❌ 不允许 | 块级作用域 | ❌ 不提升 |
let | ❌ 不允许 | ✅ 允许 | 块级作用域 | ❌ 不提升 |
var | ✅ 允许 | ✅ 允许 | 函数作用域 | ✅ 会提升 |
<script setup>
//导入函数:defineEmits 读音: [dɪˈfaɪn ɪˈmɪts] 谐音:"第-范 伊-米茨"
import {defineEmits} from 'vue';
//使用defineEmits
//传入可以是:字符串数组、验证函数对象、类型字面量、接口或类型别名(Vue3.3+)
let emits = defineEmits(["aa"]); // aa是向父组件提交数据的时间的名字
//具体执行向父组件传递数据的操作
function a(data){
//通过aa事件将data数据向父组件传递
emits("aa",data)
}
</script>
<template>
<div>
这是子组件-two组件
<button @click="a('x')">按钮</button>
</div>
</template>
<style scoped>
</style>
子组件-three组件在路由,往下看能找到他emmmm
三、选项式 API 关键字
| 关键字 | 核心用法 | 极简示例 |
|---|---|---|
| data(Vue2) | 用于存放组件的响应式状态(页面动态数据),必须以函数形式返回对象(避免复用冲突) | data() { return { count: 0 } } |
| methods | 用于定义组件的方法(包含事件处理函数、可复用逻辑函数),方法内的 this 固定指向当前组件实例,支持接收参数传递 | methods: { handleClick() { this.count++ } } |
| props(Vue2) | 定义组件入参,支持类型校验 / 默认值 / 必传项 | props: { title: { type: String, default: '默认' } } |
| computed(Vue2) | 计算属性,依赖缓存,通过 this 访问数据 | computed: { double() { return this.count * 2 } } |
| watch(Vue2) | 监听数据变化,支持深度监听 / 立即执行 | watch: { count(newVal) { console.log(newVal) } } |
| emits(Vue2) | 定义自定义事件,Vue2.3+ 支持,替代直接 $emit | emits: ['change'], methods: { handleEmit() { this.$emit('change') } } |
四、* 生命周期钩子
| 关键字 | 核心用法 | 极简示例 |
|---|---|---|
| onMounted(Vue3)/ mounted(Vue2) | 组件挂载完成,可操作 DOM,最常用生命周期 |
Vue3: Vue2: |
| onBeforeMount(Vue3)/ beforeMount(Vue2) | 组件挂载前执行,DOM 未生成 |
Vue3: Vue2: |
| onBeforeUnmount(Vue3)/ beforeDestroy(Vue2) | 组件销毁前执行,清理定时器 / 事件监听 | Vue3:onBeforeUnmount(() => {});Vue2:beforeDestroy() {} |
| onUnmounted(Vue3)/ destroyed(Vue2) | 组件销毁完成,收尾操作 |
Vue3: Vue2: |
| onUpdated(Vue3)/ updated(Vue2) | 组件更新完成,DOM 已重新渲染 |
Vue3: Vue2: |
| onBeforeUpdate(Vue3)/ beforeUpdate(Vue2) | 组件更新前执行,数据已变 DOM 未更 |
Vue3: Vue2: |
| onErrorCaptured(Vue3)/ errorCaptured(Vue2) | 捕获子组件错误,避免应用崩溃 | Vue3:onErrorCaptured((err) => { console.log(err); return true }) |
| onActivated(Vue3)/ activated(Vue2) | keep-alive 缓存组件激活时执行 |
Vue3: Vue2: |
| onDeactivated(Vue3)/ deactivated(Vue2) | keep-alive 缓存组件失活时执行 |
Vue3: Vue2: |
例子:
<script setup>
import {
ref,
onBeforeMount,
onMounted,
onBeforeUpdate,
onUpdated,
onBeforeUnmount,
onUnmounted,
onErrorCaptured
} from 'vue'
// 使用示例
onBeforeMount(() => {
//可以打开debugger;注释调试看,也可以在想要加断点的地方加入debugger;
//debugger;
console.log('挂载前')
})
onMounted(() => {
console.log('挂载完成')
})
onBeforeUnmount(() => {
console.log('卸载前')
})
onUnmounted(() => {
console.log('卸载完成')
})
let count = ref(0);
function a(){
count.value++;
console.log(count.value);
}
</script>
<template>
<div>
<button v-on:click="a()">+</button>{{ count }}<br/>
</div>
</template>
<style>
【vue-router】
先要安装依赖:npm install vue-router
之后创建待路由的组件c1、c2放在components里<组件three.vue>
<script setup>
</script>
<template>
<div>
这是子组件-three组件
<router-view></router-view>
</div>
</template>
<style>
</style>
<组件c1.vue、c2.vue>
<script setup>
</script>
<template>
<div>
这是子组件-c1组件
</div>
</template>
<style>
</style>
<script setup>
</script>
<template>
<div>
这是子组件-c2组件
</div>
</template>
<style>
</style>
在src下面创建routers目录,创建router.js路由相关的js文件
//导入创建路由对象的一些函数
import {createRouter,createWebHashHistory} from 'vue-router';
//导入子组件
import c1 from '../components/c1.vue';
import c2 from '../components/c2.vue';
//调用createRouter构建路由对象,返回router
let router = createRouter({
history:createWebHashHistory(),
routes:[
{
path:"/c1",
component:c1
},
{
path:"/c2",
component:c2
}
]
});
// 暴露路由对象
export default router;
之后再main.js里面导入路由文件(这里前面没写,默认生成的是App不是Zero)
import {createApp} from 'vue'
import router from './routers/router.js';
import Zero from '.Zero.vue'
let app = createApp(Zero);
app.use(router);
app.mount('#zero')
此时,切换浏览器url路由就会变化了
修改three组件,增加连接用于点击切换路由
<script setup>
</script>
<template>
<div>
这是子组件-three组件
<router-link to="/c1">c1组件</router>
<router-link to="/c2">c2组件</router>
<router-view></router-view>
</div>
</template>
<style>
</style>
【Pinia】
要是没有父子关系,就要借助Pinia 读音: [ˈpiːniə] 谐音:"皮-尼亚"
Pinia是Vue的状态管理库,允许跨组件/页面共享状态。
先要安装依赖:npm install pinia
之后创建共享数据相关的目录文件stores/store.js
//定义共享数据,借助方法defineStore
//导入defineStore
import {defineStore} from 'pinia';
//使用defineStore,参数是一个对象,这个对象包含4个属性:id、state、getters、actions
//defineStore调用以后,返回值还是一个函数,外界通过调用这个函数操作共享数据
let share = defineStore({
id:'myid001',//表述共享数据对应的id,全局唯一
state:()=>{
return{
x:"A"
y:65
};//return返回值才是共享的数据
},
getters:{//相当于定义多个共享数据的get方法,方法里面获取数据
getX(){
return this.x;
},
getY(){
return this.y;
}
},
actions:{//定义多个动作
doubleY(){
this.y=this.y+2;
}
}
});
//暴露share
export {share};
之后再main.js里面配置Pinia
import {createApp} from 'vue'
import router from './routers/router.js';
import Zero from '.Zero.vue'
import {createPinia} from 'pinia'
let pinia=creartPinia();
let app = createApp(Zero);
//使用pinia
app.use(pinia);
//使用router
app.use(router);
app.mount('#zero')
之后在需要的地方使用,例如
<script setup>
// 共享数据导入
import {share} from '../shore/store';
let mysharedata =share; // mysharedata共享数据
</script>
<template>
<div>
<span>这是子组件-c1组件/<span><br/>
显示共享数据{{ mysharedata }}
修改共享数据:<input type="text" v-model="mysharedata.x">
<button @click="mysharedata.doubleY()">doubleY</button>
</div>
</template>
<style>
</style>
<script setup>
// 共享数据导入
import {share} from '../shore/store';
let mysharedata =share; // mysharedata共享数据
</script>
<template>
<div>
<span>这是子组件-c2组件/<span><br/>
显示共享数据{{ mysharedata }}
修改共享数据:<input type="text" v-model="mysharedata.x">
</div>
</template>
<style>
</style>
9、非官方包的使用
【axios】
axios 音标:[æksi:əʊs] 谐音:"艾克-see-欧斯"
axios 是 vue 代替 ajax 的一个异步处理
┌─────────────────────────────────────────────┐
│ 1. 触发事件 │
│ (点击、滚动、输入、定时器等) │
└─────────────────┬───────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ 2. 创建 XMLHttpRequest 对象 │
│ 或使用 Fetch API │
└─────────────────┬───────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ 3. 配置并发送异步请求 │
│ (GET/POST/PUT/DELETE 等) │
└─────────────────┬───────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ 4. 服务器处理请求 │
│ (数据库操作、业务逻辑等) │
└─────────────────┬───────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ 5. 返回数据(JSON/XML/Text) │
└─────────────────┬───────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ 6. 客户端接收数据,用 JavaScript 更新DOM │
│ (局部更新,不刷新整个页面) │
└─────────────────────────────────────────────┘
【插一嘴】
| 技术 | 说明 | 示例 |
|---|---|---|
| XMLHttpRequest | 原始的 AJAX API | const xhr = new XMLHttpRequest() |
| Fetch API | 现代浏览器原生 API | fetch('/api/data') |
| Axios | 流行的第三方库 | axios.get('/api/data') |
| jQuery.ajax | jQuery 的封装 | $.ajax({url: '/api/data'}) |
ajax主要是做异步处理的(啊……我以前其实jq的用的比较多,具体要用可以查一下语法)
【原生例子】
<html>
<herad>
<title></title>
<script>
function getData(){
//定义XMLHttpRequest对象
let req=new XMLHttpRequest();
req.open("get","http……服务器对应的接口服务……");
//发送异步请求:调用XMLHttpRequest方法
req.send();
//获取服务器端响应的数据:每次状态变化都会出发后面的函数执行(回调函数)
req.onreadystatechange = funxtion(){
if(req.readyState ==4 && req.status == 200){
//响应数据填充在div中:
document.getElementById('mydiv').innerText=req.responseText;
}
}
}
</script>
</head>
<body>
<div id="mydiv"></div>
<button onclick="getData()"></button>
</body>
</html>
【readyState状态枚举】
| 值 | 常量 | 状态 | 描述 |
|---|---|---|---|
| 0 | UNSENT | 未初始化 | 请求未初始化,open() 方法还未调用 |
| 1 | OPENED | 已打开 | open() 方法已调用,但 send() 还未调用 |
| 2 | HEADERS_RECEIVED | 已发送 | send() 已调用,已接收到响应头 |
| 3 | LOADING | 接收中 | 正在接收响应体(部分数据可用) |
| 4 | DONE | 完成 | 请求完成,响应已完全接收(或失败) |
接下来来具体的使用
下载 axios 依赖:npm install axios
<script setup>
//导入axios方法
import axios from "axios";
//导入ref
import ref from "vue";
//定义一个响应式数据
let msg=ref("");
//编写getData()函数
function getData(){
//调用axios方法,发送请求,参数是个请求信息的对象
let promise = axios({
method:'get'
url:'http……'
});
//利用promise 对象的then方法设置回调函数
promise.then(function(resp){
console.log(resp);
console.log(resp.data.属性);
msg.value = resp.data;
});
}
</script>
<template>
<div>
<div v-text="msg"></div>
<button @click="getData()"></button>
</div>
</template>
<style>
</style>
简化的写法
<script setup>
//导入axios方法
import axios from "axios";
//导入ref
import { ref } from "vue";
//定义一个响应式数据
let msg=ref("");
//编写getData()函数
function getData(){
axios.get('http……',{
params:{
key1:'value1',
key2:'value2'
}
}).then(resp => {
msg.value = resp.data;
});
}
function getData1(){
axios.post('http……',
{
// post 请求体参数
key1:'value1',
key2:'value2'
},{
// 配置参数
params:{
key3:'value3'
}
// 还可以添加其他配置,如 headers、timeout 等
// headers: { 'Content-Type': 'application/json' }
}).then(resp => {
msg.value = resp.data;
}).catch(error => {
console.error('POST 请求失败:', error)
msg.value = '请求失败'
});
}
</script>
<template>
<div>
<div v-text="msg"></div>
<button @click="getData()"></button>
<button @click="getData1()"></button>
</div>
</template>
<style>
</style>
10、使用第三方栗子
拿饿了么举例:
创建项目 npm create vite
进入项目 cd xxx
安装依赖 npm i
安装第三方依赖 npm install element-plus
在 main.ts 引入 ElementPlue 对象和全局样式并应用
//引入对象
import ElementPlue from 'element-plus';
//引入样式
import 'element-plus/dist/index.css';
//应用
let app =createApp(App);
app.use(ElementPlue);
app.mount('#app');
之后根据官网的来使用对应的控件(别忘记复制样式)

被折叠的 条评论
为什么被折叠?



