v-model只能用在表单元素中;
枚举(enumerable)不能遍历,
MVVM
数据代理
通过一个对象代理对另一个对象中属性的操作
Object.defineProperty
vm._data=data
事件修饰符
<div id="root">
<h2>欢迎来到{{name}}学习</h2>
<!-- 阻止默认事件(常用) -->
<a href="http://www.baidu.com" @click.prevent="showInfo">点我提示信息</a>
<!-- 阻止事件冒泡(常用) -->
<div class="demo1" @click="showInfo">
<button @click.stop="showInfo">点我提示信息</button>
<!-- <a href="http://www.atguigu.com" @click.prevent.stop="showInfo">点我提示信息</a> -->
</div>
<!-- 事件只触发一次(常用) -->
<button @click.once="showInfo">点我提示信息</button>
</div>
键盘事件
key的作用和原理
面试题:react,vue中的key有什么作用(key的内部原理)
1.虚拟DOM中Key的作用
key是虚拟对象的标识,当数据发生变化时,vue会根据[新数据]生成[新的虚拟DOM]
随后vue进行[新的虚拟DOM]与[旧的虚拟DOM]的差异比较,比较规则如下:
2.对比规则:
(1)旧虚拟DOM中找到了与新虚拟DOM相同的key:
1、若虚拟DOM中内容没变,直接使用之前的真实DOM
2、若虚拟DOM中内容变了,则生成新的真实DOM,随后替换页面中之前的真实DOM
(2)旧虚拟DOM中未找到与新虚拟DOM相同的key
创建新的真实DOM,随后渲染到页面
3.用index作为key可能会引发的问题
1.若对数据进行:逆序添加,逆序删除等跑环顺序操作
会产生没有必要的真实DOM更新==>界面效果没有问题,但效率低
2.如果结构中还包括输入类的DOM:
会产生错误DOM更新===>界面有问题
4.开发任何选择key?
1.最好使用每一条数据的唯一标识作为key,比如id,手机号,身份证号,学号等唯一值
2.如果不存在对数据的逆序添加,逆序删除顺序操作,只用于渲染列表用于展示,使用index作为key是没有问题的
列表过滤(模糊搜索)、列表排序
<body>
<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) in filPersons" :key="p.id">
{{p.name}}--{{p.age}}--{{p.sex}}
</li>
</ul>
</div>
<script type="text/javascript">
const vm=new Vue({
el:'#root',
data:{
sortType:0, //0原顺序,1降序,2升序
keyWord:'',
persons:[
{id:'001',name:'马冬梅',age:'30',sex:'女'},
{id:'002',name:'周冬雨',age:'32',sex:'女'},
{id:'003',name:'周杰伦',age:'19',sex:'男'},
{id:'004',name:'温兆伦',age:'21',sex:'男'}
],
// filPersons:[]
},
computed:{
filPersons(){
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
}
},
})
</script>
</body>
</html>
获取表单数据
收集表单数据
1.input type=‘text’,则v-model收集的是value值,用户输入的就是value值
2.input type='radio',则v-model收集的value值,且要给标签配置value值
3.input type='checkbox',那么收集的就是checked
(1).没有配置input的value属性,那么收集的就是checked(勾选或未勾选,是布尔值)
(2).配置input的value属性
1.v-model的初始值是非数组,那么收集的就是checked(勾选或未勾选,是布尔值)
2.v-model的初始值是数组,那么收集的就是value组成的数组
4.v-model的三个修饰符:
lazy:失去焦点再收集数据
number:输入字符串转为有效的数字
trim:输入首尾空格过滤
指令
前面学过的指令:
1.v-bind:单向绑定解析表达式,可简写为:xxx
2.v-model:双向数据绑定
3.v-for:遍历数组/对象/字符串
4.v-on:绑定事件监听,可简写为@
5.v-if:条件渲染(动态控制节点是否存在)
6.v-else:条件渲染(动态控制节点是否存在)
7.v-show:条件渲染(动态控制节点是否展示)
- v-pre指令:
1.跳过其所在节点的编译
2.可以利用它跳过:没有使用指令语法,没有使用插值语法的节点,会加快编译- v-once指令:
1.v-once所在节点在初次动态渲染后,就视为静态内容了
2.以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能
自定义指令
<div id="demo">
<h2>当前的n值是:<span v-text="n"></span></h2>
<h2>放大10倍后的n值是:<span v-big="n">放大10倍后的n值是:</span></h2>
<button @click="n++">点我n+1</button>
<hr>
<input type="text" v-fbind="n">
<!-- 获得焦点 -->
</div>
<script type="text/javascript" >
Vue.config.productionTip = false ;
new Vue({
el:'#demo',
data:{
n:100
},
directives:{
// 指令【里面的this都指向window】
// big:function(){}
// big函数何时会被调用1.指令和元素成功绑定时(一上来)2.指令所在的模板发生变化时(data发生变化时)
big(element,binding){
// 事件对象 ,绑定(绑定元素和指令)
element.innerHTML = binding.value * 10// 不靠返回值,靠收到的参数
},
fbind:{
// 指令和元素成功绑定时调用
bind(){
element.value=binding.value
},
// 元素插入到页面中时调用
inserted(){
element.focus();
},
// 指令所在的模板更新时调用
update(){
element.focus();
}
}
}
})
</script>
v-clock
1.本质是一个特殊属性,vue实例完毕并接管容器后,会删掉v-cloak属性
2.使用css配合v-cloak可以解决网速慢时页面显示{{xxx}}的问题
v-once
1.v-once所在节点在初次动态渲染后,就视为静态内容了
2.以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能
v-html
1.作用:向指定节点中渲染包含HTML结构的内容
2.与插值语法的区别:
(1)v-html会替换节点中所有的内容,{{xx}}则不会
(2)v-html可以识别HTML结构
3.严重注意:v-html有安全性问题
(1)在网站上动态渲染任意HTML是十分危险的,容易导致xss攻击
(2)一定要在可信的内容上使用v-html,永不要用在用户提交的内容上
v-text
1.作用:向其所在的节点中渲染文本内容
2.与插值语法的区别:v-text会替换掉节点中的全部内容,{{xxx}}不会
1.跳过其所在节点的编译
2.可以利用它跳过:没有使用指令语法,没有使用插值语法的节点,会加快编译
组件
非单文件组件:这个组件不是由单个文件组成。
单文件组件:这个组件是由1个文件组成。
Vue中使用组件的三大步骤:
1.定义组件(创建组件)
2.注册组件
3.使用组件(写组件标签)
一、如何定义一个组件?
使用Vue.extend(options)创建,其中options和New Vue(option)时传入的那个option几乎一样,但也有点区别:
1.el不要写,为什么?最终所有组件都要经过一个vm的管理,由VM中的el决定服务哪个容器
2.data必须写出函数,为什么?——————避免组件被复用时,数据存在引用关系
备注:使用template可以配置组件结构
二、如何注册组件
1.局部注册:靠new Vue的时候传入components选项
2.全局注册:靠Vue.component(‘组件名’,组件)
三、编写组件标签
<组件名><组件名/>
组件注意点
生命周期
常见的生命周期钩子
1.mounted:发送Ajax请求,启动定时器,绑定自定义事件,订阅消息等[初始化操作]
2.beforeDestroy:清除定时器,解绑自定义事件,取消订阅消息等[收尾工作]
关于销毁Vue实例
1.销毁后借助Vue开发中工具看不到任何消息
2.销毁后自定义事件会失效,但原生DOM事件依然有效
3.一般不会在beforeDestroy操作数据,因为即使操作数据,也不会在触发更新流程了
组件嵌套
<div id="root">
<app></app>
</div>
<script>
const hello=Vue.extend({
template:`
<h1>{{msg}}</h1>
`,
data(){
return{
msg:'欢迎来到尚硅谷学习'
}
}
})
const app=Vue.extend({
template:`
<div>
<hello></hello>
<school></school>
</div>
`,
components:{
school:school,
hello
}
})
const vm= new Vue({
el:'#root',
data:{
msg:'hello!'
},
components:{app}
})
</script>
</body>
</html>
关于VueComponent
1.school组件本质是应该名为Vuecomponent的构造函数,且不是程序员定义的,是Vue.extend生成的
2.我们只需要写<school></school>或<school>,Vue解析时会帮我们创建school组件的实例对象,即Vue帮我们执行的:new VueComponent(options)
3.特别注意:每次调用Vue.extend,返回的都是一个全新的Vuecomponent
4.关于this指向:
(1)组件配置中:
data函数,methods中的函数,watch中的函数,computed中的函数,它们的this均是[VueComponent实例对象]
(2)new Vue(options)配置中:
data函数,methods中的函数,watch中的函数,computed中的函数,它们的this均是[Vue实例对象]
5.VueComponent的实例对象,以后简称VC(也可以简称为:组件实例对象)
Vue和VueCompoent关系
1.一个重要的内置关系:VueComponent.prototype.__proto===Vue.prototype
2.为什么要有这个关系:让组件实例对象(vc)可以访问到Vue原型上的属性和方法
ref属性:
1.被用来给元素或子组件注册引用信息(id的代替者)
2.应用在HTML标签上获取的是真实dom元素,应用在组件标签上是组件实例对象(vc)
3.使用方法:
打标识:<h1 ref="xxxx></h1>或<school ref="xxx"></school>
获取:this.$refs.xxx
配置项props
功能:让组件接收外部传入过来的数据
(1)传递数据:
<demo name='xxx'>
(2)
接收数据:
第一种方式(只接受)
props['name']
第二种方式(限制类型)
props:{
name:String
}
第三种方式:(限制类型,限制必要性,指定默认值)
props:{
name:{
type:String,//类型
required:true//必要性
default:'张三'//默认值
}
}
备注:props是只读的,Vue底层会监测你对props的修改,如果进行了修改,就会发出警告,
若业务需求确实需要修改,那么请复制props的内容到data中一份,然后去修改data中的数据
数组reduce函数
浏览器本地存储
1.存储内容大小一般支持5MB左右
2.浏览器端通过Window.sessionStorage和Window.localStorage属性来实现本地存储机制
3.相关api:
(1)
xxxxxStorage.setItem('key','value');
该方法接收一个键和值作为参数,会把键值对添加到存储中,如果键名存在,则更新其对应的值
(2)
xxxxxStorage.getItem('key','value');
该方法接收一个键名作为参数,返回键名对应的值
(3)
xxxxxStorage.removeItem('key','value');
该方法接收一个键名作为参数,并把该键名从存储中删除
(4)
xxxxStorage.clear()
该方法会清空存储中所有的数据
4.备注
(1)sessionStorage存储的内容会随着浏览器窗口关闭而消失
(2)LocalStorage存储的内容,需要手动清除才会消失
(3)xxxxStorage.getItem(xx)如果xxx对应的value获取不到,那么getItem的返回值是null
(4)JSON.parse(null)的结果依然是null
组件自定义事件
1.一种组件间通信的方式,适用于:子组件===>父组件
2.使用场景:A是父组件,B是子组件,B想给A传数据,那么就要在A中给B绑定自定义事件(事件的回调在A中)
3.绑定自定义事件:
(1)第一张方式,在父组件中:<demo @atguiigu='test'/>或<demo v-on:atguigu='test'/>
(2)第二种方法,在父组件中:
<demo ref='demo'>
......
mounted(){
this.$ref.xxx.$on('atuguigu',this.test)
}
(3)若想让自定义事件只能触发一次,可以使用once修饰符,或$once方法
4.触发自定义事件:this.$emit('atguigu',数据)
5.解绑自定义事件:this.$off('atguigu')
6.组件上也可以绑定原生dom事件,需要使用native修饰符
7.注意:通过this.$ref.组件名.$on('atguigu',回调)绑定自定义事件时,回调要么配置在methods中,要么用箭头函数,否则this指向vc而不是vm
hasOwnProperty判断身上有没有一个属性
动画和过渡
动画
<template>
<div>
<button @click="isShow=!isShow">点击显示与隐藏</button>
<!-- appear :true 刚挂载后就显示一次动画-->
<transition name="m" :appear="true">
<h1 v-show="isShow" >
111111111 111111111
</h1>
</transition>
</div>
</template>
/* 进入动画 */
.m-enter-active{
animation: move 3s ;
}
/* 离开动画 */
.m-leave-active{
animation: move 2s reverse;
}
@keyframes move {
from{
transform: translateX(-100%);
};
to{
transform: translateX(800px);
}
}
过渡
<template>
<div>
<button @click="isShow=!isShow">点击显示与隐藏</button>
<!-- appear :true 刚挂载后就显示一次动画-->
<transition name="m" :appear="true">
<h1 v-show="isShow" >
111111111 111111111
</h1>
</transition>
</div>
</template>
/* 进入的起点 */
.m-enter{
transform: translateX(-100%);
}
/* 进入的终点 */
.m-enter-to{
transform: translateX(0);
}
/* 离开的起点 */
.m-leave{
transform: translateX(0);
}
/* 离开的终点 */
.m-leave-to{
transform: translateX(-100%);
}
/* 谁变给谁加过渡 */
h1{
transition: 2s;
background-color: orange;
width: 800px;
height: 100px;
}
备注:若有多个元素需要过度,则需要使用:,且每一个元素主要指定key值
npm 的动画库animate
vue配置代理服务器解决跨域方法
vuex
专门在Vue中实现集中式状态(数据)管理的一个Vue插件,对vue应用中多个组件的共享状态进行集中式的管理(读/写),也是一种组件间通信的方式,且适用于任意组件通信
缓存路由组件
切换路由后上面数据还在
1.作用:让不展示的路由组件保存挂载,不被销毁
2.具体编码:
2.1适用于缓存一个路由组件
<keep-alive include='欲保存的组件名'>
<router-view></router-view>
</keep-alive>
2.2缓存多个路由组件
<keep-alive :include="['News','Message']">