《基础篇第2章:vue2基础》包含Vue2知识点、个人总结的使用注意点及碰到的问题总结

导读:本篇文章讲解 《基础篇第2章:vue2基础》包含Vue2知识点、个人总结的使用注意点及碰到的问题总结,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

在这里插入图片描述

第2章:vue2基础 – 指令

2.1如何使用vue

如何使用Vue:
1、引入Vue的核心JS文件
2、准备Dom结构
3、实例化组件
通过el属性,挂载元素,绑定id为app的html元素
通过data属性,定义数据,可以在html代码段中显示的数据
4、获取数据
数据绑定最常见的形式就是使用“Mustache”语法 (双大括号) 的文本插值

2.2vue模板语法

在这里插入图片描述

<div id="app">
        <h1>插值语法</h1>
        <h1>{{name}}-{{address}}</h1>
        <hr>
        <h1>指令语法</h1>
        <a v-bind:href="url">点我跳转百度</a>
        <a :href="url"></a>
</div>

2.3文本渲染 (都是针对标签属性)

2.3.1 v-text

在这里插入图片描述

注意点1:v-text=’msg’会拿msg的值替换标签体的值,换句话说如果设置了v-text标签且无论msg是否为空,那么标签体的内容“你好”就失效了,不会显示

比如data中msg值为Hello World,那么页面会显示Hello World,如果msg=’ ’值为空,那么h3整个标签都不会显示,更不会显示标签体内容“你好”
<h3 v-text=’msg’>你好</h3>

在 html 中插入数据,跟{{}}功能一致:
在这里插入图片描述

2.3.2 v-once

注意点1:切记不要弄混了文本渲染v-once和事件修饰符的.once
文本渲染v-once:指页面只渲染一次
事件修饰符的.once:指的是方法只调用一次有效
在这里插入图片描述

2.3.3 v-html

在这里插入图片描述

注意点1(重点关注):使用v-html存在安全隐患,比如下面图片举例说明,str2是一个黄色钓鱼网址链接,如果使用v-html,那么会解析标签内容结构到页面上变成一个链接,如果用户点击了该链接,那么恶意网站就能获取用户登录cookie(cookie包含了你的用户名密码),那么恶意网站就会做坏事了,比如盗号、恶意转账盗钱等。所以为了避免安全隐患,请谨慎使用v-html标签,如果你确定代码部分是安全的,不会有乱七八糟的东西,那么使用v-html标签也没事。而v-text就不会解析html元素,就不会把str2变成链接地址,这样因为跳转不了,恶意软件也就无法获取用户cookie 了,也就做到了避免安全隐患。
在这里插入图片描述

注意点2:把文本内容进行解析,生成 html 结构并渲染。
在这里插入图片描述
在这里插入图片描述

2.4数据绑定

v-bind 指令可以绑定元素的属性,动态给属性赋值。比如: v-bind:class、
v-bind:style、 v-bind:href 形式。
注意点1:v-bind标签不仅可以传属性值,还可以传方法

v-bind:是单项绑定,下图中黄线存在,粉线不存在
注意点2:总结:v-bind单向绑定 v-model双向绑定
在这里插入图片描述

v-model只能用于表单元素,换句话说只作用于有value属性的标签(表单元素)
在这里插入图片描述

在这里插入图片描述

2.5el和data两种写法

在这里插入图片描述

el两种方法
在这里插入图片描述

data两种写法
在这里插入图片描述

说明点1:el两种用哪个都可以,但是data两种方式分情况,后续使用组件,data使用方式必须使用“函数式”,不然会报错。

data写法函数式的普通方式:data:function () {}
 data:function () {
console.log('@@@',this)  //指代vue对象
        return{
           name:"尚硅谷",
           address:"哈尔滨",
             }
}
data写法函数式的简化普通方式:data() {}
data() {
console.log('@@@',this)  //指代vue对象
    return{
        name:"尚硅谷",
        address:"哈尔滨",
        }
}
data的第二种写法箭头函数式:data:()=> {}
data:()=> {
      console.log('@@@',this)  //指代window对象
      return{
           name:"尚硅谷",
           address:"哈尔滨",
      }
}

针对函数式,箭头函数方式this指代window对象,普通方式this指代vue对象
在这里插入图片描述
在这里插入图片描述

2.6MVVM模型

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

2.7数据代理

锚点

2.7.1回顾Object.defineProperty()

回顾Object.defineProperty()方法,该方法可动态设置属性。
defineProperty(目标对象, key, {config})

注意点1:defineProperty中如果定义使用get()和set(),那么属性value和writable:true必须注释掉,不然报错
注意点2:如果defineProperty中只定义value属性,那么控制台赋值无效,即必须设置writable:true才能对person属性实现更新

let number = 18
let person = {
        name:"张三",
        sex:"男"
}

