模板语法
vue:
1.插值语法:
功能:用于解析标签体内容
写法:{{xxx}},xxx是js表达式,且可以直接读取data中的所有属性
2.指令语法:
功能:用于解析标签(包括标签属性、标签体内容、绑定事件)
属性:必须是一个js表达式
<div id="root">
<h1>插值语法,放在标签体中</h1>
<h3>你好,{{name}}</h3>
<h1>指令语法,用在标签属性</h1>
<a v-bind:href="url">尚硅谷</a>
<a :href="url"></a>
<h1>单向数据绑定</h1>
单向数据绑定:
<input type="text" :value="name"><br>
双向数据绑定:
<input type="text" v-model:value="name">
<input type="text" v-model="name">
</div>
事件处理
vue中的事件修饰符:
* 1.prevent:阻止默认事件(常用)
* 2.stop:阻止冒泡事件(常用)
* 3.once:事件只触发一次(常用)
* 4.capture:使用事件的捕获模式
* 5.self:只有event.target是当前操作的元素的才触发
* 6.passive:事件的默认行为立即执行,无需等待事件回调执行完毕
<!--阻止默认事件发生,加上prevent修饰符后跳转事件不在发生-->
<a href="http://www.baidu.com" @click.prevent="showInfo()">点我跳转到百度</a>
<!--阻止事件冒泡-->
<div class="demo" @click="showInfo()">
<button @click.stop="showInfo2()">点我跳转到百度2</button>
</div>
<!--事件只触发一次-->
<button @click.once="showInfo2()">点我跳转到百度2</button>
<!--使用事件的捕获模式(捕获的同时触发事件) tips:捕获由外向内,触发由内向外-->
<div class="box1" @click.capture="showInfo()">
div1
<div class="box2" @click="showInfo2()">
div2
</div>
</div>
内置指令
vue内置指令:
v-bind : 单向绑定解析表达式,可简写为 :xxx
v-model : 双向数据绑定
v-for : 遍历数组/对象/字符串
v-on : 绑定事件监听,可简写为@
v-if : 条件渲染(动态控制节点是否存在)
v-else-if: 条件渲染(动态控制节点是否存在)
v-else : 条件渲染(动态控制节点是否存在)
v-show : 条件渲染(动态控制节点是否显示)
v-text:
1.作用:向其所在的节点中渲染文本内容
2.与插值语法的区别:v-text会替换掉节点中的内容,{{xxx}}不会
v-html:
1.作用:向指定节点中渲染包含HTML结构的内容
2.与插值语法的区别:
(1)v-html会替换掉节点中的内容,{{xxx}}不会
(2)v-html可以识别html结构,支持HTML结构解析,其他和v-text差不多
3.严重注意:v-html有安全性问题!!
(1)在网站上动态渲染任意html是非常危险的,容易导致xss攻击
(2)一定要在可信的内容上使用v-html,永远不要用在用户提交的内容上
v-cloak:
1.本质上是一个特殊属性,vue实例创建完毕并接管容器后,会删掉v-cloak属性
2.使用css配合v-cloak可以解决网速慢时页面展示出{{xxx}}的问题
v-once:
1.v-once所在的节点在初次动态渲染后,就视为静态内容了
2.以后的数据的改变不会引起v-once所在结构的更新,可以用于优化性能
v-pre:
1.跳过其所在节点的编译过程
2.可利用它跳过:没有指令的语法、没有使用插值语法的节点,会加快编译
<!--v-cloak测试-->
<div>
<div v-cloak>你好,{{name}}</div>
<div v-text="msg">付东</div>
<div v-html="str"></div>
</div>
<br><br>
<!--v-once测试-->
<div>
<h2 v-once>初始化的N值是:{{n}}</h2>
<h2>当前的N值是:{{n}}</h2>
<button @click="n++">加1</button>
</div>
<!--v-pre指令测试-->
<div>
<h2 v-pre>vue功能很强大</h2>
<h2 v-pre a="1">当前的N值是:{{n}}</h2>
<button v-pre @click="n++">加1</button>
</div>
计算属性
/*
* 计算属性
* 当计算属性被调用时,会自动调用计算函数;或者当计算的值发生改变时也会调用计算属性(原理:vue值改变,模板会重新渲染,也就会重新调用计算属性函数改变值)
* */
/*
* computed和watch的区别:
* (1)computed能完成的功能,watch都可以完成
* (2)watch能完成的工作,computed不一定能完成。例如:watch可以进行异步操作
*
* 两个重要的小原则:
* 1.所被vue管理的函数,最好写成普通函数,这样this的指向才是vm或组件实列对象。
* 2.所有不被vue管理的函数(定时器的回调函数,Ajax的回调函数、promise的回调函数等),最好写成箭头函数,这样this的指向才是vm或组件实例对象
* */
<div id="root">
<h3>今天天气很{{info}}</h3>
<button @click="change()">切换天气</button>
</div>
computed: {
info: function (){
return this.isTrue? "炎热":"凉爽";
}
监视属性
//vue 监视属性变化
watch: {
//watch的正常写法
isHot: {
//初始化时让handler立即调用
immediate: true,
//handler什么时候被调用,isHot发生改变时被调用;还可以接收修改的值以及修改后的值
handler(newValue, oldValue){
console.log(newValue);
console.log("ishot被修改了");
console.log(oldValue);
}
},
/* //简写形式
isHot(newValue, oldValue){
// 不使用immediate和deep等其他属性可以使用
console.log(newValue);
console.log("简写ishot被修改了");
console.log(oldValue);
},*/
/* // 第二种监视写法
vm.$watch('isHot', {
//初始化时让handler立即调用
immediate: true,
//handler什么时候被调用,isHot发生改变时被调用;还可以接收修改的值以及修改后的值
handler(newValue, oldValue){
console.log(newValue);
console.log("ishot被修改了");
console.log(oldValue);
}
})*/
深度监视
data: {
isHot: true,
number: {
a: 1,
b: 1,
}
},
//vue深度监视字典里的值写法
'number.a':{
handler(newValue, oldValue) {
console.log("a被修改了");
},
},
//监视多级结构中任意属性的变化
'number':{
//深度监视
deep: true,
handler(){
console.log('检测number中任意值改变');
}
},
绑定calss样式
<!--mood、arr、classobj都指的是style的样式-->
<div id="root">
<!--绑定class样式,字符串写法:适用于样式的类名不确定,需要动态指定-->
<div class="basic" :class="mood" @click="changeMood()">{{name}}</div>
<!--绑定class样式,数组写法:要绑定的样式个数不确定,名字也不确定-->
<div class="basic" :class="arr">{{name}}</div>
<!--绑定class样式,对象写法:要绑定的样式个数名字确定,但要动态决定用不用-->
<div class="basic" :class="classObj">{{name}}</div>
<!--绑定style样式,表达式写法-->
<div class="basic" :style="{fontSize: fsize + 'px'}">{{name}}</div>
<!--绑定style样式,对象写法-->
<div class="basic" :style="styleObj">{{name}}</div>
</div>
列表渲染
react、vue中的key有什么作用?(key的内部原理)
1.虚拟DOM中的作用:
key是虚拟dom对象的标识,当数据发生变化时,vue会根据{新数据}生成{新的虚拟DOM},随后vue进行{新虚拟DOM}与{旧虚拟DOM}的差异比较,比较规则如下:
2.对比规则:
(1)旧虚拟DOM找到了与新虚拟DOM相同的key:
若虚拟DOM中内容没变,直接使用之前的真实的DOM
若虚拟DOM中内容变了,则生成新的真实DOM,随后替换页面中之前的真实DOM
(2)旧虚拟DOM中未找到与新虚拟DOM相同的key
创建新的真实DOM,随后渲染到页面
3.用index作为key可能会引发的问题:
(1)若对数据进行:逆序增加、逆序删除等破坏顺序的操作,会产生没有必要的真实DOM更新==》界面效果没有问题,但效率低
(2)如果结构中还包含输入类的DOM:会产生错误DOM更新==》界面有问题
4.开发中如何选择key?:
(1)最好使用每条数据的唯一标识作为key,比如id、手机号、身份证号、学号等唯一值
(2)如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示,使用index作为key是没有问题的
<ul>
<li v-for="p in persons" :key="p.id">{{p.id}} {{p.name}}--{{p.age}}</li>
</ul>
<!--遍历数组数据-->
<ul>
<li v-for="(p, index) in persons" :key="p.id">{{p.name}}--{{p.age}}</li>
</ul>
<!--遍历对象数据-->
<ul>
<li v-for="(p, index) in obj" :key="p.id">{{p}}--{{index}}</li>
</ul>
<!--遍历字符串数据-->
<ul>
<li v-for="(p, index) in chr" :key="p.id">{{p}}--{{index}}</li>
</ul>
收集表单数据
收集表单数据:
若<input type="text"/>,则v-model收集的是value值,用户输入的就是value值。
若<input type="radio"/>,则v-model收集是value值,且要给标签配置value值。
若<input type="checkbox"/>
1.没有配置input的value属性,那么v-model收集就是checked(勾选 or 未勾选,是布尔值)
2.配置input的value属性:
(1)v-model的初始值是非数组,那么收集的就是checked(勾选 or 未勾选,是布尔值)
(2)v-model的初始值是数组,那么收集的就是value组成的数组
备注:v-model的三个修饰符
lazy:失去焦点再收集数据
number:输入字符串转化为有效的数字
trim:输入首尾空格过滤
<form @submit.prevent="demo">
<label for="account">账号:</label>
<input type="text" id="account" v-model.trim="userInfo.name">
<br><br>
<label for="password">密码:</label>
<input type="password" id="password" v-model="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" v-model="hobby" value="userInfo.study">学习
<input type="checkbox" v-model="hobby" value="userInfo.playGame">打游戏
<input type="checkbox" v-model="hobby" value="userInfo.eating">吃饭
<br><br>
所属校区:
<select v-model="userInfo.city">
<option value="beijing">北京</option>
<option value="shanghai">上海</option>
<option value="shenzhen">深圳</option>
<option value="wuhan">武汉</option>
</select>
<br><br>
其他信息:
<textarea v-model.lazy="userInfo.other"></textarea>
<br><br>
<input type="checkbox" v-model="userInfo.agreen">阅读并接收<a href="http://www.baidu.com">用户协议</a>
<button>提交</button>
</form>
生命周期
生命周期:
生命周期函数中的this是指向vm或组件实例对象
常用的生命周期钩子:
1.mounted:发生Ajax请求,启动定时器,绑定自定义事件,订阅消息等初始化操作
2.beforeDestroy:清除定时器、解绑自定义事件、取消订阅消息等收尾工作
关于销毁vue实例:
1.销毁后借助vue开发者工具看不到任何消息
2.销毁后自定义事件会失效,但原生DOM事件任然有效
3.一般不会在beforeDestroy中操作数据,即使操作了也没有用
<script>
const vm = new Vue({
el: "#root",
data: {
opacity: 1,
},
methods: {
change(){
//定时方法,每多少毫秒执行一次
this.timer = setInterval(() => {
this.opacity -= 0.001;
if (this.opacity <= 0) this.opacity = 1;
},16)
},
stop(){
//停止定时器
// clearInterval(this.timer)
},
destroy(){
//销毁vm实例
this.$destroy();
}
},
beforeCreate(){
console.log('beforeCreate');
//打断点
debugger;
},
created(){
console.log('create');
//打断点
debugger;
},
beforeMount(){
console.log('beforeMount');
//打断点
debugger;
},
//挂载,vue完成模板的解析并把初始的真实DOM元素放入页面后(挂载完毕),调用mounted
mounted(){
this.change()
},
//数据跟新前,页面和数据
beforeUpdate(){
console.log('beforeUpdate');
},
//数据更新
updated(){
console.log('update');
},
//销毁之前
beforeDestroy(){
console.log('beforeDestroy');
},
//销毁
destroy() {
console.log('destroy');
}
})
//通过外部定时方法实现
/* setInterval(() => {
vm.opacity -= 0.001;
if (vm.opacity <= 0) vm.opacity = 1;
}, 16)*/
</script>
组件模块
Vue中使用组件的三大步骤:
一、定义组件(创建组件)
二、注册组件
三、使用组件
一、如何定义一个组件?
使用Vue.extend(options)创建,其中options和new Vue(options)时传入的参数options几乎一样,但也有点区别:
区别如下:
1.el不要写,为什么?---最终所有组件都要被一个vm管理调用,由vm中的el决定服务于哪个容器
2.data必须写成函数,为什么?---避免组件被复用时,数据存在引用关系
简写形式:
const school = new Vue(options)可以简写为const school = options
二、如何注册组件?
1.局部注册:靠new Vue的时候传入components选项
2.全局注册:靠Vue.component('组件名',组件)
三、编写组件标签
<school></school>
<script>
<!--第一步:创建vue组件-->
const school = Vue.extend({
// el: "#root", //组件定义时,一定不要写el配置项,因为最终所有组件都要被一个vm调用
template: `
<div>
<h2>学校名称:{{school.name}}</h2>
<h2>学校地址:{{school.address}}</h2>
</div>
`,
data: function () {
return {
school: {
name: '电子科技大学',
address: '成都市',
}
}
}
})
const student = Vue.extend({
template: `
<div>
<h2>学生名字:{{student.name}}</h2>
<h2>学生年龄:{{student.age}}</h2>
</div>
`,
data(){
return {
student: {
name: '付东',
age: 18,
}
}
}
})
const vm = new Vue({
el: "#root",
/* data: {
school: {
name:'电子科技大学',
address: '成都市',
},
student: {
name: '付东',
age: 18,
}
},*/
//第二步:注册组件(局部注册)
components: {
school: school,
student: student,
},
})
//vue全局注册组件
// Vue.component('school', school)
</script>
VueComponent构造函数
vueComponent(vue组件)
1.school组件本质是一个名为VueComponent的构造函数,且不是程序员定义的,是Vue.extend()生成的
2.我们只写<school></school>,Vue解析时会自动帮我们创建school组件的实例对象,即Vue帮我们执行:new VueComponent(options)
3.特别注意:每次调用Vue.extend(),返回的都是一个全新的VueComponent!!!!
4.关于this指向:
(1)组件配置中:
data函数、methods中函数等等,他们的this均是指向【VueComponent实例对象】
(2)new Vue(options)配置中:
data函数、methods中函数等等,他们的this均是指向【Vue实例对象】
5.VueComponent的实例对象,简称vc(也可称为组件实例对象)
Vue与VueComponent的关系
1.一个重要关系:VueComponent.prototype.__proto__ === Vue.prototype
2.为什么要有这个关系:让组件实例对象(vc)可以访问到Vue原型上的属性和方法
![](https://img-blog.csdnimg.cn/d6c4004ae96646f6b84a7a8a780c7950.png)
ref属性
ref属性:
* 1.被用来给元素或子组件注册引用信息(id的替代者)
* 2.应用在HTML标签上获取的是真实DOM元素,应用在组件标签上是组件实例对象(vc)
* 3.使用方式:
* 打标识:<h1 ref="xxx"><>/h1 或 <school ref="xxx"></school>
* 获取:this.$refs.xxx
props属性
配置项props
* 功能:让组件接收外部传过来的数据
* (1)传递数据
* <Demo name="xxx">
* (2)接收数据:
* 第一种方式(只接收):
* props:['name']
* 第二种方式(限制类型)
* props:{
* name: String
* }
* 第三种方式(限制类型、限制必要行、指定默认值)
* props: {
* name: {
* type: String, //类型
* required: true, //必要性
* default: '张三' //默认值
* }
* }
*
* 备注:props是只读的,Vue底层会检测你对props的修改,如果修改了就会发出警告,若业务需求需要修改,那么请复制props的内容到data中,然后去修改data中的数据