vue2+vue3
2024/3/21
v-model的三种修饰符:
lazy
lazy 修饰符:使模型绑定的数据只有在失去焦点或者是按下回车时才会更新
<input type="text" id="inp" v-model.lazy="message">
numer
number 修饰符: 使输入框中输入的内容自动转换为数字类型
<input type="text" name="" id="age" v-model.number="age">
trim
trim 修饰符:
1.只去除两端空格
<el-input v-model.trim = "data"><el-input>
2.只要有空格就去除
<el-input v-model.trim = "data" @keyup.native="trim('data')"><el-input>
trim(v) {
this[v] = this[v].replace(/\s+/g, '')
},
或者
<el-input v-model = "data" oninput="value = value.replace(/\s/g, '')"><el-input>
v-on修饰符:prevent 、stop
prevent:阻止a标签的默认行为 stop:阻止事件冒泡
<a href="https://www.baidu.com" @click.prevent.stop="fn">百度</a>
按键修饰符keyup、keydown
@keyup.enter 监听回车键
@keyup.esc 监听返回键
<input type="text" @keyup.enter="fn"><button>发送</button>
Tip:一般用keyup事件而不用keydown事件,因为keyup事件只触发一次,如果按住键盘不松开keydown事件就会一直触发
v-for中的key值
简单来说key是给每一个vnode的唯一id,同时也是diff的一种优化策略,可以根据key,更准确, 更快的找到对应的vnode节点
<div v-for="(item, index) in list" :key="index" >{{item.name}}</div>
2024/3/22
computed 计算属性 vs methods 方法
计算属性完整写法
computed: {
计算属性名: {
get() {
//一段代码逻辑(计算逻辑)
return 结果
},
set(修改的值) {
//一段代码逻辑(修改逻辑)
}
}
}
watch侦听器语法
简单写法
watch:{
数据属性名(newValue,oldValue){
一些业务逻辑或异步操作
}
'对象.属性名'(newValue,oldValue){
一些业务逻辑或异步操作
}
}
vue中watch监听对象中某个属性
例子:通过input输入框触发watch
<input v-model="currentParams.selOrgId" />
data(){
return {
currentParams: {
selOrgId: '1',//声明不声明都可以触发watch
},
}
},
watch: {
//使用 ''
'currentParams.selOrgId': (newV, oldV) => {
console.log("watch", newV, oldV)
},
},
完整写法
添加配置项
- deep:true 对复杂类型深度监听
- immediate:true 初始化立刻执行一次handler方法
watch: {
obj: {
deep: true, //深度监听
immediate: true, //立刻执行
handler(newValue) {
console.log('被修改了', newValue);
}
}
}
防抖
延迟执行,一段时间内没有再次执行,才触发,触发了相当于重新计时
clearTimeout(this.timer)
this.timer = setTimeout(async() => {
const res = await axios({
url: '',
params: {
words: newValue
}
})
this.res = res.data.data
}, 300);
reduce累加统计
let total = this.list.reduce((sum, item) => sum + item.num, 0)
every判断全选
this.fruitList.every(item => item.isChecked)
2024/3/23
Vue生命周期
四个阶段:①创建 ②挂载 ③更新 ④销毁
input初始化获取焦点
<input autofocus type="text" v-model="words" id="inp">
在vue中使用
document.querySelector('#inp').focus()
脚手架CLI
使用步骤
脚手架目录文件介绍
main.js核心代码
让组件支持less
组件注册使用
普通组件注册的两种方式
1.局部注册
①创建.vue文件(三个部分组成:结构 样式 行为)
②在使用的组件内导入,并局部注册 components:{组件名:组件对象}
2.全局注册
所有组件内部都能使用
①创建.vue文件
②main.js内导入,并进行全局注册 Vue.component(组件名,组件对象)
vscode配置trigger on tab
设置中搜索trigger on tab 并勾选
vscode所有都折叠
ctrl+k,ctrl+0
vscode所有都展开
ctrl+k,ctrl+j
2024/3/25
scoped解决组件的样式冲突
<style scoped>
/* 加上scoped属性的style样式,指挥作用于当前组件->局部样式 */
/*
默认情况:写在组件中的样式会 全局生效 → 因此很容易造成多个组件之间的样式冲突问题。
1. 全局样式: 默认组件中的样式会作用到全局
2. 局部样式: 可以给组件加上 scoped 属性, 可以让样式只作用于当前组件
-----------------------------------------------------
scoped原理:
1. 当前组件内标签都被添加 data-v-hash值 的属性
2. css选择器都被添加 [data-v-hash值] 的属性选择器
最终效果: 必须是当前组件的元素, 才会有这个自定义属性, 才会被这个样式作用到
*/
</style>
组件通信
两种组件关系分类 和 对应的组件通信方案
父子关系 → props & $emit
非父子关系 → provide & inject 或 eventbus
eventbus具体用法 :(是一个一对多的关系)
provide&inject具体用法 :(数据类型推荐使用复杂类型)
通用方案 → vuex