Object.defineProperty(person, "age", {
        value:18,
}

在这里插入图片描述
如果defineProperty()方法设置属性enumerable:true、writable:true、configurable:true就可实现跟局部定义变量属性一样的效果,可增删改

Object.defineProperty(person, "age", {
        value:18,
        enumerable:true,    //控制属性是否可以枚举(也就是是否可以遍历访问到),默认值是false
        writable:true,      //控制属性是否可以被修改,默认值是false
        configurable:true,   //控制属性是否可以被删除,默认值是false
}

在这里插入图片描述
defineProperty()方法定义get()和set()

Object.defineProperty(person, "age", {       
        //当有人读取person的age属性时,get函数(getter)就会被调用,且返回值就是age的值
        get() {
             console.log('有人读取age属性了')
             return number
         },
        // //当有人修改person的age属性时,set函数(setter)就会被调用,且会收到修改的具体值
         set(value) {
             console.log('有人修改age属性了')
            number = value
        }
    })

2.7.2何为数据代理

数据代理:通过一个对象代理对另一个对象中属性的操作(读/写)

 let obj = {x:100}
    let obj2 = {y:200}

    Object.defineProperty(obj2, "x", {
        get() {
            return obj.x
        },
        set(value) {
            obj.x = value
        }
})

在这里插入图片描述

2.7.3vue中的数据代理

问题:数据代理干了啥?

答案:
简单说:通过Object.defineProperty()方法把data对象所有属性添加到vm(Vue原型)对象上,且为每个属性指定一个getter/setter。
复杂说:首先vue把data对象所有属性添加到命名为_data的对象中,通过Object.defineProperty()方法把_data对象所有属性添加到vm(Vue原型)对象上,并为每一个添加到vm上的属性,都指定一个getter/setter,这样vm对象就有了属性name和address,不然你想操作属性只能使用_data.name_或者data.address,这样很不方便。
在这里插入图片描述

在这里插入图片描述

2.8事件处理

2.8.1事件的基本使用

注意点1:定义事件函数时,普通函数this指代vue对象,而箭头函数中this指代Window对象。
注意点2:定义事件没参数小括号()可省略,但是用在插值表达式使用一个函数返回值就必须带小括号(),比如 全名:{{fullName()}}。
注意点3:不被vue所管理的函数那么请使用箭头函数。
在这里插入图片描述

代码:

<button v-on:click="showInfo1">点我提示信息1(不传参)</button>
<button @click="showInfo2($event, 66)">点我提示信息2(不传参)</button>

var vm = new Vue({
        el: "#app",
        data: {},
        methods:{
            showInfo1(event) {
                console.log(event);
            },
            showInfo2(event, number) {
                console.log(event);  //指代事件对象
                console.log(number);
                console.log(this);  //箭头函数中指代Window对象,普通方法指代vue对象
            }
        }
    })

2.8.2 $event 对象

在事件处理函数中访问 DOM 原生事件 event 对象,可以使用特殊变量$event 对象传
入。

2.8.3事件的修饰符

在这里插入图片描述
在这里插入图片描述

事件修饰符举例说明:

1.默认<a>标签会跳转,想实现点击不跳转就设置@click.prevent=”事件函数”或者<a href="javascript:void(0);" >
2.阻止事件冒泡
捕获阶段:指由外往内
冒泡阶段:指由内到外
举例:2个div1,div2,都有点击事件,如果不设置事件修饰符stop,那么点击div2触发事件完成之后,还会触发div1事件,而设置stop修饰符后,不会触发冒泡阶段。

在这里插入图片描述

3.once:事件只触发一次(常用),即无论点击多少次按钮,按钮只触发一次。
4.capture:设置使用事件的捕获模式,不设置使用冒泡模式(由内向外触发事件函数);

使用事件的捕获模式 :不设置.capture,先执行showMsg(2),再执行showMsg(1),设置之后先执行showMsg(1),再执行showMsg(2)

 <div class="box1" @click.capture="showMsg(1)">
        div1
        <div class="box2" @click="showMsg(2)">
            div2
        </div>
</div>

showInfo(e){
   console.log(e.target)
}
5.self:只有event.target是当前操作的元素时才触发事件
举例:div和button都设置事件函数,如果div标签不设置.self,那么点击button按钮会调用2次函数,且输出event.target为:<button>点我提示信息</button>,如果div标签设置了.self那么只有点击div才会触发事件且输出event.target为:<div class="demo1"><button>点我提示信息</button></div>,而只点击button只会触发button的事件且输出event.target为:<button>点我提示信息</button><div class="demo1" @click.self="showInfo">
        <button @click="showInfo">点我提示信息</button>
</div>
6.passive:事件的默认行为立即执行,无需等待事件回调执行完毕
举例:定一个事件会计算10W次,如果不设置.passive,那么会等事件全部结束后,滚轮才会向下移动一个位置,而设置了.passive,那么滚轮会先移动而不会去等待事件执行是否结束。

在这里插入图片描述
事件的默认行为立即执行,无需等待事件回调执行完毕

<ul @wheel.passive="demo" class="list">
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
</ul>

demo(){
   for (let i = 0; i < 100000; i++) {
          console.log('#')
   }
   console.log('累坏了')
}

2.8.4键盘事件(键值修饰符)

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
两个隐藏小知识点:
1.事件修饰符和串行,比如:@click.stop.once
2.对于键盘按键想实现按Ctrl+y才调用,则使用@keyup.ctrl.y=”showInfo”

2.9条件渲染

锚点
在这里插入图片描述
在这里插入图片描述

注意点1:使用v-if和v-else-if和v-else时中间不可以中断,否则无效,比如:
在这里插入图片描述
注意点2:

假设我有3个<h2>标签想实现条件渲染,有3种方式可以实现并说明不同优缺点
方式1:<h2>标签加条件,缺点:太重复了

在这里插入图片描述

方式2:3个<h2>标签外绑定div条件控制,缺点:div也得知晓并设置样式,否则<h2>有样式而被div包裹后样式没了,即会改变结构

在这里插入图片描述

方式3(推荐):使用<template>标签,元素加载解析时会自动去掉<template>标签只保留<h2>标签,即不会改变结构,注意:<template>标签中只可以使用v-if,不能使用v-show,否则报错

在这里插入图片描述

2.10列表渲染

锚点

2.10.1 v-for

<li v-for="item in items">{{item.name}}</li>
列表渲染
    v-for
        可以把一组值进行列表渲染,语法形式: item  in items,
        items 是源数据数组并且 item 是数组元素迭代的别名。
        在 v-for 块中,对父作用域属性的完全访问权限。v-for 还支持一个可选的第二个参数为当前项的索引。
        v-for也可以遍历对象,可以指定三个形参:
            形式: v-for="(value, key, index) in object"
            value: 对象的值
            key: 对象的键
            index: 遍历的索引

在这里插入图片描述

2.10.2 key 属性(非常重要)

用 v-for 渲染列表时, 使用 key 属性给每个指定一个唯一的 ID 表示,那么可以在
下次数据渲染时,提高渲染速度。

<li v-for="item in items" :key="item.id">{{item.name}}</li>

注意:在 v-for 中:key非常重要,推荐每次都写:key
在这里插入图片描述

在这里插入图片描述

举例说明:默认存在3个标签且有值,有一个按钮效果是在最上面新增一行标签,此时会容易发生问题
点击按钮前:
在这里插入图片描述
点击按钮后:
在这里插入图片描述
结果:顺序乱了?详细原因如下图,对比相同就复用,对比不同就重新生成DOM
在这里插入图片描述

注意点1:默认不写:key时,解析DOM会自动加上数组index
注意点2::key最好绑定数据唯一标识,身份证、手机号、库表id等,这样无论在数组什么位置插入,哪怕是数组开头或者数组结尾,都不会影响结构。
注意点3:虚拟DOM存在于内存中,而用户操作的页面标签属于真实DOM

2.10.3 取值范围

v-for 也可以指定整数,用来重复多次使用模板。

<li v-for="i in 5">第 {{i}} 次</li>

2.10.4列表过滤

举例:针对

  • 内容进行过滤,根据用户输入筛选内容,要求使用computed和watch两种方式实现
    在这里插入图片描述

注意点1:列表过滤使用.filter(),它和自定义过滤器不是同一个东西。
列表过滤器.filter()用在方法中,而自定义过滤器用在插值表达式和 v-bind 表达式中。
注意点2:.filter会生成新数据,不会修改原数据结构。
注意点3:如果computed和watch两种方式都可以实现,推荐优先使用计算属性computed

方式一:computed

<div id="root">
			<h2>人员列表</h2>
			<input type="text" placeholder="请输入名字" v-model="keyWord">
			<ul>
				<li v-for="(p,index) of filPerons" :key="index">
					{{p.name}}-{{p.age}}-{{p.sex}}
				</li>
			</ul>
		</div>

new Vue({
				el:'#root',
				data:{
					keyWord:'',
					persons:[
						{id:'001',name:'马冬梅',age:19,sex:'女'},
						{id:'002',name:'周冬雨',age:20,sex:'女'},
						{id:'003',name:'周杰伦',age:21,sex:'男'},
						{id:'004',name:'温兆伦',age:22,sex:'男'}
					]
				},
				computed:{
					filPerons(){
						return this.persons.filter((p)=>{
							return p.name.indexOf(this.keyWord) !== -1
						})
					}
				}
			}) 

方式二:watch

new Vue({
				el:'#root',
				data:{
					keyWord:'',
					persons:[
						{id:'001',name:'马冬梅',age:19,sex:'女'},
						{id:'002',name:'周冬雨',age:20,sex:'女'},
						{id:'003',name:'周杰伦',age:21,sex:'男'},
						{id:'004',name:'温兆伦',age:22,sex:'男'}
					],
					filPerons:[]
				},
				watch:{
					keyWord:{
						immediate:true,
						handler(val){
							 this.filPerons = this.persons.filter((p)=>{
								return p.name.indexOf(val) !== -1
							})
						}
					}
				}
			})

2.10.5列表排序

注意点1:列表排序使用.sort()方法,其中sort(参数1,参数2)有两个参数,参数2-参数1为降序,参数1-参数2为升序,具体查看。
https://blog.csdn.net/weixin_46665162/article/details/112966823
注意点2:会引起自身数据的改变。
举例:对列表过滤的数据进行升降序
注意点3:.sort()方法会更改原数据结构,比如更改原数组顺序
在这里插入图片描述

<div id="root">
			<h2>人员列表</h2>
			<input type="text" placeholder="请输入名字" v-model="keyWord">
			<button @click="sortType = 2">年龄升序</button>
			<button @click="sortType = 1">年龄降序</button>
			<button @click="sortType = 0">原顺序</button>
			<ul>
				<li v-for="(p,index) of filPerons" :key="p.id">
					{{p.name}}-{{p.age}}-{{p.sex}}
					<input type="text">
				</li>
			</ul>
		</div>

new Vue({
				el:'#root',
				data:{
					keyWord:'',
					sortType:0, //0原顺序 1降序 2升序
					persons:[
						{id:'001',name:'马冬梅',age:30,sex:'女'},
						{id:'002',name:'周冬雨',age:31,sex:'女'},
						{id:'003',name:'周杰伦',age:18,sex:'男'},
						{id:'004',name:'温兆伦',age:19,sex:'男'}
					]
				},
				computed:{
					filPerons(){
						const arr = this.persons.filter((p)=>{
							return p.name.indexOf(this.keyWord) !== -1
						})
						//判断一下是否需要排序
						if(this.sortType){
							arr.sort((p1,p2)=>{
								return this.sortType === 1 ? p2.age-p1.age : p1.age-p2.age
							})
						}
						return arr
					}
				}
			}) 

2.10.6 Vue监测“对象”数据改变的原理

注意点1:vue监测数据原理就是,给每个data属性添加get()和 set()方法,即data属性改变 =》调用set() =》 重新渲染页面值改变。

注意点2:加载流程:
1)加载data属性,加工封装get()和 set()方法
2)vue._data=data,这样控制台点开vue实例就会看到一堆属性及方法了

