DOM BOM
JavaScript = ECMAscript + BOM + DOM
ECM为浏览器处理js语言的规范
DOM为js提供了访问和操作元素的接口 document对象
BOM为js提供了一种控制浏览器的方法 window对象
DOM树指各级元素标签之间的父子关系
Vue语法结构
Vue通过虚拟DOM来进行更新,只更新差异化的部分,而不是整个DOM更新,因此效率高
使用Vue:
1、从Vue对象中导入函数
2、通过 creatApp() 创建一个vue实例
3、使用Vue实例对象的 mount() 和所在页面建立联系,将Vue挂载到页面上
const { createApp } = Vue
const app = createApp({})
app.mount("#app")
4、setup函数 使用在 createApp() 函数的参数对象中,用来声明响应式变量或者函数
5、在 setup函数 中通过 return 返回的对象会暴露在页面中(所有对象和函数都得暴露才能使用)
6、ref函数,也是需要在Vue对象中导入
<script>
const {createApp, ref} = Vue
window.onload = function(){
createApp({
setup() {
const message = ref('hellow vue')
const num1 = ref(1)
const num2 = ref(2)
function num1_add(){
num1.value += 1
}
function num1_remove(){
num1.value -= 1
}
return {
num1,
num2,
message,
num1_add,
num1_remove
}
}
}).mount('#app')
}
</script>
模板语法
1、文本插值:在script中将变量定义并且暴露出来,在html结构中可以使用 {{ value }} 进行取值
2、JS表达式: {{ a }} 其中a可以作为js表达式出现,也会正常执行
3、调用函数:{{ func }} func可以是自定义函数(需要在scipt中定义并暴露),也可以是内置函数
4、vue指令: v-html
和 v-text
是 Vue 提供的两个指令,它们用于处理模板中的文本内容。
<!-- 使用 v-text 渲染 -->
<div v-text="mesB">v-text 渲染</div>
<!-- 使用 v-html 渲染 -->
<div v-html="mesC">v-html 渲染</div>
属性绑定
1、使用:v-bind: 或 **: **
2、绑定单个属性:字符串,布尔值,整形等等
<!-- v-bind完整写法 跳转到百度首页 -->
<p><a v-bind:href="baidu">访问百度</a></p>
<!-- v-bind缩写形式 跳转到必应首页-->
<p><a :href='bing'>访问必应</a></p>
3、绑定多个属性
script
const style1 = ref({"width":"100px", "color":"red"})
body
<h1 :style="style1">多个属性绑定</h1>
事件绑定
1、 v-on: 简写为 @
2、内联js语法:
<p><input type="button" v-on:click="numA++" value="点击加1" /> {{numA}}</p>
3、绑定函数:有参函数 @add = “add_num(参数)” 无参函数 @add = “add_num”
双向绑定
1、 v-model:
2、文本的单项绑定:只需要将v-model绑定到对应的变量上即可
3、表单绑定:表单存在单选或多选情况,如果是多选情况,则需要在ref定义时加上 【】表示多元素
4、修饰符:使用 v-model.修饰符:
4.1、lazy修饰符:用于事件之后同步,比如输入框输入完成后再显示结果
4.2、number修饰符:将用户输入的值转换为数值类型。一般情况下所有输入都当成字符串处理,这个修饰符可以将数字自动转换成数字类型
4.3、trim修饰符:自动过滤输入的前后空格,中间的空格不会过滤
条件渲染
1、v-if = “flag” if需要参数 v-elseelse不需要参数
2、if/else语句只会创建符合条件的元素
3、v-show = “flag” 针对css中的display属性进行操作,隐藏则显示 none
列表渲染
1、v-for=”item in items“
2、带索引渲染:v-for=“(item, index) in data” item为值,index为下标索引
3、索引对象可以是普通的数组(【】), 或者js对象({name: “Tom”, age:18})
4、带属性名的渲染:对js对象的渲染v-for=“(value, key) of data”
5、带索引值的渲染:v-for=“(item, key, index) of items”
6、多层数据列表的渲染: Vue 默认按照就地更新 的策略来更新通过 v-for
渲染的元素列表。所以最好挂载在一个唯一的值做为 :key
属性的值,避免出现渲染错误
const data = ref([{
id:"s01",
name: "Tom",
age: 22,
gender: "male",
address: "BeiJing"
},{
id:"s02",
name: "Jack",
age: 23,
gender: "male",
address: "ShangHai"
}
<li v-for="(obj,index) in data" :key="index">
计算属性
1、const { createApp, ref,computed } = Vue 需要导入实例对象
2、computed期望接受一个get函数,返回值为一个计算数学ref,且该ref已经解包
3、和普通的响应式相同,都需要在 setup 中暴露
window.onload = function(){
createApp({
setup() {
const firstName = ref("Michael")
const lastName = ref("Jordan")
// 添加计算属性
const fullName = computed(()=>{
console.log("FullName")
return firstName.value + "." + lastName.value
})
return {
// 暴露计算属性
fullName
}
}
}).mount('#app');
4、计算属性与方法的区别:计算属性存在缓存,计算属性的响应式依赖更新才会进行重新计算,否则会直接调用缓存值;而函数方法每次计算都会重新取值计算
5、计算属性可写:计算属性默认可读的,尝试修改一个计算属性时会受到警告;同时通过get()方法对修改源值进行响应,使用set()方法对修改结果值进行响应
// 计算属性
const fullName = computed({
get(){
console.log("FullName")
return firstName.value + "." + lastName.value
},
set(newValue){
[firstName.value, lastName.value] = newValue.split(".")
}
})
// 函数
function getfullName(){
console.log("GetFullName")
return firstName.value + "." + lastName.value
}
// 事件响应函数
function changeFirstName(){
// 修改计算属性的值
fullName.value = "A.B"
console.log(firstName.value)
console.log(lastName.value)
}
function changeFirstName2(){
firstName.value += "A"
}
Vite 项目构建
view组件基础
1、定义组件:<script setup></script>
+<template></template>
+<style></style>
2、在App.vue中集合调用:导入各种组件,在其中组合调用
3、注意:需要导入vue中的某些对象 import { ref } from "vue"
vue组件的正向数据传递
1、声明:子组件声明 defineProps(["title", "name", ……})
2、使用:
2.1:子组件占位
<h3>{{name}}</h3>
<p>{{age}}</p>
2.2:父组件传值
const content = ref( content_value)
<!-- title 使用普通方式传递数据, content 使用v-bind方式传递动态数据 -->
<SC title="Vue 组件传递数据" :content="content"></SC>
3、注意:prop只能以字符串的形式声明注册,但是可以接受任何值;使用prop属性名传递数据时,可以传递字面值,也可以结合 v-bind 传递动态数据
vue反向传递数据
1、反向传递数据过程:
1.1、在父组件中绑定一个自定义事件,并定义该事件的响应方法
1.2、在子组件中触发自定义事件
1.3、父组件监听子组件,若触发事件,则执行相对应的方法
2、$emit方法时vue中自带的方法,不适用于自定义函数
<script setup>
import RSC from './RSC.vue';
function recvMsg(msg){
alert(msg)
}
</script>
<template>
<RSC @msg="recvMsg" />
</template>
-------------------------------------------------------------------------
子组件
<template>
<button @click="$emit('msg', 'Hello Vue')">点击触发msg事件</button>
</template>
3、 defineEmits() 函数 与 emit() 函数
3.1、defineEmits([“父组件函数名”])类似defineProps(),都是宏定义,用于子组件中,用来注明需要抛出的事件
3.2、defineEmits会返回一个等同于$emit方法的emit函数
3.3、返回的emit函数可以被用于组件的 <script setup>
中抛出事件
子组件
<script setup>
defineProps(["data"])
const emit = defineEmits(["delData"])
function deleteData(item){
emit("delData", item)
}
</script>
<template>
<div class="rsc">
<table>
<tr>
<th>编号</th>
<th>姓名</th>
<th>年龄</th>
<th>操作</th>
</tr>
<tr v-for="item in data" :key="item.sid">
<td> {{ item.sid }}</td>
<td> {{ item.name }}</td>
<td> {{ item.age }}</td>
<td> <button @click="deleteData(item)">删除</button> </td>
</tr>
</table>
</div>
</template>
----------------------------------------------------------------------------------
父组件
<script setup>
import RSC from './RSC.vue';
import {ref} from "vue"
const data = ref([
{sid: "s01",name: "Tom",age: "23"},
{sid: "s02",name: "Jack",age: "24"},
{sid: "s03",name: "Rose",age: "25"}
])
function delDataAction(obj){
const idx = data.value.indexOf(obj)
data.value.splice(idx,1)
}
</script>
<template>
<RSC :data="data" @delData="delDataAction" />
</template>
插槽
1、作用:在某些场景中需要父组件往子组件中加塞一些片段
2、使用:标准形式 v-slot:name 简写为 #name
3、插槽内容:写在父组件中引用子组件的中间片段
4、出口:在子组件的template中加入 <slot>内容</slot> 块
5、具名插槽:父组件向某一个子组件中传递多个插槽元素
<!-- 具名插槽 -->
<slot name="sloatname"></slot>
<!-- 未具名插槽,默认名为 default -->
<slot></slot>
<template>
<h1>这是父组件内容</h1>
<SlotnameSC>
<template v-slot:header>
<h1>这是页面标题</h1>
</template>n
<template #default>
<p>这是内容显示区域</p>
<p>用来显示文本和图片</p>
</template>
<template #footer>
<p>这里显示页脚信息</p>
</template>
</SlotnameSC>
</template>
动态组件
1、用于在同一个页面切换不同的组件
2、使用:<component :is=“…”></component>
3、难点在于切换的逻辑
路由管理
1、使用
1.1、在src目录下新建router文件夹,在其下新建index.js文件
在index.js处定义路由
import {createRouter,createWebHashHistory} from 'vue-router'
import Ceshiren from '../views/Ceshiren.vue'
import Hogwarts from '../views/Hogwarts.vue'
const routes=[
{
path:"/ceshiren",
component:Ceshiren
},
{
path:'/hogwarts',
component:Hogwarts
}
]
const router = createRouter({
// 路由模式
history:createWebHashHistory(),
routes,// `routes:routes` 的缩写
})
export default router
1.2、在main.js中注册路由
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import router from './router'
//注册路由
createApp(App).use(router).mount("#app")
1.3、在App.vue中使用路由
<template>
...
<div>
<p><router-link to="/ceshiren">点击进入 Ceshiren 页面</router-link></p>
<p><router-link to="/hogwarts">点击进入 Hogwarts 页面</router-link></p>
<router-view></router-view>
</div>
</template>
2、路由模式: hash模式 与 history模式
带参路由
1、使用:再index.js文件中在路径的后加上 : 参数名;在需要使用的vue界面中调用this.$route.params.参数名
const 路由=[
// 单个参数
{
path: '/post/:参数名',
component: PostDetail
},
// 多个参数
{
path:'/name/:参数名A/posts/:参数名B'
}
]
2、在路由中使用自定义的正则表达式来规范参数字符串可以实现路由匹配
3、通配符路由:
// 通配符路由,捕获所有未匹配到的路径
{
path: '/:pathMatch(.*)*',
component: NotFound
}
编程式导航
1、router对象,需要定义router
当前页面的router定义(vue3,setup)
import { useRouter } from 'vue-router'
const router = useRouter()
2、router.push()用于跳转到指定的路由
2.1、以字符串路径作为参数
router.push(“/codehome”);
2.2、以带有路径的对象作为参数
router.push({ path: “/codehome/codechild” });
2.3、命名的路由加上参数
router.push({ name: “userWithParam”, params: { userId: 123 } });
2.4、带查询参数
router.push({ name: “search”, query: { q: “今天吃什么” } });
3、router.go()接受一个整数作为参数,用于在路由历史中前进或后退
router.go(1); router.go(-1);
4、 router.replace()和push类似,但是不会保留历史记录
router.replace(“/ceshiren”)
router.push({ path: ‘/home’, replace: true })
axios访问api
1、基本用法:
1.1、安装:npm install axios
2、发送get请求:
2.1、axios.get(url[, config])
axios.get('https://httpbin.ceshiren.com/get?id=123')
.then((response) => {
alert('GET请求成功');
console.log(response)
})
.catch((error) => {
console.error('GET请求错误:', error);
});
2.2、传参get:
axios.get(“https://httpbin.ceshiren.com/get”, {params:{id:1, name:“lily”}})
3、发送post请求:
3.1、axios.post(url[, config])
3.2、发送传参post请求
json
const sendJsonRequest = function () {
const jsonData = { name: 'lily' }
axios.post('https://httpbin.ceshiren.com/post', jsonData)
.then((res) => {
alert('JSON 请求成功');
console.log(res)
}).catch((err) => {
console.log(err)
})
}
formdata
const sendFormRequest = function () {
//
const formData = new FormData();
formData.append('name', 'lily');
axios.post('https://httpbin.ceshiren.com/post', formData, {
// 添加请求头,指定表单数据格式
headers: {'Content-Type': 'multipart/form-data'}
})
.then((res) => {
alert('Form 表单请求成功');
console.log(res)
}).catch((err) => {
console.log(err)
})
}
4、优化网络封装请求
4.1、将网络基本配置提取(URL, CONTAIN-TYPE,TIMEOUT……)
在项目中添加api文件,其中新建http.js文件
// 完成 http 请求的基本配置信息
// 导入 axios
import axios from 'axios';
// 创建 axios 实例,并配置全局配置信息
const instance = axios.create({
// 请求头
headers:{
'Content-Type':'application/json',
},
// 超时时间
timeout:2500,
// 基础 url
baseURL: 'https://httpbin.ceshiren.com',
});
// 导出 axios 实例
export default instance;
4.2、封装请求方法
在api文件夹中,新建api.js
// 导入 instance 实例
import instance from "./http";
// 定义api实例,包含请求方法
const api = {
// get方法
get(url, params) {
// 使用 instance 实例发起请求
return instance({
url: url,
method: "get",
params: params,
});
},
// get方法
post(url, data) {
return instance({
url: url,
method: "post",
data: data,
});
},
// put方法
put(url, data) {
return instance({
url: url,
method: "put",
data: data,
});
},
// delete方法
delete(url, data) {
return instance({
url: url,
method: "delete",
data: data,
});
},
};
// 导入 api 实例
export default api;
4.3、挂载全局对象实例
在main.js中将封装好的api挂载到全局对象window上
// 导入 api 实例
import api from './api/api'
// 将网络请求实例挂载到全局对象中
window.$api = api
4.4、应用
const handleGetRequest = () => {
// 通过 window 对象中挂载的 api 实例调用请求方法
window.$api.get('/get', {params:{id:"123"}})
.then((result) => {
console.log(result)
}).catch((err) => {
console.log(err)
});
}