Vue核心知识点(二)
前言
本博客是对以下视频教程做的一个笔记总结,这个笔记和视频不是一一对应的,但可作为参考,不喜勿喷。
2021最新Vue迅速上手教程丨vue3.0入门到精通
本博客是Vue核心知识点的第二篇,第一篇在这儿:Vue核心(一) 。由于内容太多,一篇博客写不完,所以写了**Vue核心知识点(二)**这篇博客。
如果对你有所帮助,欢迎点赞,评论,转发。
这篇博客的主要内容有:
- 指令补充==>自定义指令。
- 指令补充==>局部指令和全局指令。
- 计算和监视属性。
- 过滤器。
- 收集表单数据。
1、自定义指令、局部指令、全局指令
需求1:定义一个v-big 指令,和v-text 功能类似,但会把绑定的数值放大10倍。
需求2:定义一个v-fbind 指令,和v-bind 功能类似,但可以当元素被插入页面时,让其所绑定的input 元素默认获取焦点。
1.1 代码示例
代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<title>自定义指令、全局指令、局部指令</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<div id="root">
<h2>1、数字放大10倍</h2>
<h2>当前的n值是:<span v-text="n"></span></h2>
<h2>放大10倍后的n值是:<span v-big="n"></span></h2>
<button @click="n++">点我n+1</button>
<hr>
<h2>2、当元素被插入页面时,让绑定的input元素默认获取焦点</h2>
<input type="text" v-fbind="n" v-abc v-def>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false;
Vue.directive('abc', {
bind(element, binding) {
console.log("指令和元素成功绑定");
},
inserted(element, binding) {
console.log("指令所在元素被插入页面");
},
update(element, binding) {
console.log("模板中数据发生改变,指令所在模板被重新解析");
}
});
Vue.directive('def', (element, binding) => {
console.log("全局指令---函数式---");
console.log("def指令的value值---" + binding.value);
});
const vm = new Vue({
data() {
return {
n: 1
};
},
directives: {
big(element, binding) {
element.innerText = binding.value * 10;
},
fbind: {
bind(element, binding) {
console.log("指令和元素成功绑定");
element.value = binding.value;
},
inserted(element, binding) {
console.log("指令所在元素被插入页面");
element.focus();
},
update(element, binding) {
console.log("模板中数据发生改变,指令所在模板被重新解析");
element.value = binding.value;
}
}
}
});
vm.$mount('#root');
</script>
</html>
指令参数输出如下:
1.2 总结
自定义指令总结:
-
一、定义语法:
-
局部指令: new Vue({
directives{指令名:回调函数}
})
或者 new Vue({
directives:{指令名:配置对象}
})
-
全局指令: Vue.directive(指令名,配置对象)
或者 Vue.directive(指令名,回调函数)
注意:directives和data,methods等属性是同级的!! -
二、配置对象中常用的3个回调:
bind :指令与元素成功绑定时调用。inserted :指令所在元素被插入页面时调用。update :指令所在模板结构被重新解析时调用。 -
三、备注:
- 指令定义时不加
v- ,但使用时要加v- ; - 指令名如果是多个单词,要使用kebab-case命名方式(小写,多个单词间横线隔开),
- 不要用camelCase(小驼峰)命名。
2、计算属性
案例:姓名案例。
需求:根据姓和名,拼成全名。
如下图:
2.1 姓名案例_插值语法实现
代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<title>姓名案例_插值语法实现</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<div id="root">
姓:<input type="text" v-model="firstName"> <br><br>
名:<input type="text" v-model="endName"> <br><br>
全名:{{firstName}}--{{endName}}
</div>
</body>
<script type="text/javascript">
const vm = new Vue({
data() {
return {
firstName: '张',
endName: '三'
};
}
});
vm.$mount('#root');
</script>
</html>
2.2 姓名案例_methods实现
代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<title>姓名案例_methods实现</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<div id="root">
姓:<input type="text" v-model="firstName"> <br><br>
名:<input type="text" v-model="endName"> <br><br>
全名:{{fullName()}}
</div>
</body>
<script type="text/javascript">
const vm = new Vue({
data() {
return {
firstName: '张',
endName: '三'
};
},
methods: {
fullName() {
return this.firstName + '---' + this.endName;
}
}
});
vm.$mount('#root');
</script>
</html>
2.3 姓名案例_计算属性实现
定义:所谓计算属性是指,要用的属性不存在,要通过已有属性计算得来 。
即:在已有属性的基础上,通过对已有属性的计算,产生一个新的属性。
2.3.1 代码示例
代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<title>姓名案例_计算属性实现</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<div id="root">
姓:<input type="text" v-model="firstName"> <br><br>
名:<input type="text" v-model="endName"> <br><br>
全名:{{fullName}}
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false;
var vm = new Vue({
data() {
return {
firstName: '张',
endName: '三'
};
},
computed: {
fullName: {
get() {
console.log("get...");
console.log(this);
return this.firstName + '-' + this.endName;
},
set(value) {
console.log("set...", value);
const arr = value.split('-');
this.firstName = arr[0];
this.endName = arr[1];
}
}
}
});
vm.$mount('#root');
</script>
</html>
2.3.2 总结
计算属性:
- 定义:要用的属性不存在,要通过已有属性计算得来。
- 原理:底层借助了
Objcet.defineproperty 方法提供的getter 和setter 。 - get函数什么时候执行?
- 初次读取时会执行一次。
- 当依赖的数据发生改变时会被再次调用。
- 优势:与
methods 实现相比,内部有缓存机制(复用),效率更高,调试方便。 - 备注:
- 计算属性最终会出现在
vm 上,直接读取使用即可。 - 如果计算属性要被修改,那必须写
set 函数去响应修改,且set 中要引起计算时依赖的数据发生改变。 - 也就是说,如果在set中没有引起,计算属性所依赖的属性发生变化的话,计算属性也不会发生变化。
3、监视属性
案例:点击按钮,切换天气。
如图:
3.1 天气案例_计算属性实现
代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<title>天气案例_计算属性实现</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<div id="root">
<h2>今天天气很{{weatherInfo}}</h2>
<button @click="isHot=!isHot">切换天气</button>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false;
const vm = new Vue({
data() {
return {
isHot: true,
};
},
computed: {
weatherInfo() {
return this.isHot ? '炎热' : '凉爽';
}
}
});
vm.$mount('#root');
</script>
</html>
3.2 天气案例_监视属性watch
所谓监视,就是监视某些属性的值是否发生了改变,
而监视属性就是为了监视这些属性变化,而设定的一个属性(watch)。
3.2.1 代码示例
代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<title>天气案例_监视属性_watch实现</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<div id="root">
<h2>今天天气很{{weatherInfo}}</h2>
<button @click="changeWeather">切换天气</button>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false;
const vm = new Vue({
data() {
return {
isHot: true,
};
},
methods: {
changeWeather() {
this.isHot = !this.isHot;
}
},
computed: {
weatherInfo() {
return this.isHot ? '炎热' : '凉爽';
}
}
});
vm.$mount('#root');
vm.$watch('isHot', {
immediate: true,
handler(newValue, oldValue) {
console.log('isHot被修改了');
console.log('新值:' + newValue);
console.log('旧值:' + oldValue);
}
});
</script>
</html>
3.2.2 总结
监视属性watch:
- 当被监视的属性变化时, 回调函数自动调用, 进行相关操作。
- 监视的属性必须存在,才能进行监视!!
- 监视的两种写法:
new Vue 时传入watch 配置。- 通过
vm.$watch 监视。 - 监视属性的作用:
- 当所监视的属性的值发生改变时,需要做一些事情(操作),
- 如:向后台发送请求等。
3.3 天气案例_深度监视
watch默认是浅层次的监视(一层),
深度监视是指,如果所监视的属性有多层(对象),
通过深度监视可以监视到属性内部值的变化。
3.3.1 代码示例
代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<title>天气案例_监视属性</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<div id="root">
<h2>今天天气很{{weatherInfo}}</h2>
<button @click="changeWeather">切换天气</button>
<hr/>
<h3>a的值是:{{numbers.a}}</h3>
<button @click="numbers.a++">a++</button>
<h3>b的值是:{{numbers.b}}</h3>
<button @click="numbers.b++">b++</button>
<h3>e: {{numbers.c.d.e}}</h3>
<button @click="numbers={a:666,b:999}">彻底替换掉numbers</button>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false;
const vm = new Vue({
data() {
return {
isHot: true,
numbers: {
a: 1,
b: 2,
c: {
d: {e: 3}
}
}
};
},
methods: {
changeWeather() {
this.isHot = !this.isHot;
}
},
computed: {
weatherInfo() {
return this.isHot ? '炎热' : '凉爽';
}
},
watch: {
numbers: {
deep: true,
handler() {
console.log('numbers变了...');
}
},
isHot(newValue, oldValue) {
console.log('isHot被修改了', newValue, oldValue, this);
}
}
});
vm.$mount('#root');
vm.$watch('numbers.a', {
immediate: true,
deep: true,
handler(newVal, oldVal) {
console.log('a变了...', this);
}
});
vm.$watch('numbers.a', (newValue, oldValue) => {
console.log('a变了...', newValue, oldValue, this);
});
</script>
</html>
3.3.2 总结
-
深度监视:
-
Vue 中的watch 默认不监测对象内部值的改变(一层)。 -
配置deep:true 可以监测对象内部值改变(多层)。 -
监视属性都有简写的形式。 watch: {
//简写
属性名(newValue, oldValue) {
//此处的this是Vue实例对象
console.log('xxx被修改了', newValue, oldValue, this);
}
}
或 //简写
vm.$watch('numbers.a', (newValue, oldValue) => {
//此处的this是window(handler写成箭头函数)
console.log('a变了...', newValue, oldValue, this);
});
-
备注:
Vue 自身可以监测对象内部值的改变,但Vue 提供的watch 默认不可以!- 使用
watch 时根据数据的具体结构,决定是否采用深度监视。 - 注意this指向问题。
-
箭头函数没有自己的this, 它的this是继承而来; 默认指向在定义它时所处的对象(宿主对象),而不是执行时的对象, 定义它的时候,可能环境是window; 箭头函数可以方便地让我们在 setTimeout ,setInterval中方便的使用this。 -
箭头函数中,this指向的固定化,并不是因为箭头函数内部有绑定this的机制,实际原因是箭头函数根本没有自己的this,导致内部的this就是外层代码块的this。
例如下面这段函数中,this指向的是Person对象,此时的箭头函数所处的宿主对象是Person,而不是执行时的对象Window,所以this指向的是person。
参考:关于箭头函数中的this的指向
3.4 姓名案例_watch实现
3.4.1 代码示例
代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<title>姓名案例_watch实现</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<div id="root">
姓:<input type="text" v-model="firstName"> <br/><br/>
名:<input type="text" v-model="lastName"> <br/><br/>
全名:<span>{{fullName}}</span> <br/><br/>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false;
const vm = new Vue({
el: '#root',
data: {
firstName: '张',
endName: '三',
fullName: '张-三'
},
watch: {
firstName(val) {
setTimeout(() => {
console.log(this);
this.fullName = val + '-' + this.lastName;
}, 1000);
},
endName(val) {
this.fullName = this.firstName + '-' + val;
}
}
});
</script>
</html>
3.4.2 总结(重要)
computed和watch之间的区别:
computed 能完成的功能,watch 都可以完成。watch 能完成的功能,computed 不一定能完成,例如:watch可以进行异步操作。- 两个重要的小原则:
- 所有被Vue管理的函数,最好写成普通函数,这样
this 的指向才是vm 或 组件实例对象。 - 所有不被Vue所管理的函数, 最好写成箭头函数,这样
this 的指向才是vm 或 组件实例对象。 - 不被
Vue 所管理的函数有:定时器的回调函数、ajax的回调函数、Promise的回调函数等。
4、过滤器
所谓过滤器,是指对要显示的数据进行特定格式化后(也就是对数据进行处理后)再显示,
适用于一些简单逻辑的处理。
4.1 代码示例
代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<title>过滤器</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dayjs/1.10.6/dayjs.min.js"></script>
</head>
<body>
<div id="root">
<h2>显示格式化后的时间</h2>
<h3>现在是:{{getFormatTime()}}</h3>
<h3>现在是:{{formatTime}}</h3>
<h3>现在是:{{time | timeFormater}}</h3>
<h3>现在是:{{time|timeFormater('YYYY年MM月DD日 HH:mm')|mySlice}}</h3>
<h3 :y="msg|mySlice">哈哈</h3>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false;
Vue.filter('mySlice', function (value) {
return value.slice(0, 4);
});
const vm = new Vue({
data() {
return {
time: 1628969177603,
msg: 'Hello, Vue!'
};
},
methods: {
getFormatTime() {
console.log(this.time);
return dayjs(this.time).format('YYYY年MM月DD日 HH:mm:ss');
}
},
computed: {
formatTime() {
return dayjs(this.time).format('YYYY年MM月DD日 HH:mm:ss');
}
},
filters: {
timeFormater(value, str = 'YYYY年MM月DD日 HH:mm:ss') {
console.log('value----', value);
return dayjs(value).format(str);
}
}
});
vm.$mount('#root');
</script>
</html>
4.2 总结
过滤器:
- 定义:对要显示的数据进行特定格式化后再显示(适用于一些简单逻辑的处理)。
- 分类:
- 全局过滤器:多个
Vue 实例中可以用。 - 局部过滤器:在哪个
Vue 实例中定义,哪个Vue 实例就可以使用。 - 语法:
- 注册过滤器:
Vue.filter(name,callback) 或 new Vue{filters:{ }} 。 - 使用过滤器:{{ xxx | 过滤器名}} 或 v-bind:属性 = “xxx | 过滤器名”。
- 备注:
- 过滤器也可以接收额外参数、多个过滤器也可以串联。
- 并没有改变原本的数据, 是产生新的对应的数据。
- 使用过滤器时,
| 的左边变量的值 作为过滤器的第一个参数。
5、收集表单数据
这个案例只是为了熟悉一些和表单相关的指令和修饰符。
5.1 代码示例
代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<title>收集表单数据</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<div id="root">
<form @submit.prevent="showInfo()">
账号:<input type="text" v-model.trim="userInfo.account"> <br/><br/>
密码:<input type="password" v-model.trim="userInfo.password"> <br/><br/>
年龄:<input type="number" v-model.number="userInfo.age"> <br/><br/>
性别:
男<input type="radio" name="sex" value="male" v-model="userInfo.sex">
女<input type="radio" name="sex" value="female" v-model="userInfo.sex"> <br/><br/>
爱好:
学习<input type="checkbox" value="study" v-model="userInfo.hobby">
打游戏<input type="checkbox" value="game" v-model="userInfo.hobby">
吃饭<input type="checkbox" value="eat" v-model="userInfo.hobby">
<br/><br/>
所属校区
<select v-model="userInfo.city">
<option value="">请选择城市</option>
<option value="beijing">北京</option>
<option value="shanghai">上海</option>
<option value="shenzhen">深圳</option>
<option value="guangzhou">广州</option>
</select>
<br/><br/>
其他信息:
<textarea v-model.trim.lazy="userInfo.other"></textarea> <br/><br/>
<input type="checkbox" v-model="userInfo.agree">阅读并接受<a href="#">《用户协议》</a>
<button>提交</button>
</form>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false;
const vm = new Vue({
data() {
return {
userInfo: {
account: '',
password: '',
age: 18,
sex: 'female',
hobby: [],
city: 'guangzhou',
other: '',
agree: '',
}
};
},
methods: {
showInfo() {
console.log(JSON.stringify(this.userInfo));
}
}
});
vm.$mount('#root');
</script>
</html>
5.2 总结
- 若:
< input type="text"/> ,则v-model 收集的是value 值,用户输入的就是value值。 - 若:
< input type="radio"/> ,则v-model 收集的是value 值,且要给标签配置value值。 - 若:
< input type="checkbox"/>
- 没有配置input的value属性,那么收集的就是
checked (勾选 or 未勾选,是布尔值)。 - 配置input的value属性:
v-model 的初始值是非数组,那么收集的就是checked (勾选 or 未勾选,是布尔值)。v-model 的初始值是数组,那么收集的的就是value 组成的数组。 - 备注:v-model的三个修饰符:
lazy :失去焦点再收集数据。number :输入字符串转为有效的数字。trim :输入首尾空格过滤。
6、结语
这篇博客就写到这里,有什么不对的地方欢迎指正。
如果对你有帮助,欢迎点赞,评论和转发。
谢谢。
|