举例:模拟data对象属性值改变了,页面值也跟着改变,即实现vue监测数据改变效果

let data = {
				name:'尚硅谷',
				address:'北京',
			}

			//第1步:创建一个监视的实例对象,用于监视data中属性的变化
			const obs = new Observer(data)		
			console.log(obs)	

			//第2步:准备一个vm实例对象
			let vm = {}
			vm._data = data = obs
            
//第3步:定义观察者函数
			function Observer(obj){
				//汇总对象中所有的属性形成一个数组
				const keys = Object.keys(obj)
				//遍历
				keys.forEach((k)=>{
					Object.defineProperty(this,k,{  //this指代观察者对象,而不是vue实例
						get(){
							return obj[k]
						},
						set(val){
							console.log(`${k}被改了,我要去解析模板,生成虚拟DOM.....我要开始忙了`)
							obj[k] = val
						}
					})
				})
			}

2.10.7 Vue.set()或者vm.$set()动态新增标签

锚点
Vue.set()和vm.$set() =》 相同效果。
主要讲解Vue.set()方法是什么?
在这里插入图片描述

注意点 1:Vue.set()方法有局限性,不能给vue实例或者data的直接属性进行添加,只能作用于data下面的某个属性对象。

举例:比如动态添加“校长属性”,即动态给data属性下面的school对象添加“校长属性”
在这里插入图片描述

