目录
一、属性监听器(面试)
watch:{x(){}}
中的方法名必须跟要监听的data中的属性名一样,才代表监听指定属性
当侦听器监听的属性发生变化时,就会调用watch中对应的方法
侦听器属性,比计算属性计算效率消耗大
new Vue({
el:"",//关联界面元素
data:{x:12},//vm的数据源
methods:{},//方法
filter:{},//过滤器
computed:{xx(){}}, //xx就是一个计算属性
watch:{x(){}} //x就是监听了data中的x属性的一个监听器
})
用法:
<div id='app'>
<p>{{n}}</p>
<button @click="change1">修改n</button>
<p>{{obj.age}}</p>
<button @click="change2">修改obj</button>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
n: 100,
obj: {
age: 20
}
},
methods: {
change1() {
console.log("点击事件触发了")
this.n = "修改了"
},
change2() {
// this.obj.age="修改了引用数据内部的属性值:页面会重新渲染,但是侦听器属性不会触发"
// this.obj={age:"只有修改了引用数据的引用 才能触发侦听器属性"}
this.obj.age = "修改了引用数据内部的属性值也想触发侦听器属性,必须深度监听"
}
},
watch: {//侦听器属性:必须和data中的数据源同名
n() {
console.log(666666666)
},
// obj(){
// console.log("obj改变了")
// }
obj: { //这就是深度监听,上面改变this.obj.age,这个属性监听器也会触发
//其实这样设计不好
deep: true,
handler: () => {
console.log("obj改变了")
}
}
}
})
</script>
案例一:汇率换算
<div id='app'>
RMB:<input type="text" v-model="rmb">
doller:<input type="text" v-model="doller">
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
rmb:0,
doller:0
},
methods: {},
watch:{
rmb(newvalue,oldvalue){
console.log(arguments) //会打印两个值,原来的值和新的值
this.doller=(newvalue/6.9).toFixed(2)*100/100
},
doller(newvalue,oldvalue){
this.rmb=newvalue*6.9
}
}
})
</script>
案例二:消费余额提示
<div id='app'>
<p>{{money}}</p>
<button @click="fn">消费</button>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
money:100
},
methods: {
fn(){
this.money-=5
}
},
watch:{
money(newv,oldv){
if(newv<30){
alert("发短信还给用户:只剩30了不到了")
}
}
}
})
</script>
案例三:播放进度条监听
<style type="text/css">
.slider{
width:400px;
height: 20px;
background-color: skyblue;
position: relative;
left: 100px;
top: 100px;
border-radius: 10px;
}
.sliderbar{
width:30px;
height: 30px;
border-radius: 50%;
background-color:cadetblue;
position: relative;
top: -5px;
}
</style>
<div id='app'>
进度条:{{total-currenttime|timerparser}}
<div class="slider">
<div class="sliderbar" :style="{left:x}"></div>
</div>
<button @click="start">start</button>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
currenttime:0,
total:242,
x:0,
maxwidth:370
},
methods: {
start(){
this.timer=setInterval(()=>{
this.currenttime+=0.1
},100)
}
},
filters:{
timerparser(arg){
return ` ${parseInt(arg/60).toString().padStart(2,"0")}:${parseInt(arg%60).toString().padStart(2,"0")}`
}
},
watch:{
currenttime(value){
this.x=this.maxwidth*value/this.total+"px"
if(value>=60){
clearInterval(this.timer)
alert("试听结束")
}
}
}
})
</script>
二、自定义指令(面试)
除了默认设置的核心指令( v-model 和 v-show 等),Vue 也允许注册自定义指令。
在Vue里,代码复用的主要形式和抽象是组件。
有的情况下,仍然需要对纯 DOM 元素进行底层操作,这时候就会用到自定义指令 。
指令:Vue中指令就是标签中V-开始的一种自定义的标签的属性,它在Vue运行了以后,就具有封装好的功能,使用时非常简洁
以一个input元素自动获得焦点为例,当页面加载时,使用autofocuse可以让元素将获得焦点 ,但是autofocuse在移动版Safari上不工作,现在注册一个使元素自动获取焦点的指令。
指令注册类似于组件注册,包括全局指令和局部指令两种。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="https://lf9-cdn-tos.bytecdntp.com/cdn/expire-1-M/vue/2.6.14/vue.js"></script>
</head>
<body>
<div id="app">
<p v-html="msg"></p>
<input v-red type="text" v-model="count" v-focus/>
<div v-red>hello</div> <!-- 变为红色 -->
<h2 v-color="'blue'">123</h2> <!-- v-color="blue"中的blue是一个变量,要为字符串需要用引号引起来 -->
<h2 v-color="'gold'">123</h2>
<p v-color="mycolor">123</p>
<input type="text" >
</div>
<script>
var vm = new Vue({
el: "#app",
data: {
msg: "<b>hello</b>",
count: 123,
mycolor:"grey"
},
methods: {
},
directives: {
red: {
inserted(el) {
console.log(el) //绑定这个指令的节点对象:DOM
el.style.color = "red"
}
},
color: {
inserted(el, option) { //option是一个对象
el.style.color = option.value
}
},
focus:{
inserted(el){
el.focus()
}
}
}
})
</script>
</body>
</html>
案例:Echarts
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src='https://lf9-cdn-tos.bytecdntp.com/cdn/expire-1-M/vue/2.6.14/vue.js'></script>
<script src="https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/echarts/5.3.0-rc.1/echarts.js"></script>
</head>
<body>
<style type="text/css">
.box {
width: 600px;
height: 600px;
}
</style>
<div id='app'>
<div class="box" style="width:600px;height:600px;" v-echarts>
</div>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
},
methods: {},
directives: {
echarts: {
bind(el) {
var myChart = echarts.init(el);
let options = {
title: {
text: 'Referer of a Website',
subtext: 'Fake Data',
left: 'center'
},
tooltip: {
trigger: 'item'
},
legend: {
orient: 'vertical',
left: 'left'
},
series: [{
name: 'Access From',
type: 'pie',
radius: '50%',
data: [{
value: 1048,
name: 'Search Engine'
},
{
value: 735,
name: 'Direct'
},
{
value: 580,
name: 'Email'
},
{
value: 484,
name: 'Union Ads'
},
{
value: 300,
name: 'Video Ads'
}
],
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
}]
}
myChart.setOption(options)
}
}
}
})
</script>
</body>
</html>
1)全局指令
// 注册一个全局自定义指令 v-focus Vue.directive('focus', { // 当绑定元素插入到 DOM 中。 inserted: function (el) { // 聚焦元素 el.focus() } })
2)局部指令
var vm = new Vue({ el: '#app', directives:{ focus:{ inserted: function (el) { el.focus() } } } })
在模板中任何元素上使用新的 v-focus 属性
<div id="app"> <input v-focus> </div>
3)钩子函数
指令定义函数提供了几个钩子函数(可选) 。
【bind】
只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个在绑定时执行一次的初始化动作。
【inserted】
被绑定元素插入父节点时调用(父节点存在即可调用,不必存在于 document 中)。
【update】
所在组件的 VNode 更新时调用,但是可能发生在其孩子的 VNode 更新之前。指令的值可能发生了改变也可能没有。但是可以通过比较更新前后的值来忽略不必要的模板更新。
当前所在组件更新的时候,这个函数才运行
【componentUpdated】
所在组件的 VNode 及其孩子的 VNode 全部更新时调用。
【unbind】
只调用一次, 指令与元素解绑时调用。
注意区别:
bind与inserted:bind时父节点为null,inserted时父节点存在;
update与componentUpdated:update是数据更新前,componentUpdated是数据更新后。
4)钩子函数参数
【el】
指令所绑定的元素,可以用来直接操作 DOM。
【binding】
一个对象,包含指令名称及该指令所绑定的表达式信息。
里面有name、value、oldvalue等等
【vnode】
Vue 编译生成的虚拟节点。
【oldVnode】
上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。
注意:除了 el 之外,其它参数都是只读的,尽量不要修改他们。如果需要在钩子之间共享数据,建议通过元素的 dataset 来进行。
<div id='app'>
<p v-hqyj="red" @click="change1">hello</p>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
red:"rgb(255,0,0)"
},
methods: {
change1(){
this.red="rgb(200,0,0)"
}
},
directives:{
hqyj:{
bind(){
console.log("bind")
},
inserted(el,binding){
var v=binding.value
console.log(v)
},
update(){
console.log("update")
},
componentUpdated(){
},
unbind(){
}
}
}
})
</script>
5)函数简写
大多数情况下,可能想在bind和update钩子上做重复动作,并且不想关心其它的钩子函数。可以这样写:
<div v-demo="{ color: 'white', text: 'hello!' }"></div> Vue.directive('demo', function (el, binding) { console.log(binding.value.color) // => "white" console.log(binding.value.text) // => "hello!" })
三、nextTick
学习了生命周期之后,会有一个问题:我们在写业务的时候,写的业务代码能否操作vm
所以需要一个工具,让我们写的diamagnetic,无论在哪里写,都希望它是组件加载完了以后才运行
这个函数的回调函数是在组件加载完了才会执行
<div id='app'>
<p>{{msg}}</p>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
msg:"hello"
},
methods: {},
beforeCreate(){
//这个函数的回调函数是在组件加载完了才会执行
this.$nextTick(()=>{
console.log(this.msg)
})
}
})
</script>
==>这个函数就可以解决上面ECharts案例
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src='https://lf9-cdn-tos.bytecdntp.com/cdn/expire-1-M/vue/2.6.14/vue.js'></script>
<script src="https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/echarts/5.3.0-rc.1/echarts.js"></script>
</head>
<body>
<style type="text/css">
.box {
width: 600px;
height: 600px;
}
</style>
<div id='app'>
<div class="box" v-echarts>
</div>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {},
methods: {},
directives: {
echarts: {
inserted(el) {
Vue.nextTick(()=>{
var myChart = echarts.init(el);
let options={
title: {
text: 'Referer of a Website',
subtext: 'Fake Data',
left: 'center'
},
tooltip: {
trigger: 'item'
},
legend: {
orient: 'vertical',
left: 'left'
},
series: [{
name: 'Access From',
type: 'pie',
radius: '50%',
data: [{
value: 1048,
name: 'Search Engine'
},
{
value: 735,
name: 'Direct'
},
{
value: 580,
name: 'Email'
},
{
value: 484,
name: 'Union Ads'
},
{
value: 300,
name: 'Video Ads'
}
],
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
}]
}
myChart.setOption(options)
})
}
}
}
})
</script>
</body>
</html>