目录
ref 引用
获取 DOM 元素
引用组件实例
初步实现按钮和文本框的按需展示
this.$nextTick 的应用场景
updated 不可用的原因
数组方法
some 循环
foreach 循环
some 循环
every 循环
reduce 基本用法
reduce 简化写法
jQuery 简化了程序员操作 DOM 的过程
在 vue 中,程序员不需要操作 DOM,只需要将数据维护好即可。即数据驱动视图
在 vue 项目中,不建议安装和使用 jQuery
当 vue 项目中,需要进行?DOM 操作时,则需要拿到页面上某个 DOM 元素的引用
ref 引用
用来辅助开发者在不依赖于 jQuery 的情况下,获取 DOM 元素或组件的引用
每一个 vue 的组件实例上,都包含一个 $refs 对象,里面存储着对应的 DOM 元素或组件的引用
默认情况下,组件的 $refs 指向一个空对象
获取 DOM 元素
- 通过 ref 指定的引用名,可以获取 dom 元素
- ref 指定的引用名必须唯一,类似于 id 选择器
<template>
<div class="app-container">
<!-- 通过 ref 指定的引用,可以获取 dom 元素 -->
<!-- 相当于 id 或者 class 等选择器 -->
<!-- ref 指定的引用名不能重名,类似于 id 选择器 -->
<h1 ref="myh1">App 根组件</h1>
<button @click="showThis">打印 this</button>
</div>
</template>
<script>
export default {
methods: {
showThis() {
// this 是当前 app 组件的实例对象
// console.log(this.$refs.myh1);
this.$refs.myh1.style.color = 'red';
}
},
}
</script>
引用组件实例
- 在 App.vue 组件中,对 Left 组件标签设置 ref 引用,即可通过 App.vue 组件的 this 获取? Left.vue 中的实例对象,进而获取组件的数据和方法
<!-- 被引用组件 Left.vue -->
<template>
<div class="left-container">
<h3>Left 组件 --- {{ count }}</h3>
<button @click="count++">+1</button>
<button @click="resetCount">重置</button>
</div>
</template>
<script>
export default {
data() {
return {
count: 0,
}
},
methods: {
resetCount() {
this.count = 0;
}
},
}
</script>
<template>
<div class="app-container">
<h1>App 根组件</h1>
<button @click="showThis">打印 this</button>
<button @click="onReset">重置 Left 组件的 count 值</button>
<hr />
<div class="box">
<!-- 渲染 Left 组件和 Right 组件 -->
<!-- 当组件标签添加 ref 引用之后,即可通过 app.vue 的 this 获取该组件标签所代表的组件的实例对象 -->
<Left ref="comLeft"></Left>
</div>
</div>
</template>
<script>
import Left from "@/components/Left.vue"
export default {
methods: {
// 点击按钮,重置 Left 组件的 count 值
onReset() {
// this.$refs.comLeft.resetCount();
this.$refs.comLeft.count = 0;
}
},
components: {
Left,
}
}
</script>
初步实现按钮和文本框的按需展示
<template>
<div class="app-container">
<!-- @blur 失去焦点,展示按钮 -->
<input type="text" v-if="inputVisible" @blur="showButton">
<button v-else @click="showInput">展示输入框</button>
</div>
</template>
<script>
export default {
data() {
return {
// 控制输入框和按钮的按需展示
// 默认值为 false,表示默认展示按钮,隐藏输入框
inputVisible: false,
}
},
methods: {
// 点击按钮,展示输入框
showInput() {
this.inputVisible = true;
},
showButton() {
this.inputVisible = false;
}
},
}
</script>
this.$nextTick 的应用场景
- 上述案例中,为了让文本框展示后自动获得焦点
- 当数据发生改变时,该数据并没有立刻渲染到 DOM 结构中,此时使用更新后的某些 DOM 元素的引用将会报错(因为此时该元素还未被渲染到 DOM 结构中)
- 组件的 $nextTick(cb) 方法,会把 cb 回调推迟到下一个 DOM 更新周期之后执行
- 通俗的理解是:等组件的 DOM 更新完成之后(updated 之后),再执行 cb 回调函数
- 从而保证 cb 回调函数可以操作到最新的 DOM 元素
<template>
<div class="app-container">
<!-- 引用名最好以 Ref 结尾,维护较方便 -->
<input type="text" v-if="inputVisible" @blur="showButton" ref="iptRef">
<button v-else @click="showInput">展示输入框</button>
</div>
</template>
<script>
export default {
methods: {
// 点击按钮,展示输入框
showInput() {
// 切换 boolean 值,让文本框展示出来
this.inputVisible = true;
// 这行代码执行完毕之后,页面还未更新,文本框将要却还没有展示出来
// 页面上看到的还是 button,input 还未展示
// 因此 iptRef 还处于 undefined
// this.$refs.iptRef.focus();
// console.log(this.$refs.iptRef); // undefined
this.$nextTick(() => {
this.$refs.iptRef.focus();
});
},
},
}
</script>
updated 不可用的原因
- 在上述场景中,点击之后,相应的 DOM 元素发生改变
- 是在特定条件下发生的
- 而 updated 只要数据发生改变就会自动触发
- 生命周期函数必须和 data、methods 平级
<script>
export default {
updated() {
this.$nextTick(() => {
this.$refs.iptRef.focus();
});
},
}
</script>
updated 在数据发生改变时必被触发,当 inputVisible 值改变为?true 之时,updated 随数据的改变而被触发,文本框展示,自动获得焦点
当我们将鼠标移开之后,本应将文本框隐藏,按钮展示。但此时,inputVisible 的值再次发生改变,此时 updated 再次被触发,自动获得焦点。这与我们原本的设定发生矛盾,程序报错
数组方法
some 循环
foreach 循环
- foreach 循环只要开始,即使找到了目标元素,也不会中途终止循环,而是会继续将循环执行完毕
<script>
const arr = ["关羽", "张飞", "赵云", "马超", "黄忠"];
// foreach 循环只要开始,即使找到目标元素,还会继续将循环执行完毕
// 效率较差
arr.forEach((item, index) => {
console.log('ok');
if (item === '张飞') {
console.log(index);
}
});
</script>
some 循环
- some 循环在找到目标元素之后,通过 return true; 固定语法可以立刻终止循环
<script>
const arr = ["关羽", "张飞", "赵云", "马超", "黄忠"];
arr.some((item, index) => {
console.log('ok');
if (item === '张飞') {
console.log(index);
// 找到目标元素之后,通过 return true 终止 some 循环
// return true; 固定写法
return true;
}
});
</script>
every 循环
- 只有当数组中的每一项都满足条件时,才返回 true;否则返回 false
<script>
const arr = [{
id: '1',
name: '张三',
state: true
}, {
id: '2',
name: '张四',
state: true
}, {
id: '3',
name: '张五',
state: false,
}, ];
// every 循环:只有数组中的每一项都满足要求,返回 true
// 只要有一项不满足要求,返回 false
// 判断数组中所有的项是否都被选中
const result = arr.every(item => item.state);
console.log(result);
</script>
reduce 基本用法
<script>
// reduce 语法
arr.filter(item => item.state).reduce((累加结果, 当前循环项) => {}, 初始值);
</script>
<script>
const arr = [{
id: '1',
name: '香蕉',
state: true,
price: 3,
count: 1
}, {
id: '2',
name: '苹果',
state: true,
price: 8,
count: 2
}, {
id: '3',
name: '西瓜',
state: false,
price: 2,
count: 3
}, ];
// 把购物车中已选中的水果(state=true),总价累加起来
// let amt = 0; // 总价
// arr.filter(item => item.state).forEach(item => {
// amt += item.price * item.count;
// });
// console.log(amt);
// reduce 方法
// arr.filter(item => item.state).reduce((累加结果, 当前循环项) => {}, 初始值);
const result = arr.filter(item => item.state).reduce((amt, item) => {
return amt += item.price * item.count;
}, 0);
console.log(result);
</script>
reduce 简化写法
<script>
// reduce 语法
// arr.filter(item => item.state).reduce((累加结果, 当前循环项) => {}, 初始值);
// 简化写法
const result = arr.filter(item => item.state).reduce((amt, item) => amt += item.price * item.count, 0);
console.log(result);
</script>
|