<body>
		<!-- 准备好一个容器-->
		<div id="root">
			<h1>学校信息</h1>
			<h2>学校名称:{{school.name}}</h2>
			<h2>学校地址:{{school.address}}</h2>
			<h2>校长是:{{school.leader}}</h2>
			<hr/>
			<h1>学生信息</h1>
			<button @click="addSex">添加一个性别属性,默认值是男</button>
			<h2>姓名:{{student.name}}</h2>
			<h2 v-if="student.sex">性别:{{student.sex}}</h2>
			<h2>年龄:真实{{student.age.rAge}},对外{{student.age.sAge}}</h2>
			<h2>朋友们</h2>
			<ul>
				<li v-for="(f,index) in student.friends" :key="index">
					{{f.name}}--{{f.age}}
				</li>
			</ul>
		</div>
	</body>

	<script type="text/javascript">
		Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。

		const vm = new Vue({
			el:'#root',
			data:{
				school:{
					name:'尚硅谷',
					address:'北京',
				},
				student:{
					name:'tom',
					age:{
						rAge:40,
						sAge:29,
					},
					friends:[
						{name:'jerry',age:35},
						{name:'tony',age:36}
					]
				}
			},
			methods: {
				addSex(){
					// Vue.set(this.student,'sex','男')
					this.$set(this.student,'sex','男')
				}
			}
		})
	</script>

2.10.8Vue监测“数组”数据改变的原理

问题1:vue实例对象针对数组元素并没有提供类似get和set方法,为啥也会实现页面响应式监听?

在这里插入图片描述
答案:因为vue对数组的部分基本方法进行了二次封装,在继承方法的使用效果同时,也进行了响应式更新DOM。
在这里插入图片描述

举例:爱好列表
在这里插入图片描述

<div id="root">
    <h2>爱好</h2>
    <ul>
        <li v-for="(h,index) in student.hobby" :key="index">
            {{h}}
        </li>
    </ul>
</div>

const vm = new Vue({
        el:'#root',
        data:{
            student:{
                hobby:['抽烟','喝酒','烫头']
            }
        }
    })

2.10.9总结vue数据监测

在这里插入图片描述

在这里插入图片描述

问题:什么叫数据劫持?

定义:指的是在访问或者修改对象的某个属性时,通过一段代码拦截这个行为,进行额外的操作或者修改返回结果。比如:拦截data各属性,添加额外的get和set方法到vue实例的_data对象中。

2.11 表单输入绑定

锚点
用 v-model 指令在表单控件元素上创建双向数据绑定。它会根据控件类型自动选取
正确的方法来更新元素。
在这里插入图片描述
在这里插入图片描述

小技巧:

1.针对input输入框想实现点击名字,光标自动定位到输入框,label设置for属性和input设置id属性即可

<label for="account">账号:</label>
<input type="text" id="account" v-model.trim="userInfo.account"> <br/><br/>

2.针对radio想实现二选一,需要设置相同name属性值,同时配置value值
3.针对radio或者select标签想实现“默认选中”,不用设置checked,只需要设置data中属性值即可
4.表单提交方式

方式1:button绑定事件
<button @click=”xx”></button>
--------------------------------------------------------------------------------------------
方式2:<form>标签设置<form @submit.prevent="demo">

5.阻止表单提交后刷新页面操作,使用事件修饰符.prevent
6.form表单提交中如何一口气获取全部数据打印输出?

