Vue2.x笔记
# 实例方法-数据
this.$set(this.obj, "属性", 值); //添加、修改属性
this.$delete(this.obj, "属性"); //删除属性
# Vue 过滤器(搭配 el-table 使用)
<template slot-scope="scope">
<div :style="scope.row.type">
{ {scope.row.type | licenseType} }
</div>
</template>
//过滤器
filters: {
licenseType: function (type) {
switch (type) {
case '0':
return 'value'
break;
case '1':
return 'value'
break;
...
default:
break;
}
}
},
# Vue 组件注册
vue 中注册组件的方式分为全局注册
和局部注册
两种,其中:被全局注册的组件,可以在全局任何一个组件内使用,被局部注册的组件,只能在当前注册的范围内使用。
- 使用
app.component()
方法注册的全局组件,直接以标签的形式进行使用
import { createApp } from "vue";
import App from "./App.vue";
import Test from "./components/Test.vue";
const app = createApp(App);
app.component("Test", Test);
app.mount("#app");
- 局部注册
<script>
import Test from './components/Test.vue'
export default {
name: 'App',
components: { // 通过 component 节点,为当前组件注册私有子组件
Test
}
}
</script>
- 通过
name
属性注册组件
// 当前组件名称
<script>
export default {
name: "Test",
};
</script>
// 注册时
import Test from './components/Test.vue'
app.component(Test.name,Test)
# /deep/ 样式穿透
如果给当前组件的 style
节点添加了 scoped
属性,则当前组件的样式对其子组件是不生效的。如果想让某些样式对子组件生效,可以使用 /deep/
深度选择器。
注意:/deep/
是 vue2.x
中实现样式穿透的方案,在 vue3.x
中推荐使用 :deep()
替代 /deep/
。
<style scoped>
/* 不加 /deep/ 时,生成的选择器格式为 .title[data-v-xxxx] */
.title{
color: pink;
}
/* 不加 /deep/ 时,生成的选择器格式为 [data-v-xxxx] .title */
/* vue2.x中 */
/deep/ .title{
color: pink;
}
/* vue3.x中 */
:deep(.title){
color: pink;
}
</style>
# Vue 侦听器的使用
watch
侦听器允许开发者监视数据的变化,从而针对数据的变化做特定的操作。
watch 侦听器的基本语法
export default {
data() {
return {
userName: "",
};
},
watch: {
/**
* 监听 userName 的值的变化
* newVal 表示变化后的新值,oldVal表示变化前的旧值
**/
userName(newVal, oldVal) {
console.log(newVal, oldVal);
},
},
};
watch 侦听器选项
- immediate
默认情况下,组件在初次加载完毕后不会调用 watch
侦听器。如果想让 watch
侦听器立即被调用,则需要使用 immediate
选项。
watch: {
// 监听 userName 值的变化
userName: {
// handler 是固定写法:当 userName 变化时,调用 handler
handler(newVal) {
console.log(newVal)
}
},
// immediate 为 true 表示组价加载完毕后立即调用一次当前的 watch 侦听器
immediate: true
}
- deep
当 watch
侦听的是一个对象,如果 对象中的属性值 发生了变化,则无法被监听到,此时需要使用 deep
选项。
export default {
data() {
return {
userInfo1: {
name: "",
},
userInfo2: {
name: "",
age: "",
},
};
},
watch: {
userInfo1: {
// 直接监听 userInfo1 对象的变化
handler(newVal) {
console.log(newVal);
},
deep: true, // 当 deep 为 true 时,可以监听到 useInfo1中 name 属性的变化
},
/**
* 当监听对象中包含不止一个属性时,比如 userInfo2
* 我们需要监听 userInfo2 中 name 属性的变化
* 使用上面的写法会出现错误:当 userInfo2 中 age 属性变化时也会触发侦听器
* 如果我们只想监听对象中单个属性的变化,可以按照如下方式定义侦听器
**/
"userInfo2.name": {
// 只直接监听 userInfo2.name 属性值的变化
handler(newVal) {
console.log(newVal);
},
},
},
};
# 计算属性 vs 侦听器
计算属性和侦听器侧重的 应用场景不同 :
- 计算属性侧重于监听
多个值
的变化,最终计算并返回一个新值
- 侦听器侧重于监听
单个数据
的变化,最终执行特定的业务处理
,不需要有任何返回值
# Vue 删除(搭配 element-ui 使用)
async del (row) {
const confirmResult = await this.$confirm(
"此操作将永久删除该内容, 是否继续?",
"提示",
{
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}
).catch(err => err);
// 点击确定 返回值为:confirm
// 点击取消 返回值为: cancel
if (confirmResult !== "confirm") {
return this.$message.info("已取消删除");
}
...
},
# Vue 刷新页面
在项目中经常会遇到用户执行完某个操作,改变了某些状态,需要重新刷新页面,以此来重新渲染页面,例如数据的增删改查等。
在 app.vue 中添加如下代码
<template>
<div id="app">
<router-view v-if="isRouterAlive"></router-view>
</div>
</template>
<script>
export default {
name: 'App',
provide () { //父组件中通过provide来提供变量,在子组件中通过inject来注入量。
return {
reload: this.reload
}
},
data() {
return{
isRouterAlive: true //控制视图是否显示的变量
}
},
methods: {
reload () {
this.isRouterAlive = false; //先关闭,
this.$nextTick(()=> {
this.isRouterAlive = true; //再打开
})
}
},
}
</>
在需要刷新页面的组件调用 reload 方法
export default {
inject:['reload'], //注入App里的reload方法
data () {
return {}
},
methods:{
方法:{
this.reload()
}
}
# Vue 路由跳转传参
//path:跳转路径
//query:请求参数
this.$router.push({
path: "/路径名称",
query: { 参数名: JSON.stringify("参数值") },
});
//跳转后页面获取参数
this.赋值对象 = JSON.parse(this.$route.query.参数名);
# 解决 Vue 重复点击路由报错
//在router文件夹下的index.js中加入以下代码
const originalPush = VueRouter.prototype.push;
VueRouter.prototype.push = function push(location) {
return originalPush.call(this, location).catch((err) => err);
};
# Vue 路由跳转缓存
实现需求
1.页面跳转后,回到此页面时,页面不刷新
2.详情页返回至列表页时,数据不刷新,同时浏览位置不改变
实现原理
keep-alive
与vue-router
配合使用
//1.在整个页面框架中需要进行是否缓存的设置
<keep-alive>
<router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive"></router-view>
//2.在路由配置中设置页面是否缓存
path: '/xxxx',
component: xxxx,
meta: {
keepAlive: true,
scollTopPosition: 0
}
//3.记录滚动条
//第一步:定义初始滚动高度
scroll:0
//第二步:mounted中的方法代表dom已经加载完毕
mounted:function(){
window.addEventListener('scroll', this.handleScroll);
},
//第三步:用于存放页面函数
methods:{
handleScroll () {
this.scroll = $(window).height()+ $(document).scrollTop()
}
},
//第四步:当再次进入(前进或者后退)时,只触发activated(注:只有在keep-alive加载时调用)
activated(){
if(this.scroll > 0){
window.scrollTo(0, this.scroll);
window.addEventListener('scroll', this.handleScroll);
}
},
//第五步:deactivated 页面退出时关闭事件 防止其他页面出现问题
deactivated(){
window.removeEventListener('scroll', this.handleScroll);
},
//4.跳转同一页面获取不同数据
//实现方法:watch监听路由
watch: {
"$route": function (n, o) {
console.log('watch', n, o);
}
},
# 深拷贝
问题:
Vue
开发过程中数组新push
一个对象,其他对象也同时被修改
原因:
对象是引用类型,传递的是引用地址,所以两个数组引用的是同一个对象,只要其中一个数组改变,就会导致对象改变,进而另一个引用的数组也会改。
解决方法:
将需要放入数组的对象先深拷贝一份,用拷贝的对象,这样就不存在引用关系了。
1.拷贝:
new_obj = JSON.parse(JSON.stringify(obj));
2.重新申请一个内存空间,然后赋值给他,再push
,实现深拷贝
# Vue 解析 XLSX 文件
vue 框架中上传 xlsx 文件,使用 js-xlsx 解析文件内容
//1.首先执行(安装)
npm install xlsx
//2.在当前页面.vue文件中引入
import XLSX from 'xlsx'
//3.在main.js中引入
import XLSX from '路径'
//4.vue+element:使用element-ui组件(el-upload),在onChange方法中调用读取数据函数(readExcel)
readExcel (e) {
let that = this;
const files = that.fileData;
console.log('files', files);
if (!files) {
//如果没有文件
return false;
} else if (!/\.(xls|xlsx)$/.test(files.name.toLowerCase())) {
this.$message.error("上传格式不正确,请上传xls或者xlsx格式");
return false;
}
const fileReader = new FileReader();
fileReader.onload = ev => {
try {
const data = ev.target.result;
// console.log('data', data)
const workbook = XLSX.read(data, {
type: "binary"
});
console.log('workbook', workbook.SheetNames)
const wsname = workbook.SheetNames[0]; //取第一张表
const ws = XLSX.utils.sheet_to_json(workbook.Sheets[wsname]); //生成json表格内容
console.log('ws', ws);//ws中即为获取到的数据
this.outputs = ws
} catch (e) {
return false;
}
};
// 如果为原生 input 则应是 files[0]
fileReader.readAsBinaryString(files.raw);
},
# Vue 自定义校验
//data中
var checkName = (rule, value, callback) => {
if (!value) {
return callback(new Error("请输入姓名"));
}
setTimeout(() => {
let reg = /^[\u0391-\uFFE5A-Za-z]+$/;
if (!reg.test(value) && value !== "") {
callback(new Error("请输入中文姓名"));
} else {
callback();
}
}, 100);
};
//rules中-validator: + 自定义规则名
name: [{ required: true, validator: checkName, trigger: "blur" }],
# 常用表单校验规则
# Vue 自定义过滤器
# -- 格式化数字三位加一逗号
Vue.filter("NumFormat", function(value) {
if (!value) return "0.00";
var intPart = Number(value) - (Number(value) % 1); //获取整数部(这里是windy93的方法)
var intPartFormat = intPart.toString().replace(/(\d)(?=(?:\d{3})+$)/g, "$1,"); //将整数部分逢三一断
var floatPart = ".00"; //预定义小数部分
var value2Array = value.toString().split(".");
//=2表示数据有小数位
if (value2Array.length == 2) {
floatPart = value2Array[1].toString(); //拿到小数部分
if (floatPart.length == 1) {
//补0,实际上用不着
return intPartFormat + "." + floatPart + "0";
} else {
return intPartFormat + "." + floatPart;
}
} else {
return intPartFormat + floatPart;
}
});