使用步骤:
state状态
提供数据
// 创建仓库
const store = new Vuex.Store({
// state 状态, 即数据, 类似于vue组件中的data
// 区别:
// 1. data 是组件自己的数据
// 2. state 是所有组件共享的数据
state: {
count: 101
}
})
访问数据
模板中: {{ $store.state.xxx }}组件逻辑中: this.$store.state.xxxJS模块中: store.state.xxx
辅助函数 mapState
mutations

mutations传参语法
注意:提交的参数只能是一个, 如果有多个参数要传, 可以传递一个对象
mutations: {
...
addCount (state, obj) {
state.count += obj.count
}
},
this.$store.commit('addCount', {
count: 10
})
辅助函数 mapMutations
actions

辅助函数 - mapActions

核心概念 - getters
辅助函数 mapGetters

模块 module (进阶语法)

访问模块中的state
访问模块中的getters
访问模块中 mutation

props校验
作用:为组件的 prop 指定验证要求,不符合要求,控制台就会有错误提示 → 帮助开发者,快速发现错误
①基础写法
props: {
校验的属性名: 类型 // Number String Boolean ...
},
②完整写法
对数据的类型、非空、默认值、自定义校验
props: {
校验的属性名: {
type: 类型, // Number String Boolean ...
required: true, // 是否必填
default: 默认值, // 默认值
validator (value) {
// 自定义校验逻辑
return 是否通过校验
}
}
},
console.error
向 Web 控制台输出一条错误消息。
prop&data
v-model原理
<template>
<div class="app">
<input v-model="msg1" type="text" />
<br />
<!-- v-model的底层其实就是:value和 @input的简写 -->
<input :value="msg2" @input="msg2=$event.target.value" type="text" >
</div>
</template>
表单类组件封装
通过v-model简化
.sync修饰符

ref和$refs
<template>
<!-- 1. 目标标签 – 添加 ref 属性 -->
<div ref="mychart" class="base-chart-box">子组件</div>
</template>
<script>
export default {
mounted() {
// 2. 获取dom 通过 this.$refs.xxx, 获取目标标签
console.log(this.$refs.mychart);
},
};
</script>
②获取组件
<template>
<div class="app">
<!-- 1. 目标组件 – 添加 ref 属性 -->
<BaseForm ref="baseForm"></BaseForm>
<button @click="handleGet">获取数据</button>
<button @click="handleReset">重置</button>
</div>
</template>
<script>
import BaseForm from './components/BaseForm.vue'
export default {
components: {
BaseForm,
},
methods: {
handleGet(){
// 2. 通过 this.$refs.xxx, 获取目标组件,就可以调用组件对象里面的方法
this.$refs.baseForm.getFormData()
},
handleReset(){
this.$refs.baseForm.resetFormData()
}
}
}
</script>
Vue异步更新、$nextTick
this.$nextTick(() => {
this.$refs.inp.focus()
});
2023/3/26
自定义指令
全局注册
在多个组件内使用
Vue.directive('指令名', {
"inserted" (el) {
// 可以对 el 标签,扩展额外功能
el.focus()
}
})
局部注册
directives: {
"指令名": {
inserted () {
// 可以对 el 标签,扩展额外功能
el.focus()
}
}
}
指令的值(传值)
<div v-color="color">我是内容</div>
directives: {
color: {
//1. inserted 提供的是元素被添加到页面中时的逻辑
inserted(el, binding) {
el.style.color = binding.value;
},
// 2.update 指令的值修改的时候触发,提供值变化后,dom更新的逻辑
update(el,binding) {
// 指令的值修改了
el.style.color=binding.value
},
},
},
封装v-loading指令
/* 伪类 - 蒙层效果 */
.loading:before {
content: "";
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background: #fff url("./loading.gif") no-repeat center;
}
(2) 添加或移除类名,实现loading蒙层的添加移除
directives: {
//inserted 钩子中,binding.value 判断指令的值,设置默认状态
//update 钩子中,binding.value 判断指令的值,更新类名状态
loading: {
inserted(el, binding) {
binding.value
? el.classList.add("loading")
: el.classList.remove("loading");
},
update(el, binding) {
binding.value
? el.classList.add("loading")
: el.classList.remove("loading");
},
},
},
(3) 利用指令语法,封装 v-loading 通用指令
<div class="box" v-loading="isLoading">
</div>
插槽
作用:让组件内部的一些 结构 支持 自定义
默认插槽