方式1:定义对象接收全部参数
new Vue({
        el:'#root',
        data:{
            userInfo:{
                account:'',
                password:'',
                age:18,
                sex:'female',
                hobby:[],
                city:'beijing',
                other:'',
                agree:''
            }
        }

console.log(JSON.stringify(this.userInfo))
--------------------------------------------------------------------------------------------
方式2:使用this._data,虽说this._data除了属性还有get和set方法,但是打印的时候不会输出这些,并不影响。
console.log(JSON.stringify(this._data))

7.针对年龄标签,防止输入字母,或者防止默认是数字但重新输入后传值为字符串,需同时设置type=”number”和v-model.number

<input type="number" v-model.number="userInfo.age">

8.针对checkbox注意点1,考虑是否需要配置input标签的value值,比如:如果是爱好等多选就需要设置;如果是是否同意协议等check标签就不需要设置
9.针对checkbox注意点2,data属性值默认设置字符串和数组效果时不一样的

2.11.1 文本 text

2.11.2 复选框

单个使用时 v-model 是逻辑值: true 和 false,多个一起使用需要指定 value 值,
选中结果绑定 v-model 的数组。

2.11.3 单选框

2.11.4选择列表

2.11.5修饰符

在这里插入图片描述

2.12计算属性与监听属性

2.12.1计算属性computed

在这里插入图片描述

注意点1:只要data任意值发生改变,vue肯定会重新解析模板。比如{{fullName()}},插值表达式使用fullName()函数,那么当vue重新解析模板时,就会重新执行一遍fullName()函数,因为data任意值改变了,vue也不知道fullName()函数中是否引用了data中改变的属性,所以会选择直接重新执行一遍fullName()函数。
注意点2:默认提供了缓存机制,实际上计算属性就是调用了fullName的get()方法,get什么时候调用?1.初次读取fullName时 2.所依赖的数据发生变化时。
注意点3:既然fullName是个对象,那我插值表达式可以使用{{fullName.get()}}?
答案:不能这样使用,只有data配置和methods配置可以调用,计算配置不能这么调用,会报错fullName中get()方法不存在。
注意点4:methods定义的方法,在插值表达式使用要加(),{{fullName()}},如果是计算属性中监听的属性,则写成{{fullName}}

举例:计算“全名”标签,由“姓-名”构成
在这里插入图片描述
思路:
方式1:用插值表达式拼,(缺点:万一对字符串进行分割、转换大小写、截取长度等等操作显得表达式太长,不易解读)
全名:{{firstName}}-{{lastName}}



方式2:定义函数写在methods配置中(缺点:不提供缓存,有几个fullName()调用就会执行几次)

全名:
{{fullName()}}

全名:
{{fullName()}}



方式3:定义计算属性(推荐使用,有缓存),代吗如下↓

全名:<span>{{fullName}}</span> <br/><br/>

computed:{
				fullName:{
					//get有什么作用?当有人读取fullName时,get就会被调用,且返回值就作为fullName的值
					//get什么时候调用?1.初次读取fullName时。2.所依赖的数据发生变化时。
					get(){
						console.log('get被调用了')
						// console.log(this) //此处的this是vm
						return this.firstName + '-' + this.lastName
					},
					//set什么时候调用? 当fullName被修改时。
					set(value){
						console.log('set',value)
						const arr = value.split('-')
						this.firstName = arr[0]
						this.lastName = arr[1]
					}
				}
			}

2.12.2(简写)计算属性

注意点1:计算属性只有在没有set方法时才能使用简写
注意点2:

问题:插值表达式中使用data配置、methods配置和计算配置时,区分何时带()?何时不能带()?

答案:
针对data配置都不带()
针对methods配置有形参带(),没有形参()可省略
针对计算配置也不带(),带()会报错

全名:<span>{{fullName}}</span> <br/><br/>

computed:{
				//完整写法
				 fullName:{
					get(){
						console.log('get被调用了')
						return this.firstName + '-' + this.lastName
					},
					set(value){
						console.log('set',value)
						const arr = value.split('-')
						this.firstName = arr[0]
						this.lastName = arr[1]
					}
				} 
				//简写
				fullName(){
					console.log('get被调用了')
					return this.firstName + '-' + this.lastName
				}
			}

2.12.3计算属性-天气案例

该案例为了讲述1个坑,1个技巧

案例说明:今天天气很【炎热/凉爽】,点击按钮进行切换
源代码如下:
在这里插入图片描述
在这里插入图片描述

<div id="root">
			<h2>今天天气很{{info}}</h2>
			<!-- 绑定事件的时候:@xxx="yyy" yyy可以写一些简单的语句 -->
			<!-- <button @click="isHot = !isHot">切换天气</button> -->
			<button @click="changeWeather">切换天气</button>
</div>

const vm = new Vue({
			el:'#root',
			data:{
				isHot:true,
			},
			computed:{
				info(){
					return this.isHot ? '炎热' : '凉爽'
				}
			},
			methods: {
				changeWeather(){
					this.isHot = !this.isHot
				}
			},
		})

注意点1:(1个坑指的是),假设页面显示的是“今天天气很好”,也就是页面压根没用到info属性,而代码中却定义了计算属性及方法,那么会发生的坑是,点击按钮后Vue插件显示结果没变动,但是实际控制台info结果已经改变了,也就是说因为页面没用到属性所以插件就不更新值了,但是实际info值已经改变了。
注意点2:(1个技巧指的是),假设定义方法逻辑很简单,可以直接这样写@click=“isHot = !isHot”,也是生效的。
在这里插入图片描述

在这里插入图片描述

2.12.4监听属性watch

配置watch关键字和handler()方法实现监听
在这里插入图片描述

写法1:.new Vue是配置

const vm = new Vue({
watch:{
				isHot:{
					immediate:true, //初始化时让handler调用一下
					//handler什么时候调用?当isHot发生改变时。
					handler(newValue,oldValue){
						console.log('isHot被修改了',newValue,oldValue)
					}
			}
}

写法2:首先保证vue实例已经创建完了,在vue实例下面,通过vm.$watch配置

vm.$watch('isHot',{
			immediate:true, //初始化时让handler调用一下
			//handler什么时候调用?当isHot发生改变时。
			handler(newValue,oldValue){
				console.log('isHot被修改了',newValue,oldValue)
			}
		})
注意点1:什么场景下使用写法1 和写法2呢?
答案:创建vue实例时已经明确知道监听什么属性时就使用写法1,而如果创建vue实例时不知道监视谁,而是后续根据用户业务行为才知道要监视谁就使用写法2

注意点2:vm.$watch(参数1,参数2)有两个参数,参数2为{}配置对象,参数1表示你要监视的属性名,注意名字要加引号“引号”标识,如果直接写vm.$watch(isHot,参数2)这是错误的,会报如下错误,原因在于写法1中的isHot不会触发“读取变量”,而写法2会触发“读取变量”,所以写法2中属性名必须加“引号”。

在这里插入图片描述

2.12.5监听属性watch-深度监听

在这里插入图片描述

举例:data配置numbers对象,其中有属性a和b,我想监听numbers,只要numbers中任意属性值改变了,我就打印一条语句。

<h3>a的值是:{{numbers.a}}</h3>
<button @click="numbers.a++">点我让a+1</button>
<h3>b的值是:{{numbers.b}}</h3>
<button @click="numbers.b++">点我让b+1</button>

const vm = new Vue({
			el:'#root',
			data:{
				numbers:{
					a:1,
					b:1
				}
			},
			watch:{
				numbers:{
						deep:true, //开启深度监视,监视多级结构中所有属性的变化
						handler(){
						  console.log('numbers改变了')
					   }
				}
			}
})

注意点1:默认deep为false,不进行深度监视,这样效率快
注意点2:如果如图1这么写,不配置deep=true的话,那么watch配置会让vue实例监视的是整个numbers的地址,而不是咱们想实现的监视numbers对象内部任意属性值a或者b的变化,因为如图2,watch配置会让vue实例默认监视的是“粉色框”的地址值是否改变,而不是监视“绿色框”中属性a和b的值是否改变,哪怕属性a或者b值改变了,但是numbers对象整体地址没改变,那么被watch配置的vue实例就会觉得监视值未改变,所以如果想实现深度结构监控,请设置deep=true
记住:配置watch是为了作用于vue实例怎么怎么怎么地。
在这里插入图片描述
在这里插入图片描述

2.12.6监听属性watch-(简写)深度监听

watch和 vm.$watch都有2种写法:

问题:什么情况下使用简写方式?

答案:当监听属性中只用到handler()方法,而没有其他配置(比如immediate或者deep)时,就可以使用简写方式。

watch:{
	//正常写法
	isHot:{
		// immediate:true, //初始化时让handler调用一下
		// deep:true,//深度监视
		handler(newValue,oldValue){
			console.log('isHot被修改了',newValue,oldValue)
		}
	}, 
	//简写
	isHot(newValue,oldValue){
		console.log('isHot被修改了',newValue,oldValue,this)
	} 
}
-------------------------------------------------------------------------------------------------
//正常写法
vm.$watch('isHot',{
	immediate:true, //初始化时让handler调用一下
	deep:true,//深度监视
	handler(newValue,oldValue){
		console.log('isHot被修改了',newValue,oldValue)
	}
}) 
-------------------------------------------------------------------------------------------------
//简写
vm.$watch('isHot',function(newValue,oldValue){
	console.log('isHot被修改了',newValue,oldValue,this)
}) 

2.12.7计算属性和监视属性区别

举例说明:天气案例

计算属性

data:{
	firstName:'张',
		lastName:'三'
	},
	computed:{
		info(){
			return this.firstName + “-” + this.lastName
		}
	},

监视属性

data:{
	firstName:'张',
			lastName:'三',
			fullName:'张-三'
		},
		watch:{
			firstName(val){
					this.fullName = val + '-' + this.lastName
			},
			lastName(val){
				this.fullName = this.firstName + '-' + val
			}
		}

区别:

注意点1:如果计算属性computed和监视属性watch都可以实现,推荐使用计算属性,因为代码最少
注意点2:计算属性computed不能使用异步操作,比如睡一秒再执行操作等,而监视属性watch可以进行异步操作
注意点3:为了使用this指代vue对象,那么使用计算属性computed的同步操作,必须写普通函数(因为计算属性computed被vue管理),如果使用监视属性watch的异步操作等(不被vue所管理的函数)那么请使用箭头函数,
(即:
计算属性使用同步操作的普通函数,this => vue,
计算属性使用同步操作的箭头函数,this => window

监视属性使用同步操作的普通函数,this => vue,
监视属性使用同步操作的箭头函数,this => window,
监视属性使用异步操作的普通函数,this => window,
监视属性使用异步操作的箭头函数,this => vue,具体原因看下面图
)。
在这里插入图片描述

2.13绑定样式

2.13.1绑定class

在这里插入图片描述

data:{
	name:'尚硅谷',
		mood:'normal',
		classArr:['atguigu1','atguigu2','atguigu3'],
		classObj:{
			atguigu1:false,
			atguigu2:false,
		}
}

2.13.2绑定style

在这里插入图片描述

data:{
	styleObj:{
			fontSize: '40px',
				color:'red',
			},
	styleObj2:{
				backgroundColor:'orange'
			},
	styleArr:[
				{
					fontSize: '40px',
					color:'blue',
				},
				{
					backgroundColor:'gray'
				}
			]
}

2.14自定义过滤器

在这里插入图片描述

Vue允许自定义过滤器,可被用作一些常见的文本格式化。
过滤器可以用在两个地方:mustache 插值表达式和 v-bind 表达式 (后者从 2.1.0+ 开始支持)。
注意点1:过滤器无形参时,默认也会把前面参数传给过滤器,举例:{{time | timeFormater}},默认会把time当作第一个参数传给timeFormater
注意点2:过滤器有形参时,前面的参数还是当作第一个参数,而形参默认当作第二个参数,举例:{{time | timeFormater(‘YYYY_MM_DD’)}},time 为形参1,’YYYY_MM_DD’为形参2
注意点3:过滤器可串行使用:{{ message | filterA | filterB }}
注意点4:过滤器并没有改变原本数据
注意点5:“ES6默认参数”机制(可用在方法中) =》举例:timeFormater方法的第二个参数str,如果有传值就用传递过来的值,如果str为空,就用默认的值YYYY年MM月DD日 HH:mm:ss

filters:{
	timeFormater(value,str='YYYY年MM月DD日 HH:mm:ss'){
			return dayjs(value).format(str)
				}
			}

注意点6:过滤器应该被添加在 JavaScript 表达式的尾部,由“管道符”指示:

<!-- in mustaches -->
{{ message | capitalize }}
<!-- in v-bind -->
<div v-bind:id="name| upperCase ">hei</div>

注意点7:使用Vue.filter定义全局过滤器,使用filters在组件内指定局部过滤器。

<div id="root">
    <h4>{{name | upperCase | length | test('A-','-B')}}</h4>
</div>
<script>
    /***
     * filter:过滤器
     * */
    var vm = new Vue({
        el: '#root',
        data: {
            name: 'hello'
        },
        filters: {
            upperCase: function (value) {
                return value.toUpperCase();
            },
            length: function (value) {
                return value+value.length;
            },
            //在value两边加点东西
            test: function (value, begin, end) {
                console.log(value, begin, end);
                return begin+value+end;
            }
        }
    });
</script>

在这里插入图片描述

2.15内置指令

就是介绍下vue自带的但是我们不常用到的指令

2.15.1 v-cloak指令

在这里插入图片描述

举例说明:比如网页上方有个{{name}}属性,在<div>标签下面</body>的上面写个js引入文件,如果js引入出现网络延迟,那么出现的现象是页面只显示{{name}},而没有走到实例化vue去解析页面内容,这样用户体验极差,正常效果是要么不显示name,要么解析好了直接显示name属性值。

解决方案:标签设置 v-cloak特殊属性,并配合css样式display:none进行隐藏内容,默认网页元素加载时隐藏{{name}}属性所在的标签,当实例化vue完毕后会自动删除v-cloak特殊属性,从而达到显示name属性值的作用。
<head>
		<meta charset="UTF-8" />
		<title>v-cloak指令</title>
		<style>
            //[v-cloak]代表选中所有带v-cloak的标签
			[v-cloak]{
				display:none;
			}
		</style>
		<!-- 引入Vue -->
	</head>
	<body>		
		<!-- 准备好一个容器-->
		<div id="root">
			<h2 v-cloak>{{name}}</h2>
		</div>
		<script type="text/javascript" src="http://localhost:8080/resource/5s/vue.js"></script>
	</body>
	
	<script type="text/javascript">
		console.log(1)
		Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
		
		new Vue({
			el:'#root',
			data:{
				name:'尚硅谷'
			}
		})
	</script>

2.15.2 v-pre指令

在这里插入图片描述

注意点1:加了v-pre后,vue解析到红色框时,就会跳过该行了,不会去判断当前行是否有指令和插值表达式之类的。

2.16.自定义指令

除了默认设置的核心指令 (v-model 和 v-show),Vue 也允许注册自定义指令。
在这里插入图片描述

2.16.1基本使用

1)定义

注意点1:定义全局指令使用Vue.directive,定义局部指令使用directives。
注意点2:自定义指令时不需要加v-,而标签使用时需要加v-自定义指令名
注意点3:只定义指令可以用在很多地方,包括:标签属性、标签体内容、绑定事件…
注意点4:

问题:自定义函数何时被调用?

答案:
1)指令与元素成功绑定时(一上来)
2)指令所在的模板被重新解析时,比如下方图片,无论data中属性name或者属性n只要其中任意一个发生值改变,上面的红框div模板就会进行重新解析
在这里插入图片描述

注意点5:自定义指令有两个形参,形参1代表:自定义指令所在的标签,如图1,形参2:代表绑定的所有信息封装一个成对象给你,如图2,既然形参1能获取自定义指令所在的标签,那么指令用在标签属性、标签体内容、绑定事件上,就都可以实现了。
在这里插入图片描述
图1:形参1
在这里插入图片描述

图2:形参2

//自定义全局指令v-focus
Vue.directive('focus',{
    //当绑定元素插入到DOM调用
    inserted: function (el) {
        //元素获取焦点
        el.focus();
    }
});

使用directive定义,第一个参数为指令名,使用时加上v-前缀才能生效。inserted属性指当绑定元素插入到DOM时调用。
定义局部指令使用directives:

//定义局部指令使用directives
var app = new Vue({
    el:'#app',
    directives:{
        focus:{
            inserted: function (el) {
                //元素获取焦点
                el.focus();
            }
        }
    }
});

2)使用

