v-bind
- 语法:v-bind:属性名="vue变量"
- 简写::属性名="vue变量"
<div id='app'>
<img :src="image" :alt="name" srcset="">
</div>
<script>
Vue.createApp({
data() {
return {
name: '小明',
image: 'https://v3.ru.vuejs.org/logo.png',
};
},
}).mount('#app')
</script>
v-on
- v-on:事件名="要执行的少量代码"
- v-on:事件名="methods中的函数名"
- v-on:事件名="methods中的函数名(实参)"
- 简写:@事件名= "methods中的函数"
<div id="app">
<p>你要购买商品的数量:{{count}}</p>
<button v-on:click="count = count +1">+1</button>
<button v-on:click="addFn">+1</button>
<button v-on:click="addCountFn(5)">+5</button>
<button @click="addCountFn(5)">+5</button>
</div>
<script>
Vue.createApp({
data() {
return {
count: 1
};
},
//2.定义函数
methods: {
addFn() {
//this指向的export default的{}
//data函数会把对象挂到当前组件对象上
this.count++
},
addCountFn(num) {
this.count += num
}
}
}).mount('#app')
</script>
v-on按键修饰符
- 语法
- @keyup.enter 监测回车按键
- @keyup.esc 监测返回按键
<div id="app">
<input type="text" @keydown.enter="enterFn">
<input type="text" @keydown.esc="esc">
</div>
<script>
Vue.createApp({
//2.定义函数
methods: {
enterFn() {
console.log('用户按下了回车');
},
esc() {
console.log("用户按下了ESC");
}
}
}).mount('#app')
</script>
v-model
- 语法:v-model="Vue数据变量"
- 双向数据绑定
- 变量变化 -> 视图自动同步
- 试图变化 -> 变量自动同步
v-model 会让页面和数据双向关联到一起
<div id="app"><span>用户名</span>
//v-model 双向数据绑定
<input type="text" v-model="username">
</div>
<script>
Vue.createApp({
data() {
return {
username: "hi"
};
},
}).mount('#app')
</script>
v-model 修饰符
- 语法 v-model 修饰符="Vue 数据变量"
- .number 转成数值类型赋予给Vue数据变量
- .trim 去除左右两边空白字符后把值赋予给Vue数据变量
- .lazy 等表单失去焦点时,才把值赋予给Vue数据变量
v-text 和 v-html
- 语法
- v-text="Vue数据变量" 把值当成普通字符串显示
- v-html="Vue数据变量" 把值当成标签进行解析显示
<body>
<div id="app">
<p v-text="str"></p>
<p v-html="str"></p>
</div>
</body>
<script>
Vue.createApp({
data() {
return {
str: "<span>我是span标签</span>"
};
},
}).mount('#app')
</script>
v-show 和 v-if
- 语法
- v-show="Vue" 变量
- v-if="Vue" 变量
- 原理
- v-show 隐藏 用的display:none隐藏(频繁切换使用)
- v-if 隐藏 直接从DOM树上移出
v-if 可以配合 v-else 或者 v-else-if 使用
<div id="app">
<p v-if="age >= 18">成年了</p>
<p v-else>未成年</p>
</div>
<script>
Vue.createApp({
data() {
return {
age: 17
};
},
}).mount('#app')
</script>
v-for
- 语法
- v-for="(值变量,索引变量) in 目标结构"
- v-for="值变量 in 目标结构"
- 目标结构:
- 可以遍历数组 / 对象 / 数字
<div id="app">
<ul>
<li v-for="obj in stuArr" :key="obj.id">
<span>{{obj.name}}</span>
<span>{{obj.sex}}</span>
<span>{{obj.hubby}}</span>
</li>
</ul>
</div>
<script>
Vue.createApp({
data() {
return {
stuArr: [
{
id: 1001,
name: "孙悟空",
sex: "男",
hubby: "吃peach"
},
{
id: 1002,
name: "猴子",
sex: "男",
hubby: "啊吧不"
}
]
};
},
}).mount('#app')
</script>
动态class
用v-bind 给标签设置动态的值
- 语法:class=“{类名:布尔值}”
<div id="app">
<p :class="{red:bool}">动态class</p>
</div>
<script>
Vue.createApp({
data() {
return {
bool: true,
};
},
}).mount('#app')
</script>
<style scoped>
.red {
color: red;
}
</style>
动态style
给标签动态设置style的值
- 语法:style=“{css属性名:值}”
<div id="app">
<p :style="{backgroundColor: color}">动态class</p>
</div>
<script>
Vue.createApp({
data() {
return {
color: "red"
};
},
}).mount('#app')
</script>
计算属性
<template>
<div>
<p>{{ num }}</p>
</div>
</template>
<script>
export default {
data() {
return {
a: 10,
b: 20,
};
},
//计算属性:
//场景:一个变量的值,需要用另外变量计算而得来
//注意:计算属性和data属性都是变量-不能重名
computed: {
num() {
return this.a + this.b;
},
},
};
</script>
侦听器 watch
<template>
<div>
<input type="text" v-model="name" />
</div>
</template>
<script>
export default {
data() {
return {
name: "",
};
},
//侦听到name值的改变
watch: {
//newVal 当前最新值
//oldVal 上一刻值
name(newVal, oldVal) {
console.log(newVal, oldVal);
},
},
};
</script>
axios使用
- 特点
- 支持客户端发送Ajax请求
- 支持服务端Node.js发送请求
- 支持Promise相关用法
- 支持请求和响应的拦截器功能
- 自动转换JSON数据
axios获取所有图书get请求
<template>
<div>
<p>1.获取所有的图书信息</p>
<button @click="getAllFn">点击-查看控制台</button>
<p>2.查询某本书的信息</p>
<input type="text" placeholder="请输入要查询的书名" v-model="bName">
<button @click="findFn">查询</button>
</div>
</template>
<script>
import axios from 'axios'
export default {
data() {
return {
bName: ""
}
},
methods: {
getAllFn() {
// 1. 下载axios
// 2. 引入axios
// 3. 发起axios请求
axios({
url: "http://www.escook.cn:3006/api/getbooks",
method: "GET" //默认就是Get请求 可以省略不写
}).then(res => {
console.log(res);
})
},
findFn() {
axios({
url: "http://www.escook.cn:3006/api/getbooks",
method: "GET",
params: {
//都会被axios最终拼接到 url?后面
bookname: this.bName
}
}).then(res => {
console.log(res);
})
}
}
}
</script>
<style></style>
axios添加书籍-post传参
<template>
<div>
<p>3.新增图书信息</p>
<div> <input type="text" placeholder="书名" v-model="bookObj.bookname"></div>
<div>
<input type="text" placeholder="作者" v-model="bookObj.author">
</div>
<div>
<input type="text" placeholder="出版社" v-model="bookObj.publisher">
</div>
<button @click="sendFn">发布</button>
</div>
</template>
<script>
import axios from 'axios'
export default {
data() {
return {
bName: "",
bookObj: {
bookname: "",
author: "",
publisher: ""
}
}
},
methods: {
//发送函数
sendFn() {
axios({
url: "http://www.escook.cn:3006/api/addbook",
method: "POST",
data: {
Aappkey: "7250d3eb-18e1-41bc-8bb2-11483665535a",
...this.bookObj
//等同于下面
// bookname: this.bookObj.bookname,
// author: this.bookObj.author,
// publisher: this.bookObj.publisher
}
})
}
}
}
</script>
<style></style>
axios 全局配置
//全局配置URL
axios.defaults.baseURL = "http://www.escook.cn:3006"
- 修改请求url / 以后的请求都不用带前缀基地地址了-运行时,axios的baseURL会自动拼在前
//获取函数
getAllFn() {
// 1. 下载axios
// 2. 引入axios
// 3. 发起axios请求
axios({
url: "/api/getbooks",
method: "GET" //默认就是Get请求 可以省略不写
}).then(res => {
console.log(res);
})
}
$refs和$nextTick使用
通过id或ref属性获取原生DOM
<template>
<div>
<p>获取元素的DOM元素</p>
<h1 id="h" ref="myH">我是一个孤独又可怜的h1</h1>
</div>
</template>
<script>
export default {
mounted() {
console.log(document.getElementById("h")); //h1
console.log(this.$refs.myH); //h1
}
}
</script>
<style></style>
用id属性或者ref属性都可以获取原生DOM
通过ref属性获取组件对象
如何获取组件对象呢?
目标组件添加ref属性
this.$refs.名字 获取组件对象
<template>
<div>
<p>获取组件对象 - 可调用组件内一切</p>
<Demo ref="de"></Demo>
</div>
</template>
<script>
import Demo from '../../Child/Demo.vue'
export default {
mounted() {
let demoObj = this.$refs.de;
demoObj.fn();
},
components: {
Demo
}
}
</script>
<style></style>
nextTick+name属性
获取原生DOM内容
<template>
<div>
<p>3. vue更新DOM是异步的</p>
<p ref="myP">{{ count }}</p>
<button @click="btn">点击count+1 马上提取p标签里面的内容</button>
</div>
</template>
<script>
export default {
mounted() {
let demoObj = this.$refs.de;
demoObj.fn();
},
components: {
Demo
},
methods: {
btn() {
this.count++; //vue监测数据更新,开启一个DOM更新队列(异步任务)
//它不会立刻去更新DOM 而是要等待主线程执行完成
console.log(this.$refs.myP.innerHTML);
//所以这条语句获取的值是 0 vue更新是异步的
}
},
data() {
return {
count: 0
}
}
}
</script>
<style></style>
可以使用nextTick解决问题
//$nextTick 里的函数体
this.$nextTick(() => {
console.log(this.$refs.myP.innerHTML);
})
组件缓存
动态组件
- 什么是动态组件?
- 在同一个挂载点,可以切换显示不同组件
- 如何使用动态组件?
- vue内置的component组件,配合is属性
- 如何切换?
- 改变is属性的值,为要显示的组件名即可
<template>
<div>
<button @click="comName = 'UserInfo'">账号密码填写</button>
<button @click="comName = 'UserName'">个人信息填写</button>
<p>下面显示注册组件-动态切换:</p>
<div style="border: 1px solid red;">
<component :is="comName"></component>
</div>
</div>
</template>
<script>
import UserName from '@/components/UserName.vue';
import UserInfo from '@/components/UserInfo.vue';
export default {
data() {
return {
comName: "UserName"
}
},
components: {
UserName,
UserInfo
}
}
</script>
<style></style>
组件缓存
vue内置的keep-alive组件 包起来要频繁切换的组件
<div style="border: 1px solid red;">
<!-- vue组件内置Keep-alive组件,把包起来的组件缓存起来 -->
<keep-alive>
<component :is="comName"></component>
</keep-alive>
</div>
缓存后的组件可以避免被频繁创建和销毁
组件缓存-激活钩子函数
如何知道缓存的组件是出现了还是消失了
- 方法名:
- activated - 激活时触发
- deactivated - 失去激活状态触发
<script>
export default {
activated() {
console.log("02-UserName-激活");
},
deactivated() {
console.log("02-UserName-失去激活");
}
}
</script>
插槽
组件插槽
当组件内某一部分标签不确定怎么办?
- 用插槽技术
插槽具体如何使用?
1.组件内用<slot></slot>
占位
2.使用组件时<Pannel></Pannel>
夹着的地方,传入标签替换slot
插槽运行效果?
传入的标签会替换掉slot显示
<template>
<div id="container">
<div id="app">
<h3>案例:折叠面板</h3>
<Pannel>
<span>我是内容</span>
</Pannel>
<Pannel></Pannel>
<Pannel></Pannel>
</div>
</div>
</template>
<template>
<div class="title">
<h4>芙蓉楼送辛渐</h4>
<span class="btn" @click="isShow = !isShow">
{{ isShow ? "收起" : "展开" }}
</span>
<!-- 下拉内容 -->
<div class="container" v-show="isShow">
<slot></slot>
<p>寒雨连江夜入吴</p>
<p>平明送客楚山孤</p>
<p>寒雨连江夜入吴</p>
<p>平明送客楚山孤</p>
</div>
</div>
</template>
作用域插槽
目标:使用插槽时,想使用子组件内变量
口诀:
子组件,在slot上绑定属性和子组件内的值
使用组件,传入自定义标签,用template和v-slot=’自定义变量名‘
scope变量明自动绑定slot上所有属性和值
scpoe = {row:defaultObj}
<template>
<div class="title">
<h4>芙蓉楼送辛渐</h4>
<span class="btn" @click="isShow = !isShow">
{{ isShow ? "收起" : "展开" }}
</span>
<!-- 下拉内容 -->
<div class="container" v-show="isShow">
<slot :row="defaultObj">{{ defaultObj.defaultOne }}</slot>
<p>寒雨连江夜入吴</p>
<p>平明送客楚山孤</p>
</div>
</div>
</template>
<script>
//目标:组件插槽的使用 - 为了让疯转的组件显示不同的标签结构(灵活)
export default {
data() {
return {
isShow: false,
defaultObj: {
defaultOne: "无名氏",
defaultTwo: "哮喘退学"
}
}
}
}
</script>
<template>
<div id="container">
<div id="app">
<h3>案例:折叠面板</h3>
<Pannel>
<!-- 需求:插槽时,使用组件内变量
scope变量:{row:defaultObj} -->
<template v-slot="scope">
<p>{{ scope.row.defaultTwo }}</p>
</template>
</Pannel>
<Pannel></Pannel>
</div>
</div>
</template>
Vue路由
路由重定向
路由重定向指的是:用户在访问地址A的时候,强制用户跳转到地址C,从而展示特定的组件页面
import { createRouter, createWebHashHistory } from "vue-router";
import Home from "./components/MyHome.vue";
import Movie from "./components/MyMovie.vue";
const router = createRouter({
history: createWebHashHistory(),
routes: [
//其中,path 表示需要被重定向的’原地址‘,
// redirect 表示将要被重定向到的’新地址‘
{ path: "/", redirect: "/home" },
{
path: "/home",
component: Home,
},
{
path: "/moive",
component: Movie,
},
],
});
export default router;
嵌套路由
在Movie组件中,声明tab1 的子路由连接以及子路由占位符
<template>
<div>
<p>MyMovie组件</p>
<router-link to="/movie/tab1">tab1</router-link>
<router-view></router-view>
</div>
</template>
通过 children 声明子路由规则
const router = createRouter({
history: createWebHashHistory(),
routes: [
//其中,path 表示需要被重定向的’原地址‘,
// redirect 表示将要被重定向到的’新地址‘
// { path: "/", redirect: "/home" },
{
path: "/home",
component: Home,
},
{
path: "/movie",
component: Movie,
children: [
{ path: "tab1", component: Tab1 },
// { path: "tab2", component: Tab2 },
],
},
// {
// path: "*",
// component: NotFound,
// },
],
});