大家好,大家好,我又来了,这次还是基础部分的知识,快来学习吧,下一篇将学习Vue组件化的使用以及组件通信,插槽等知识,原创不易,如果觉得写的不错,可以点赞评论支持一下
简单上手
假如要实现两个变量的计算,目前可以使用拼接,使用 methods 方法来实现,现在将引入一个新的 option ,计算属性,computed,你可能会疑问,有什么不一样吗?不着急,慢慢来,你会理解的
<body>
<div id="app">
<h2>使用拼接 {{firstName + " " + lastName}}h2>
<h2>使用方法 {{getFullName()}}h2>
<h2>计算属性 {{fullName}}h2>
div>
<script src="./vue.js">script>
<script>
new Vue({
el: '#app',
data: {
firstName: 'liu',
lastName: 'xiao sen',
},
methods: {
getFullName() {
return this.firstName + " " + this.lastName;
}
},
computed: {
fullName: function () {
return this.firstName + " " + this.lastName;
}
}
})
script>
body>
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Documenttitle>
head>
<body>
<div id="app">
<h2>计算属性 {{fullName}}h2>
div>
<script src="./vue.js">script>
<script>
var app = new Vue({
el: '#app',
data: {
firstName: 'liu',
lastName: 'xiao sen',
},
computed: {
// 只用get方法时,可以简写
/*fullName: function () {
return this.firstName + " " + this.lastName;
}
*/
// 完成写法是对象,我们通过 fullName 访问,会直接调用 get 方法,所以写成 fullName
fullName: {
set: function (newVal) {
console.log(newVal);
const names = newVal.split(' ');
this.firstName = names[0];
this.lastName = names[1];
},
get: function () {
return this.firstName + ' ' + this.lastName;
}
}
}
})
script>
body>
html>
计算属性的优势就是它是使用缓存机制了的,如果多次使用,计算属性只执行一次
下面是对比的代码,一目了然
<body>
<div id="app">
<h3>{{getFullName()}}h3>
<h3>{{getFullName()}}h3>
<h3>{{getFullName()}}h3>
<h3>{{getFullName()}}h3>
<hr />
<h3>{{fullName}}h3>
<h3>{{fullName}}h3>
<h3>{{fullName}}h3>
<h3>{{fullName}}h3>
div>
<script src="./vue.js">script>
<script>
var app = new Vue({
el: '#app',
data: {
firstName: 'liu',
lastName: 'xiao sen',
},
methods: {
getFullName() {
console.log("method执行了");
return this.firstName + ' ' + this.lastName;
}
},
computed: {
fullName() {
console.log("计算属性执行了");
return this.firstName + ' ' + this.lastName;
}
}
})
script>
body>
因为 v-on 使用较多,因此添加了语法糖,语法糖就是简写
普通写法
<body>
<div id="app">
<button v-on:click="count ++">{{count}}button>
div>
<script src="./vue.js">script>
<script>
new Vue({
el: "#app",
data: {
count: 0,
},
});
script>
body>
使用了语法糖,使用@代替重复的 v-on:
<body>
<div id="app">
<button @click="count ++">{{count}}button>
div>
<script src="./vue.js">script>
<script>
new Vue({
el: "#app",
data: {
count: 0,
},
});
script>
body>
◼️ 1. 无参数,不传
◼️ 2. 有一个参数或多个参数,但不包含时间对象参数时,加括号,参数按照顺序写
◼️ 3. 当不仅要传普通参数,还要传递事件参数时,获取事件对象通过 $event
例子
<body>
<div id="app">
<button @click="f1">按钮1button>
<button @click="f2('小u')">按钮2button>
<button @click="f3('小R',$event)">按钮3button>
div>
<script src="./vue.js">script>
<script>
new Vue({
el: "#app",
methods: {
f1() {
console.log("无参数");
},
f2(name) {
console.log("name is:" + name);
},
f3(name, event) {
console.log("name is:" + name + " and event is:" + event);
console.log(event);
},
},
});
script>
body>
事件修饰符,简化编码,比如阻止事件冒泡,阻止默认事件等等……
.stop 阻止事件冒泡
.prevent 阻止事件的默认行为
.键别名/键代码 特定键触发
.once 只触发一次回调
事件冒泡
微软提出了名为事件冒泡(event bubbling)的事件流。事件冒泡可以形象地比喻为把一颗石头投入水中,泡泡会一直从水底冒出水面。也就是说,事件会从最内层的元素开始发生,一直向上传播,直到document对象。
<body>
<div id="app">
<div @click="f2">
<div @click="f1">点击事件冒泡div>
div>
div>
<script src="./vue.js">script>
<script>
new Vue({
el: "#app",
methods: {
f1() {
console.log("f1");
},
f2() {
console.log("f2");
},
},
});
script>
body>
js冒泡和捕获是事件的两种行为,使用event.stopPropagation()起到阻止捕获和冒泡阶段中当前事件的进一步传播。
<body>
<div id="app">
<div @click="f2">
<div @click="f1">点击事件冒泡div>
div>
div>
<script src="./vue.js">script>
<script>
new Vue({
el: "#app",
methods: {
f1(e) {
console.log("f1");
e.stopPropagation();
},
f2() {
console.log("f2");
},
},
});
script>
body>
<div id="app">
<div @click="f2">
<div @click.stop="f1">点击事件冒泡div>
div>
div>
<body>
<div id="app">
<li v-if="count == 10">如果count=10我就显示li>
<li v-if="count > 20">如果count大于20我就显示li>
<li v-else>如果都不对我就显示li>
div>
<script src="./vue.js">script>
<script>
new Vue({
el: "#app",
data: {
count: 15,
},
});
script>
body>
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
<style>
body {
display: flex;
align-items: center;
justify-content: center;
min-height: 100vh;
}
span {
cursor: pointer;
background-color: #69F;
color: #FFF;
border-radius: 5px;
}
input {
margin-top: 30px;
border: none;
outline: none;
border-bottom: 1px solid #ccc;
width: 250px;
}
input[type='submit'] {
border: none;
height: 25px;
background-color: #69F;
color: #fff;
}
style>
head>
<body>
<div id="app">
<span @click="f1">账号登录span>
<span @click="f2">手机登录span>
<form action="" method="post">
<input type="text" placeholder="请输入账号" v-if="flag == 10">
<input type="text" placeholder="请输入手机" v-else><br />
<input type="password" placeholder="请输入密码"><br />
<input type="submit" value="登录">
form>
div>
<script src="./vue.js">script>
<script>
new Vue({
el: '#app',
data: {
flag: 0
},
methods: {
f1() {
this.flag = 10;
},
f2() {
this.flag = 20;
}
},
})
script>
body>
html>
有一个小问题,生活中的注册登录,在切换登录方式时,里面的输入会被清空,但是我们上面的案例,并不会,为什么,这就涉及 vue 的底层了,它为了提高性能,使用了 diff 算法,说白了,就是找不同算法,结合虚拟 DOM ,实现最大化的复用,如果 key 相同,能复用,就原地复用,如果不能,再创建 DOM渲染视图,我们可以设置不同的 key,以达到每次都重新渲染的效果
<div id="app">
<span @click="f1">账号登录span>
<span @click="f2">手机登录span>
<form action="" method="post">
<input type="text" placeholder="请输入账号" v-if="flag == 10" key="account">
<input type="text" placeholder="请输入手机" v-else key="phone"><br />
<input type="password" placeholder="请输入密码"><br />
<input type="submit" value="登录">
form>
div>
v-show 和 v-if 都是控制元素是否展示的,我想问他们是情侣吗?哈哈,跑偏了,回归正题,通过下面代码,你会秒懂,并知道啥时候该用啥
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
head>
<body>
<div id="app">
<p v-if="1==1">v-if {{message}}p>
<p v-show="1==1">v-show {{message}}p>
<hr/>
<p v-if="1==2">v-if {{message}}p>
<p v-show="1==2">v-show {{message}}p>
div>
<script src="./vue.js">script>
<script>
new Vue({
el:'#app',
data:{
message:'Hello King'
}
})
script>
body>
html>
上图能发现,使用 v-show 为假隐藏元素时,他是通过css的 display:none
隐藏的,使用 v-for 为假隐藏元素时,他是直接将元素从 DOM 树里移除
什么时候使用 v-for,什么时候用 v-show
◼️ 当需要在隐藏和显示之间来回跳的话,推荐你使用 v-show,性能更好
◼️ 当只有一次或很少次的切换时,推荐使用 v-if
<body>
<div id="app">
<ul>
<li>普通遍历数组li>
<li v-for="item in arrs">{{item}}li>
<hr />
<li>遍历数组,同时打印索引li>
<li v-for="(item,index) in arrs">{{index + 1}} - {{item}}li>
<hr />
<li>普通遍历对象li>
<li v-for="(value,key) in obg">{{key}} - {{value}}li>
<hr />
<li>遍历对象,同时获取indexli>
<li v-for="(value,key,index) in obg">{{index}} - {{key}} - {{value}}li>
ul>
div>
<script src="./vue.js">script>
<script>
new Vue({
el: '#app',
data: {
arrs: ['你的名字', '天气之子', '萤火之森'],
obg: {
name: '小爱',
sex: '女',
age: 8
}
}
})
script>
body>
key的主要作用是高效的更新虚拟 DOM
使用index作为key
<body>
<div id="app">
<ul>
<li v-for="(item,index) in arrs" :key="index">
{{item.id}} - {{item.name}} - {{item.age}}
<input type="text">
li>
ul>
<button @click="add">添加一个小张button>
div>
<script src="./vue.js">script>
<script>
new Vue({
el: '#app',
data: {
arrs: [
{
id: '001',
name: '小艾',
age: 18
},
{
id: '002',
name: '小兵',
age: 24
},
{
id: '003',
name: 'Sirie',
age: 26
}
]
},
methods: {
add(){
const xiaozhang = {id:'004',name:'小张',age:8};
this.arrs.unshift(xiaozhang);
}
},
})
script>
body>
使用 index 作为 key,当你在前面添加时,就导致 index 重新编排,最坏的就是从头插入,这时虚拟dom的diff算法,就不能就地复用了
当我们使用id作为 key 时,避免v-for“就地更新”策略导致的问题。
◼️ 因为 Vue 是响应式的,所以当数据有变化时,Vue会自动检测到数据的变化,视图会发生对应的更新
◼️ Vue 包含了一组观察数组变化的方法,使用这些方法操作数组才会被 Vue 检测到,从而更新视图
◼️ 使用下标操作数组,不会被 Vue 检测到,因为代价较大,所以不是响应式的,而下面的这些方法都是被 Vue 重写过的,在实现功能的基础上,添加了响应式的代码
⚙️ push()
⚙️ pop()
⚙️ shift()
⚙️ unshift()
⚙️ splice()
⚙️ sort()
⚙️ reverse()
***
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>购物车title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
#app {
display: flex;
width: 100vw;
height: 100vh;
}
table {
margin: auto;
width: 40%;
border-collapse: collapse;
}
th,
td {
height: 35px;
line-height: 35px;
text-align: center;
border: 1px solid rgb(222, 222, 222);
}
th {
background-color: rgb(238, 238, 238);
color: #454545;
}
button {
width: 40px;
height: 25px;
border: 1px solid #cfcfcf;
border-radius: 6px;
background-color: transparent;
}
p {
position: absolute;
bottom: 200px;
left: 50%;
transform: translateX(-50%);
}
style>
head>
<body>
<div id="app">
<p v-show="shoppings.length == 0">什么都没有呀p>
<table>
<tr>
<th v-show="shoppings.length != 0" v-for="item in names">{{item}}th>
tr>
<tr v-for="(item,index) in shoppings">
<td>{{item.name}}td>
<td>{{item.date}}td>
<td>{{item.price}}td>
<td>
<button @click="subNum(index)">-button>
{{item.num}}
<button @click="addNum(index)">+button>
td>
<td>
<button @click="moveShop(index)">移除button>
td>
tr>
<p v-show="shoppings.length != 0">总价:{{priceSum}}p>
table>
div>
<script src="./vue.js">script>
<script>
new Vue({
el: '#app',
data: {
names: ['商品名称', '出版日期', '价格', '购买数量', '操作'],
shoppings: [
{
id: 1,
name: '卫龙辣条',
date: '2012-12-12',
price: 10,
num: 1
},
{
id: 2,
name: '嘿嘿C语言',
date: '2012-2-10',
price: 100,
num: 1
},
{
id: 3,
name: '别想嫩多啦',
date: '2021-2-2',
price: 20,
num: 1
},
{
id: 4,
name: '球衣',
date: '2009-12-12',
price: 1000,
num: 1
},
],
totalPrice: 0
},
methods: {
addNum(index) {
this.shoppings[index].num++;
},
subNum(index) {
if (this.shoppings[index].num > 1) {
this.shoppings[index].num--;
}
},
moveShop(index) {
this.shoppings.splice(index, 1);
}
},
computed: {
priceSum() {
this.totalPrice = 0;
for (let i = 0; i < this.shoppings.length; i++) {
this.totalPrice += this.shoppings[i].price * this.shoppings[i].num;
}
return this.totalPrice;
}
}
})
script>
body>
html>
定义在配置对象中添加 filters 配置项,然后写过滤函数,传入要处理的参数
使用在参数后 {{price | showDecimalPoint}}
可以使用多个过滤器
<body>
<div id="app">
<ul>
<li v-for="price in prices">{{price | showDecimalPoint}}li>
ul>
div>
<script src="./vue.js">script>
<script>
new Vue({
el: '#app',
data: {
prices: [100, 200, 300, 10]
},
filters: {
showDecimalPoint(price) {
return '¥' + price.toFixed(2);
}
}
})
script>
body>
使用增强 for 方便我们对数组和对象的遍历
使用 for in 遍历对象数组时,返回的是数组下标
<body>
<div id="app">
<button @click="heightenFor">点击使用增强for(for in)button>
div>
<script src="./vue.js">script>
<script>
new Vue({
el: '#app',
data: {
arrs: [
{ id: 1, age: 56 },
{ id: 2, age: 34 },
{ id: 3, age: 24 },
{ id: 4, age: 22 },
]
},
methods: {
heightenFor() {
for (let arr in this.arrs) {
console.log(this.arrs[arr].age);
}
}
},
})
script>
body>
使用 for of 遍历对象数组时,会直接返回我们的对象,这就非常的方便了
<body>
<div id="app">
<button @click="heightenFor">点击使用增强for(for of)button>
div>
<script src="./vue.js">script>
<script>
new Vue({
el: '#app',
data: {
arrs: [
{ id: 1, age: 56 },
{ id: 2, age: 34 },
{ id: 3, age: 24 },
{ id: 4, age: 22 },
]
},
methods: {
heightenFor() {
for (let arr of this.arrs) {
console.log(arr.id);
console.log(arr.age);
}
}
},
})
script>
body>
<body>
<div id="app">
<p>用户账号 <input type="text" v-model="username"> p>
<p>username: {{ username}}p>
div>
<script src="./vue.js">script>
<script>
var vm = new Vue({
el: '#app',
data: {
username: ''
}
})
script>
body>
模拟实现双向绑定
v-model其实是一个语法糖
1. 使用 v-bind 绑定一个 value 属性
2. v-on 指令给当前元素绑定 input 事件
<body>
<div id="app">
<input type="text" :value="message" @input="message = $event.target.value">{{message}}
div>
<script src="./vue.js">script>
<script>
new Vue({
el: '#app',
data: {
message: 'abc'
}
})
script>
body>
<body>
<div id="app">
<label for="male">
<input type="radio" v-model="gender" value="男" id="male">
label>
<label for="female">
<input type="radio" v-model="gender" value="女" id="female">
label>
<p>{{gender}}p>
div>
<script src="./vue.js">script>
<script>
new Vue({
el: '#app',
data: {
gender: '男'
}
})
script>
body>
<body>
<div id="app">
<label for="agreement">
<input type="checkbox" id="agreement" v-model="isAgree">同意协议
label>
{{isAgree}}
<hr />
<label for="1">
<input type="checkbox" v-model="hobbys" value="看动漫" id="1">看动漫
label>
<label for="2">
<input type="checkbox" v-model="hobbys" value="学java" id="2">学java
label>
<label for="3">
<input type="checkbox" v-model="hobbys" value="打豆豆" id="3">打豆豆
label>
<label for="4">
<input type="checkbox" v-model="hobbys" value="起飞" id="4">起飞
label>
<p>你的爱好是: {{hobbys}}p>
div>
<script src="./vue.js">script>
<script>
new Vue({
el: '#app',
data: {
isAgree: false,
hobbys: []
}
})
script>
body>
<body>
<div id="app">
<select name="" id="" v-model="me">
<option value="青果">青果option>
<option value="香蕉">香蕉option>
<option value="山楂">山楂option>
<option value="草莓">草莓option>
<option value="西瓜">西瓜option>
select>
<p>你选择的水果是: {{me}}p>
<hr />
<select name="" id="" v-model="mes" multiple>
<option value="青果">青果option>
<option value="香蕉">香蕉option>
<option value="山楂">山楂option>
<option value="草莓">草莓option>
<option value="西瓜">西瓜option>
select>
<p>你选择的水果是: {{mes}}p>
div>
<script src="./vue.js">script>
<script>
new Vue({
el: '#app',
data: {
me: '西瓜',
mes: []
}
})
script>
body>
lazy修饰符,使用 lazy 修饰符可以让数据在失去焦点或者回车时才更新
number修饰符,可以让输入框中的内容自动转换成数字类型
trim修饰符,可以过滤输入内容左右两边的空格
感谢你能看完这篇文章,我相信你一定收获颇多,如果对博主的文章有什么建议,欢迎在评论区讨论,拜拜了