<div id="app">
    <input type="text" v-focus>
</div>

2.16.2钩子函数

指令定义函数提供了几个钩子函数 (可选):

  • bind:只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个在绑定时执行一次的初始化动作。
  • inserted:被绑定元素插入父节点时调用 (父节点存在即可调用,不必存在于 document 中)。
  • update:所在组件的 VNode 更新时调用,但是可能发生在其孩子的 VNode 更新之前。指令的值可能发生了改变也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 。
  • componentUpdated:所在组件的 VNode 及其孩子的 VNode 全部更新时调用。
  • unbind:只调用一次,指令与元素解绑时调用。

钩子函数的参数有4个:
1)el:当前指令绑定元素
2)binding:当前指令绑定的所有信息对象,有以下属性:

  • name:指令名,不包括 v- 前缀。
  • value:指令的绑定值,例如:v-my-directive=“1 + 1”, value 的值是 2。
  • oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
  • expression:绑定值的字符串形式。例如 v-my-directive=“1 + 1” ,expression 的值是 “1 + 1”。
  • arg:传给指令的参数。例如 v-my-directive:foo,arg 的值是 “foo”。
  • modifiers:一个包含修饰符的对象。例如:v-my-directive.foo.bar, 修饰符对象 modifiers 的值是 { foo: true, bar: true }。

