Vue学习笔记
模板语法
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原型上的属性和方法