插槽-后备内容
给插槽设置 默认显示内容

具名插槽

作用域插槽
是插槽的一个传参语法,定义 slot 插槽的同时, 是可以传值的。
作用:给 插槽 上可以 绑定数据,将来 使用组件时可以用。
使用步骤:
<slot :row="item" msg="测试文本"></slot>
{
"row": {
"id": 1,
"name": "张小花",
"age": 18
},
msg: "测试文本"
},
<template>
<div>
<MyTable :data="list">
<template #default="obj">
<button @click="del(obj.row.id)">删除</button>
</template>
</MyTable>
<MyTable :data="list2">
<template #default="{ row }">
<button @click="show(row)">查看</button>
</template>
</MyTable>
</div>
</template>
单页应用程序
所有功能在一个html页面上实现
优点:按需更新性能高,开发效率高,用户体验好(页面按需更新)
路由
VueRouter 的 介绍
VueRouter 的 使用 (5 + 2)
Vue2 VueRouter3.x Vue3.x
Vue3 VueRouter4.x Vue4.x
5个基础步骤 (固定)
① 下载: 下载 VueRouter 模块到当前工程,版本3.6.5
yarn add vue-router@3.6.5
import VueRouter from 'vue-router'
③安装注册
Vue.use(VueRouter)
④创建路由对象
const router = new VueRouter()
⑤注入,将路由对象注入到new Vue实例中,建立关联
new Vue({
render: h => h(App),
router
}).$mount('#app')

组件存放目录问题

2024/3/27
路由的封装抽离
main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router/index'
Vue.config.productionTip = false
new Vue({
render: h => h(App),
router
}).$mount('#app')
index.js
import Find from '@/views/Find'
import My from '@/views/My'
import Friend from '@/views/Friend'
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const router = new VueRouter({
routes: [
{ path: '/find', component: Find },
{ path: '/my', component: My },
{ path: '/friend', component: Friend },
]
})
export default router
声明式导航
router-link

两个类名
a.router-link-active {
background-color: purple;
}
定制高亮类名
const router = new VueRouter({
routes: [...],
linkActiveClass: "类名1",
linkExactActiveClass: "类名2"
})
路由传参
1.查询参数传参(比较适合传多个参数)
2.动态路由传参(优雅简洁,传单个参数比较方便)
const router = new VueRouter({
routes: [
...,
{
path: '/search/:words',
component: Search
}
]
})
const router = new VueRouter({
routes: [
{ path: '/', redirect: '/home' },
{ path: '/home', component: Home },
{ path: '/search/:words?', component: Search }
]
})
路由重定向
const router = new VueRouter({
routes: [
{ path: '/', redirect: '/home'},
{ path: '/home', component: Home },
{ path: '/search/:words', component: Search }
]
})
配置404页面
import NotFind from '@/views/NotFind'
const router = new VueRouter({
routes: [
{ path: '/', redirect: '/home' },
{ path: '/home', component: Home },
{ path: '/search/:words?', component: Search },
{ path: '*', component: NotFind }
]
})
Vue路由 - 模式设置
const router=new VueRouter({
routes,
mode:"history"
})
路由跳转方式
this.$router.push('路由路径')
this.$router.push({
path: '路由路径'
})
this.$router.push({
name: '路由名'
})
{ name: '路由名', path: '/path/xxx', component: XXX },
跳转传参

2. name 命名路由跳转
组件缓存 keep-alive
<template>
<div class="h5-wrapper" :include="['LayoutPage']>
<keep-alive >
<router-view></router-view>
</keep-alive>
</div>
</template>
activated () {
console.log('actived 激活 → 进入页面');
},
deactivated() {
console.log('deactived 失活 → 离开页面');
}