3)vnode:Vue 编译生成的虚拟节点
4)oldVnode:上一个虚拟节点,仅在 update 和 componentUpdated
钩子中可用。

<div id="app">
    <input type="text" v-demo:arg.a.b="1+1">
</div>
<script>
    Vue.directive('demo',{
        bind: function (el,binding) {
            console.log(el);
            console.log(binding);
        }
    });
    var app = new Vue({
        el:'#app'
    });
</script>

在这里插入图片描述

2.16.3实例图片懒加载

谷歌图片的加载做得非常优雅,在图片未完成加载前,用随机的背景色占位,图片加载完成后才直接渲染出来,用自定义指令可以非常方便的实现这个功能。

1)样式

<style>
    .item, .item img{
        width: 200px;
        height: 120px;
        float: left;
    }
</style>

2)自定义v-img指令

//定义全局自定义指令v-img
Vue.directive('img',{
    bind: function (el,binding) {
        //生成随机颜色
        var color = parseInt(Math.random()*0xFFFFFF).toString(16);
        //设置当前元素的背景,提前进行占位等待图片加载
        el.style.background = '#'+color;
        //setTimeout模拟图片加载的延时情况
        setTimeout(function () {
            //创建图片对象
            var img = new Image();
            //通过binding对象获取真实的图片url
            img.src = binding.value;
            //将图片元素插入DOM结构
            el.appendChild(img);
            //随机延时
        },Math.random()*3000+500);
    }
});

