一、ES6语法:
1.1 let/var
1.1.1 var
var为ES5中定义变量的关键字,但是由于ES5之前if和for没有属于自己的块级作用域,会使得在其他域中能够改变它的值。
<script>
if(true){
var name = '张三';
console.log(name);
}
// var name = "李四";
console.log(name);
</script>
在前端打印时两次全部可以打印出来,可见var没有自己的块级域。
1.1.2 let
let为ES6中定义变量的关键字,let有了if和for的块级作用域,避免了在不同作用域会更改其他作用域的问题。所以在定义变量时尽量使用let。
1.1.3 例子:
定义三个按钮实现点击第几个按钮前端打印第几个按钮
<button>按钮一</button>
<button>按钮二</button>
<button>按钮三</button>
<script>
//1.ES5时错误写法:由于没有块作用域的原因,每遍历一次i的值都会加1,因此无论点击那个按钮最终打印的都是最后一个按钮。
var btns = document.getElementsByTagName('button');
for (var i = 0; i < btns.length; i++){
btns[i].addEventListener('click',function{
console.log('第' + i + '个按钮被点击');
})
}
//2.ES5使用闭包实现功能:因为函数有自己的块作用域,每个作用域都有属于自己的i,每次打印的都是自己的i所以可以实现。
var btns = document.getElementsByTagName('button')
for (var i = 0; i < btns.length; i++){
(function(i){
btns[i].addEventListener('click',function{
console.log('第' + i + '个按钮被点击');
})
})(i)
}
//3.ES6实现功能:let有自己的块作用域
const btns = document.getElementsByTagName('button');
for (let i = 0; i < btns.length; i++){
btns[i].addEventListener('click',function{
console.log('第' + i + '个按钮被点击');
})
}
</script>
1.2 const
- 将某个标识符修饰为一个常量
- 建议:在开发中优先使用const,只有在需要修改某个标志符时才使用let。
- 注意
-
一旦给const修饰的标识符被赋值之后,不能修改。
错误1. <script> const name = 'zhangsan'; //会报错 name = 'lisi' </script>
-
在使用const定义修饰符时必须赋初始值。
错误2. <script> const name; </script>
-
定义的常量含义是指向的对象不能修改,但是可以改变对象内部的属性。(因为const保存的是内存地址并不是属性)
<script> const ojb = { name: 'zhangsan', age: '18', } obj.name = 'lisi'; //错误写法: //const obj = {} </script>
二、事件监听 v-on
缩写:@
2.1 单击事件
<div id="app">
<h2>{{num}}</h2>
<button @click="add">点击加一</button>
</div>
<script>
const app = new Vue({
el: "#app",
data: {
num: 0
},
methods: {
add(){
this.num++
}
}
})
</script>
2.2 v-on的参数问题
-
若函数需要传一个参时,执行代码时没有传参会打印undefind
<div id="app"> <button @click="getNum()">获取值</button> </div> <script> const app = new Vue({ el: "#app", methods:{ getNum(num){ console.log("-----------"+num) } } }) </script>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-g4LCaCEn-1657504443274)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\1655443261809.png)]
-
想要获取网页的event对象
<div id="app"> <button @click="getNum">获取值</button> </div> <script> const app = new Vue({ el: "#app", methods:{ getNum(e){ console.log("-----------"+e) } } }) </script>
将点击事件中绑定的需要传参的函数的小括号去掉,可以获取到网站自动生成的event对象数据。
-
同时获取到传递参数和event对象
<div id="app"> <button @click="getNum(abc,$event)">获取值</button> </div> <script> const app = new Vue({ el: "#app", data: { abc: 123 }, methods:{ getNum(abc,event){ console.log("-----------"+abc) console.log("-----------"+event) } } }) </script>
2.3 v-on修饰符
.stop
<div id="app">
<div @click="fatherClick">
<button @click.stop="childClick">click</button>
</div>
</div>
<script>
const vm = new Vue({
el: '#app',
methods: {
fatherClick() {
console.log('father');
},
childClick() {
console.log('child');
}
}
})
</script>
若没有阻止冒泡则打印child,father,组织后只打印child
.self
作用:只当事件是从侦听器绑定的元素本身触发时才触发回调
<div id="app">
<div :style="{ backgroundColor: '#f88', width:'100px',height:'100px'}" @click.self='fatherClick'>
<button @click='childClick'>click</button>
</div>
</div>
<script>
const vm = new Vue({
el: '#app',
methods: {
fatherClick() {
console.log('father');
},
childClick() {
console.log('child');
}
}
})
</script>
只有点击绑定元素时才会触发对应的效果
.once
只能触发一次,之后点击不在触发
三、条件判断
3.1 v-if、v-elseif、v-else
<div id="qpp">
<h2 v-if="num >= 90">{{good}}</h2>
<h2 v-else-if="num >= 60 && num <90">{{Pass}}</h2>
<h2 v-else>{{fauit}}</h2>
</div>
<script>
const app = new Vue({
el: "#app",
data: {
fauit: "不及格",
good: "优秀",
Pass: "及格",
num: 90
},
})
</script>
四、v-for遍历
在for循环中
<script>
let num[]
//1.在for循环中使用"in"是遍历的数组的索引值
for (let n in num){
console.log(n)
}
//2.在for循环中使用"of"是遍历的数组的元素值
for (let n of num){}
</script>
4.1遍历数组
遍历数组并实现点击那个那个字体变成红色
<stype>
.active{color: red}
</stype>
<div>
<div id="app">
<ul>
<li v-for=" (value,index) in datalist" :class="{active: cuerys==index}" @click='bander(index)' :title="value">
{{index+1}}{{value}}
</li>
</ul>
</div>
</div>
<script>
const apps = new Vue({
el: "#app",
data: {
cuerys:0,
datalist: ['西游记','红楼梦','水浒传','三国演义']
},
methods: {
bander: function (obj) {
this.cuerys = obj;
}
}
})
</script>
4.2 遍历对象
<div>
<div id="app">
<ul>
<li v-for="(value, key) in info">{{key}}:{{value}}</li>
</ul>
</div>
</div>
<script>
const apps = new Vue({
el: "#app",
data: {
info: {
name: "张三",
age: 18
}
}
})
</script>
4.3 组件的key属性
推荐在使用v-for时,给对应元素或组件设置key属性(必须确保:key中的值要和数组里的值能够一一对应)。
<div id="app">
<ul>
<li v-for="items in datalist" :key="items">{{items}}</li>
</ul>
</div>
<script>
const app = new Vue({
el: "#app",
data: {
datalist:['zhangsan','lisi','wangwu']
}
})
</script>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MM4CwjQr-1657504443281)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\1655452396084.png)]
-
未使用:key时在中间插入数据(会将插入位置元素替换为插入值,然后其他值往后移,性能低):
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yhmVKTGQ-1657504443282)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\1655517290037.png)]
-
使用:key时在中间插入数据:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-j9NA4vNn-1657504443284)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\1655517255407.png)]
4.4 高级函数
*编程范式:命令式编程、声明式编程
*编程范式:面向对象编程、函数式编程
filter
- filter中的回调函数有一个要求:必须返回一个boolean值。
- filter中传递的参数必须是一个函数
- true:当返回ture时,函数内部会自动将这次回调的n加入到新的数组中。
- false:当返回false时,函数内部会过滤掉这次的n。
<script>
//筛选出小于100的值
const nums = [10, 20, 111, 222, 444, 40, 50]
let newNums = nums.filter(function(n){
return n < 100
})
</script>
map
<script>
//使数组中的所有数值乘以2
const nums = [10, 20, 111, 222, 444, 40, 50]
let newNums = nums.map(function(n){
return n * 2
})
</script>
reduce
- 对数组中所有内容进行汇总
- reduce的回调函数中需要传两个值
<script>
//
const nums = [20, 40, 80, 100]
//reduce.function(上次返回的值,初始化的值)
//此代码中,第一个参数:function(preValue, n{return preValue + n;});第二个参数:0(将第一次返回值设成0)
let total = nums.reduce(function(preValue, n){
return preValue + n;
},0)
//第一次遍历:preValue=0,n=20
//第二次遍历:preValue=20,n=40
//第三次遍历:preValue=60,n=80
//第四次遍历:preValue=140,n=100
//最终执行结果为240
</script>
将一个数组小于100的取出来乘以2把数值相加
<script>
const nums = [10, 20, 111, 222, 444, 40, 50]
let total1 = nums.filter(function(n){
return n < 100
}).map(function(n){
return n * 2
}).reduce(function(preValue, n){
return preValue + n
},0)
let total2 = filter(n => n<100).map(n => n*2).reduce((pre, n) => pre + n)
</script>
五、v-model表单绑定
5.1 v-model的基本使用
5.1.1 双向绑定
//使用v-model实现双向绑定
<div>
<input type="text" v-model="message">
{{message}}
</div>
<script>
const = app = new Vue({
el: "#app",
data: {
message: "你好啊"
}
})
</script>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZMS0pgVz-1657504443287)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\1655521820789.png)]
打开页面是在input输入框内已经绑定了message里面的值
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-56aCCeNj-1657504443288)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\1655521882187.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YiWtzYMR-1657504443289)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\1655521891004.png)]
在修改了input里面的值的时候,message里面的值也会发生改变。
v-model等同于下面两条指令
<div>
<input type="text" v-bind:value="message" v-on:input="message = $event.target.value">
{{message}}
</div>
<script>
const = app = new Vue({
el: "#app",
data: {
message: "你好啊"
}
})
</script>
5.1.2 v-model:radio
<div id="app">
//name相同时实现单选框互斥
//在v-model绑定同一个变量时也可以实现互斥,可以删除name属性
<label for="man">
<input type="radio" id="man" name="sex" value="男" v-model="sex">男
</label>
<label for="woman">
<input type="radio" id="woman" name="sex" value="女" v-model="sex">女
</label>
</div>
<script>
const app = new Vue({
el: "#app",
data: {
sex: "",
}
})
</script>
5.1.3 v-model:checkbox
<div id="app">
//checkbox单选框,对应布尔值
<label for="agree">
<input type="checkbox" id="agree" v-model="isAgree">同意协议
</label>
<button :disable="!isAgree">下一步</button>
//checkbox多选框,对应数组
<input type="checkbox" value="篮球" v-model="hobbies">篮球
<input type="checkbox" value="足球" v-model="hobbies">足球
<input type="checkbox" value="羽毛球" v-model="hobbies">羽毛球
</div>
<script>
const app = new Vue({
el: "#app",
data: {
idAgree: false,
hobbies: []
}
})
</script>
5.1.3 v-model:select
<div id="app">
//选择单个
<select name="abc" id="" v-model="fruit">
<option value="苹果">苹果</option>
<option value="香蕉">香蕉</option>
<option value="西瓜">西瓜</option>
</select>
//选择多个
<select name="cba" id="" v-model="fruits" multiple>
<option value="苹果">苹果</option>
<option value="香蕉">香蕉</option>
<option value="西瓜">西瓜</option>
</select>
</div>
<script>
const app = new Vue({
el: "#app",
data: {
fruit: '',
fruit: []
}
})
</script>
5.1.4 v-model值绑定
//从给定的变量值中进行选择
<div id="app">
<label v-for="item in playhobbeis" :for="item">
<input type="checkbox" :value="item" v-model="hobbies" :id="item">{{item}}
</label>
</div>
<script>
const app = new Vue({
el: '#app',
data: {
playhobbeis: ['篮球','足球','乒乓球'],
hobbeis: []
}
})
</script>
5.1.5 v-model修饰符
- v-model.lazy:因为v-model是双向绑定的,在输入框输入数据时绑定的变量会立刻进行改变,使用lazy修饰符后变量中的值会在用户敲击回车或者输入框失去焦点时才会发生改变。
- v-model.number:v-model在双向绑定时无论用户输入字母还是数字数据类型均被改变为string类型,使用.number修饰符是数据类型改变为number类型。
- v-model.trim:去除用户输入的字符串两端的空格。
6、组件化
组件的使用分为三个步骤:
- 创建组件构造器:调用Vue.extend()方法创建。
- 注册组件:调用Vue.component()方法注册。
- 使用组件:在Vue实例范围内使用。
<div id="app">
<!--3.使用组件-->
<cpn></cpn>
</div>
<script src="导入vue.js"></script>
<script>
//1.创建组件构造器
const cpnC = Vue.extend({
//ES6定义字符串使用``(波浪键),可以实现字符串换行。
//template是组件模板
template:
`<div>
<h2> 组件标题</h2>
<p>我是组件中的一个段落内容</p>
</div>`
});
//2.注册组件,并且定义组件标签名称
Vue.component('cpn',cpnC)
let app = new Vue({
el: "#app"
})
</script>
6.1 组件化开发
6.1.1 全局组件和局部组件
- 全局组件:可以在多个Vue实例中使用。
- 局部组件:在某个Vue实例中注册
<script>
//只可以在绑定的div中使用
const app = new Vue({
el: '#app',
data: {},
components: {
//cpn使用组件时的标签名
my-cpn: myComponent
}
})
</script>
6.1.2 父组件和子组件的区分
<div id="app">
<cpn2></cpn2>
</div>
<script src="Vue.js"></script>
<script>
//创建第一个组件构造器
const cpnC1 = Vue.extend({
template: `
<div>
<h2> 组件标题1</h2>
<p>我是组件中的一个段落内容1</p>
</div>
`
})
//创建第二个组件构造器(父组件)
const cpnC2 = new Vue({
template: `
<div>
<h2> 组件标题2</h2>
<p>我是组件中的一个段落内容2</p>
<cpn1></cpn1>
</div>
`,
components: {
cpn1: cpnC1
}
})
const app = new Vue({
el: '#app',
components: {
cpn2: cpnC2
}
})
</script>
6.1.3 组件的语法糖注册方式
省去了电泳Vue.extend()的步骤,可以直接使用一个对象来代替。
<!--1.全局组件的语法糖-->
<script>
Vue.component('cpn1', {
template: `
<div>
<h2> 组件标题2</h2>
<p>我是组件中的一个段落内容2</p>
<cpn1></cpn1>
</div>
`
})
</script>
<!--2.局部组件的语法糖-->
<script>
const app = new Vue({
el: '#app',
components: {
'cpn': {
template: `
<div>
<h2> 组件标题</h2>
<p>我是组件中的一个段落内容</p>
</div>
`
}
}
})
</script>
6.1.4 组件中组件模板的抽离
<div id="app">
<cpn></cpn>
</div>
<!--第一种写法,使用script标签-->
<script type="text/x-template" id="cpn">
<div>
<h2>组件1</h2>
</div>
</script>
<!--第二种写法,使用template标签-->
<template id="cpn">
<div>
<h2>组件1</h2>
</div>
</template>
<script src="Vue.js"></script>
<script>
//注册一个全局组件
Vue.component('cpn', {
template: '#cpn',
//存在data属性,但是data应该是function
data() {
return {
//组件中需要存放的数据
}
}
})
const app = new Vue({
el: '#app',
}
})
</script>
组件中可以有data属性也可以有methods属性。组件中的数据存放在data属性中,只是组件中的data属性必须是一个函数: data(){}。
<div id="app">
<cpn></cpn>
<cpn></cpn>
</div>
<template id="cpn">
<div>
当前技术:{{count}}
<button @click="increment">+</button>
</div>
</template>
<script src="Vue.js"></script>
<script>
Vue.component('cpn', {
template: '#cnp',
data(){
return count: 0
},
methods: {
increment() {
this.count++
}
}
})
const app = new Vue({
el: '#app
})
</script>
为什么必须是函数:组件是点击按钮使count属性值加1。组件是可以重复使用的,定义了两个组件。若data不是函数类型会造成连锁反应,点击一个按钮两个按钮的count均会增加。由于data是函数类型,每个组件的count属性值是不共用的。因为每次调用对象的本质上是调用的对象的内存地址,函数会给对象分配不同的内存地址。
6.2 父子组件通信
6.2.1 父传子props
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lO0qj0eJ-1657504443291)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\1657003216620.png)]
<div id="app">
<!--<cpn :c-Movies="movies></cpn>"-->
<cpn :cmovies="movies"></cpn>
</div>
<template id='cpn'>
<div>
{{cmovies}}
</div>
</template>
<script src="Vue.js"></script>
<script>
//父传子:props
const cpn = {
template: '#cpn',
data() {
return {}
}
//props: ['cmovies']
props: {
//cMovies: Array,
//类型限制
cmovies: Array,
//默认值
default: ['', '', '']
//必须传值
required: true
}
}
const app = new Vue({
el: '#app',
data: {
movies:['西游记', '红楼梦', '三国演义', '水浒传']
}
components: {
//'cpn': cpn
cpn
}
})
</script>
6.2.2 props驼峰标识
注意:Vue当前版本v-bind不支持驼峰,当父组件中props中的字段名是驼峰式时(例:cInfo),在使用时需要这样书写(<组件名 :c-info=“”></组件名>),用“-”符号隔开。在上方代码中以注解体现。
6.2.3 子传父(自定义事件)
<div id="app">
<cpn @item-click="clicks(item)"></cpn>
</div>
<template id="cpn">
<div>
<button v-for="item in categories" @click="btnClick(item)">{{item.name}}</button>
</div>
</template>
<script src="Vue.js"></script>
<script>
const cpn = {
template: '#cpn',
data() {
categories: [
{id: '001', name: '热门推荐'},
{id: '002', name: '家用电器'},
{id: '003', name: '电脑办公'}
]
},
methods: {
btnClick(item) {
console.log(item)
this.$emit('item-click', item)
}
}
}
//父组件
const app = new Vue({
el: '#app',
components: {
cpn
},
methods: {
clicks(item){
console.log(item)
}
}
})
</script>