目录
npm
npm 是 nodejs 中进行 包管理 的工具;
下载:Node.js — Run JavaScript Everywhere
2.1环境
●安装Node.js
●配置 npm
npm config set registry https://registry.npmmirror.com #设置国内阿里云镜像源
npm config get registry #查看镜像源
2.2命令
- ●npm init: 项目初始化;
- ○npm init -y:默认一路yes,不用挨个输入信息
- ●npm install 包名:安装js包到项目中(仅当前项目有效)。指定 包名,或者 包名@版本号
- ○npm install -g: 全局安装,所有都能用
- ○可以去 npm仓库 搜索第三方库
- ●npm update 包名:升级包到最新版本
- ●npm uninstall 包名:卸载包
- ●npm run:项目运行
2.3使用流程
Java:
●项目创建:Java环境 ==》 maven 初始化 ==》 添加依赖 ==》运行项目
●项目迁移:Java环境 ==》 maven 下载依赖 ==》运行项目
Vite
3.1简介
快速创建前端项目脚手架
●统一的工程化规范:目录结构、代码规范、git提交规范 等
●自动化构建和部署:前端脚手架可以自动进行代码打包、压缩、合并、编译等常见的构建工作,可以通过集成自动化部署脚本,自动将代码部署到测试、生产环境等;
3.2实战
创建项目
npm create vite #根据向导选择技术栈
安装依赖
npm install #安装项目所有依赖
npm install axios #安装指定依赖到当前项目
npm install -g xxx # 全局安装
项目启动
npm run dev #启动项目
项目打包
npm run build #构建后 生成 dist 文件夹
项目部署
●前后分离方式:需要把 dist 文件夹内容部署到如 nginx 之类的服务器上。
●前后不分离方式:把 dist 文件夹内容复制到 SpringBoot 项目 resources 下面
Vue3
2023 年前端框架各个国家使用占比。
我们使用 vite 创建 vue项目脚手架,并测试Vue功能
npm create vite #根据向导选择技术栈
4.1组件化
组件系统是一个抽象的概念;
- ●组件:小型、独立、可复用的单元
- ●组合:通过组件之间的组合、包含关系构建出一个完整应用
几乎任意类型的应用界面都可以抽象为一个组件树;
4.2SFC
Vue 的单文件组件 (即 *.vue 文件,英文 Single-File Component,简称 SFC) 是一种特殊的文件格式,使我们能够将一个 Vue 组件的模板、逻辑与样式封装在单个文件中
<script setup>
//编写脚本
</script>
<template>
//编写页面模板
</template>
<style scoped>
//编写样式
</style>
4.3Vue工程
运行原理
4.4基础使用
插值
<script setup>
//基本数据
let name = "张三"
let age = 18
//对象数据
let car = {
brand: "奔驰",
price: 777
}
</script>
<template>
<p> name: {{name}} </p>
<p> age: {{age}} </p>
<div style="border: 3px solid red">
<p>品牌:{{car.brand}}</p>
<p>价格:{{car.price}}</p>
</div>
</template>
<style scoped>
</style>vue
事件绑定:v-on
使用 v-on指令,可以为元素绑定事件。可以简写为 @
<script setup>
//定义事件回调
function buy(){
alert("购买成功");
}
</script>
<template>
<button v-on:click="buy">购买</button>
<button @click="buy">购买</button>
</template>
<style scoped>
</style>
Modifiers:修饰符详情
事件处理 | Vue.js
条件判断:v-if
循环:v-for
内置指令 | Vue.js;后期我们都会用到。
属性绑定
响应式 - ref()
数据的动态变化需要反馈到页面;
Vue通过ref()和reactive()包装数据,将会生成一个数据的代理对象。vue内部的 基于依赖追踪的响应式系统 就会追踪感知数据变化,并触发页面的重新渲染。
使用方式
使用步骤:
1使用 ref() 包装原始类型、对象类型数据,生成 代理对象
2任何方法、js代码中,使用 代理对象.value 的形式读取和修改值
3页面组件中,直接使用 代理对象
注意:推荐使用 const(常量) 声明代理对象。代表代理对象不可变,但是内部值变化会被追踪。
<script setup>
import { ref } from 'vue'
const count = ref(0)
function increment() {
count.value++
}
</script>
<template>
<button @click="increment">
{{ count }}
</button>
</template>
深层响应性
import { ref } from 'vue'
const obj = ref({
nested: { count: 0 },
arr: ['foo', 'bar']
})
function mutateDeeply() {
// 以下都会按照期望工作
obj.value.nested.count++
obj.value.arr.push('baz')
}
响应式 - reactive()
使用步骤:
1使用 reactive() 包装对象类型数据,生成 代理对象
2任何方法、js代码中,使用 代理对象.属性的形式读取和修改值
3页面组件中,直接使用 代理对象.属性
import { reactive } from 'vue'
const state = reactive({ count: 0 })
<button @click="state.count++">
{{ state.count }}
</button>
基本类型用 ref(),对象类型用 reactive(),ref 要用 .value,reactive直接 . 。页面取值永不变。
也可以 ref 一把梭,大不了 天天 .value
表单绑定
复制如下模板到组件,编写你的代码,实现表单数据绑定
<div style="display: flex;">
<div style="border: 1px solid black;width: 300px">
<form>
<h1>表单绑定</h1>
<p style="background-color: azure"><label>姓名(文本框):</label><input/></p>
<p style="background-color: azure"><label>同意协议(checkbox):</label>
<input type="checkbox"/>
</p>
<p style="background-color: azure">
<label>兴趣(多选框):</label><br/>
<label><input type="checkbox" value="足球"/>足球</label>
<label><input type="checkbox" value="篮球"/>篮球</label>
<label><input type="checkbox" value="羽毛球"/>羽毛球</label>
<label><input type="checkbox" value="乒乓球"/>乒乓球</label>
</p>
<p style="background-color: azure">
<label>性别(单选框):</label>
<label><input type="radio" name="sex" value="男">男</label>
<label><input type="radio" name="sex" value="女">女</label>
</p>
<p style="background-color: azure">
<label>学历(单选下拉列表):</label>
<select>
<option disabled value="">选择学历</option>
<option>小学</option>
<option>初中</option>
<option>高中</option>
<option>大学</option>
</select>
</p>
<p style="background-color: azure">
<label>课程(多选下拉列表):</label>
<br/>
<select multiple>
<option disabled value="">选择课程</option>
<option>语文</option>
<option>数学</option>
<option>英语</option>
<option>道法</option>
</select>
</p>
</form>
</div>
<div style="border: 1px solid blue;width: 200px">
<h1>结果预览</h1>
<p style="background-color: azure"><label>姓名:</label></p>
<p style="background-color: azure"><label>同意协议:</label>
</p>
<p style="background-color: azure">
<label>兴趣:</label>
</p>
<p style="background-color: azure">
<label>性别:</label>
</p>
<p style="background-color: azure">
<label>学历:</label>
</p>
<p style="background-color: azure">
<label>课程:</label>
</p>
</div>
</div>
计算属性 - computed
计算属性:根据已有数据计算出新数据
<script setup>
import {computed, reactive, toRef, toRefs} from "vue";
//省略基础代码
const totalPrice = computed(()=>{
return price.value * num.value - coupon.value*100
})
</script>
<template>
<div class="car">
<h2>优惠券:{{ car.coupon }} 张</h2>
<h2>数量:{{ car.num }}</h2>
<h2>单价:{{ car.price }}</h2>
<h1>总价:{{totalPrice}}</h1>
<button @click="getCoupon">获取优惠</button>
<button @click="addNum">加量</button>
<button @click="changePrice">加价</button>
</div>
</template>
<style scoped>
</style>
4.5进阶用法
监听 - watch
watch(num, (value, oldValue, onCleanup) => {
console.log("newValue:" + value + ";oldValue:" + oldValue)
onCleanup(() => {
console.log("onCleanup....")
})
})
生命周期
每个 Vue 组件实例在创建时都需要经历一系列的初始化步骤,比如设置好数据侦听,编译模板,挂载实例到 DOM,以及在数据改变时更新 DOM。在此过程中,它也会运行被称为生命周期钩子的函数,让开发者有机会在特定阶段运行自己的代码。
生命周期整体分为四个阶段,分别是:创建、挂载、更新、销毁,每个阶段都有两个钩子,一前一后。
常用的钩子:
●onMounted(挂载完毕)
●onUpdated(更新完毕)
●onBeforeUnmount(卸载之前)
<script setup>
import {onBeforeMount, onBeforeUpdate, onMounted, onUpdated, ref} from "vue";
const count = ref(0)
const btn01 = ref()
// 生命周期钩子
onBeforeMount(()=>{
console.log('挂载之前',count.value,document.getElementById("btn01"))
})
onMounted(()=>{
console.log('挂载完毕',count.value,document.getElementById("btn01"))
})
onBeforeUpdate(()=>{
console.log('更新之前',count.value,btn01.value.innerHTML)
})
onUpdated(()=>{
console.log('更新完毕',count.value,btn01.value.innerHTML)
})
</script>
<template>
<button ref="btn01" @click="count++"> {{count}} </button>
</template>
<style scoped>
</style>
组件传值
父组件给子组件传递值;
单向数据流效果:
●父组件修改值,子组件发生变化
●子组件修改值,父组件不会感知到
//父组件给子组件传递数据:使用属性绑定
<Son :books="data.books" :money="data.money"/>
//子组件定义接受父组件的属性
let props = defineProps({
money: {
type: Number,
required: true,
default: 200
},
books: Array
});
子传父 - Emit
props 用来父传子,emit 用来子传父
//子组件定义发生的事件
let emits = defineEmits(['buy']);
function buy(){
// props.money -= 5;
emits('buy',-5);
}
//父组件感知事件和接受事件值
<Son :books="data.books" :money="data.money"
@buy="moneyMinis"/>
思考:
●利用父子传值即可
插槽 - Slots
<!-- 组件定义 -->
<button class="fancy-btn">
<slot></slot> <!-- 插槽出口 -->
</button>
<!-- 组件使用 -->
<FancyButton>
Click me! <!-- 插槽内容 -->
</FancyButton>
默认内容
<button type="submit">
<slot>
Submit <!-- 默认内容 -->
</slot>
</button>
具名插槽
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
使用: v-slot可以简写为 #
<BaseLayout>
<template v-slot:header>
<!-- header 插槽的内容放这里 -->
</template>
</BaseLayout>