3)模拟数据

var app = new Vue({
    el:'#app',
    data:{
        //定义模拟数据
        imgs:[
            {url:'img/01.jpg'},
            {url:'img/02.jpg'},
            {url:'img/03.jpg'},
            {url:'img/04.jpg'}
        ]
    }
});

4)使用

<div id="app">
    <div v-img="item.url" v-for="item in imgs" class="item"></div>
</div>

5)效果

在这里插入图片描述

本人其他相关文章链接

1.《基础篇第1章:vue2简介》包含Vue2知识点、个人总结的使用注意点及碰到的问题总结

2.《基础篇第2章:vue2基础》包含Vue2知识点、个人总结的使用注意点及碰到的问题总结

3.《进阶篇第3章:vue进阶-组件》包含组件、自定义事件、插槽、路由等等扩展知识点

4.《基础篇第4章》:使用vue脚手架创建项目

5.vue2知识点:数据代理

6.vue2知识点:事件处理

7.vue2知识点:列表渲染(包含:v-for、key、取值范围、列表过滤、列表排序、vue监视对象或数组的数据改变原理、总结vue数据监测)

8.vue2知识点:计算属性与监听属性

9.vue2知识点:生命周期(包含:生命周期介绍、生命周期钩子、整体流程图详解)

10.vue2知识点:非单文件组件和单文件组件

11.vue2知识点:组件is属性

12.vue2知识点:组件模板定义

13.vue2知识点:组件的props属性、非props属性、props属性校验

14.vue2知识点:组件自定义事件

15.vue2知识点:组件插槽分发

16.vue2知识点:动态组件

17.vue2知识点:混入

18.vue2知识点:浏览器本地缓存

19.vue2知识点:全局事件总线(GlobalEventBus)

20.vue2知识点:消息订阅与发布

21.vue2知识点:nextTick语法

22.vue2知识点:Vue封装的过度与动画

23.vue2知识点:路由

24.vue2知识点:vm调用待$命令介绍

25.vue组件通信案例练习(包含:父子组件通信及平行组件通信)

26.vue表单案例练习:vue表单创建一行数据及删除数据的实现与理解

27.vue2基础组件通信案例练习:待办事项Todo-list案例练习

28.vue2基础组件通信案例练习:把案例Todo-list改写成本地缓存

29.vue2基础组件通信案例练习:把案例Todo-list改成使用自定义事件

30.vue2基础组件通信案例练习:把案例Todo-list改成使用全局事件总线

31.vue2基础组件通信案例练习:把案例Todo-list改成使用消息订阅与发布

32.vue2基础组件通信案例练习:把案例Todo-list新增编辑按钮

33.vue2基础组件通信案例练习:把案例Todo-list改成使用动画与过度

34.学习vue2遇到过的问题及个人总结

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/106209.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!