Vue基础知识
Vue基础,数据响应式原理,数据绑定等
文章目录
Vue
理解MVVM
- M:Model对应vue中的data里面的数据
- V:View视图:dom模板
- VM:视图模型:vue实例对象
new Vue({
data:function(){
return{
name:'',
age:2/**将data里面的数据通过代理到vue实例上去,然后视图dom模板
可以直接访问Vue实例上的任何属性*/
}
}
}).$mount('#app')
//实现原理
Object.defineProperty(对象名称,属性值,配置项)
如:let a = {
name:'',
age:15
}
Object.defineProperty(a,'sex'{
value:'男';
enumerable:true//表示该添加的属性是否可以遍历
writable:true//表示是否可以修改
configurable:true //表示该添加的属性是否可以被删除
})
数据代理的简单原理
一个场景如下,从后台获取一个动态的值count,想要添加到下面的对象里面
let fcount = 5;
let finalcount = {
date:'',
number:55,
count:fcount
}
这样对象上就有一个值为fount的count属性,但是如果fcount改变值,对象上的属性是不会自动更新的
用
Object.defineProperty(finalcount,'count'{
enumerable:true//表示该添加的属性是否可以遍历
writable:true//表示是否可以修改
configurable:true //表示该添加的属性是否可以被删除
/**当有人读取对象添加的值的时候就会调用get方法,返回最新的fcount,来实现响应式**/
get:function(){
return fcount
}
//当有人修改这个值的时候就会调用set方法,方法里面一定要对数据进行更新,不然毫无意义
set:function(value){
fcount = value
}
})
再次回到vue的数据代理
-
通过vue的实例对象简称vm来代理data函数返回的对象的读写操作
通过defineProperty()吧data对象中的所有数据添加到vm上面
然后用getter和setter回调来操作data里面的数据(读写)
new Vue({
data:function(){
return{
name:'',
age:2/**将data里面的数据通过代理到vue实例上去,然后视图dom模板
可以直接访问Vue实例上的任何属性*/
}
}
}).$mount('#app')
//个人理解如下:
vue初识化的时候将data函数里面的属性代理到vue实例的_data上去,也就是this.name访问的属性。
相当于用defineproperty给vue实例加属性,当访问属性的时候会触发getter,返回的是_data函数里面的属性,当修改this上的属性的时候,会触发setter从而修改data函数里面的属性
回忆一下在vue里面通常是否是通过this.属性来修改值
数据劫持响应式的原理
- _data里面的数据不是直接赋值,如下图
通过getter和setter函数来拿到这个代理的值
/**模拟vue里面的数据代理**/ <body> <h2></h2> <input type="text" name="" id="" value="初始值" onchange="inpu()"> </body> <script> let data = { name: '打样', sex: '男' } let watchobj = { } let vm={ _data:watchobj } Object.defineProperty(watchobj, 'sex', { get: function () { console.log("调用了get"); return data.sex }, set: function (val) { data.sex = val document.querySelector('h2').innerHTML = watchobj.sex; } }) function inpu() { watchobj.sex = document.querySelector('input').value console.log(1); }
所以vue所有的属性,不关是字段类型,还是多结构的对象类型都会被代理,
所以当data数据里面的一个对象的属性不被确定想事后添加,不能直接
对象.sex='男'
这让sex成为了不被代理的属性了不会有响应式效果。Vue.set(target,key,val)
替我们实现了追加属性的功能。data(){ retuan { people:{ name:'打烊了' } } } created(){ this.$set(this.stu, 'sex', '男') } 或者Vue.set(people,'sex','男') ps:只能给data中某一个对象追加不能给data追加
综上:vue实现响应式页面的原理是数据代理的setter,但是数组类型是没有为其服务的getter和setter的,所以要修改数组只能调用数组的经过vue修改过后的原生方法如pop,push
事件处理
事件的基本使用:
1.使用v-on :xxx或@xxx绑定事件,其中xxx是事件名;
2.事件的回调需要配置在methods对象中,最终会在vm上;
3.methods中配置的函数,不要用箭头函数!否则this就不是vm了:
4.methods中配置的函数,都是被Vue所管理的函数,this的指向是vm或组件实例对象;
5事件之中,事件对象用$event传递
事件修饰符 prevent阻止默认事件 stop:阻止事件冒泡 once只允许触发一次
capture 使用事件捕获模式//一般事件是先捕获,后冒泡,但是默认在冒泡处理回调
self:只有event.target是当前对象的时候才会触发事件,阻止冒泡误触发
passive: 事件的默认行为立即执行不用等待回调函数
回车=>enter
删除=>delete(插获“删除”和“退格”键)退出=>esc
空格=>space
换行=>tab(特殊,必须配合keydown去使用)上=>up
下=> down左=> left右=> right
系统修饰健(用法特殊):ctrl、alt、 shift、 meta
(1).配合keyup使用:按下修饰键的同时,再按下其他键,随后释放其他键,事件才被触发。(2).配合keydown使用:正常触发事件。
自定义事件
/***一般用于子组件向父组件传值***/
原生的事件是绑定到html标签上的,而自定义事件是绑定到组件实例上面的
如:<people》组件想要绑定一个add事件
在people内部用 this.$emit('add',people内部的参数):触发add事件
而在父组件之中调用add事件绑定到people组件之上,用
...<people @add="handle" />
handle(name或者其他参数,而这个参数就是people组件内部的参数){
//上述就实现了子组件向父组件传值
}
- 事件解绑
this.$off()解绑全部
this.$off('add')或者this.$off(['add','app'....])
---------------------------
组件不能绑定原生事件,原生事件都是绑定在原生html标签上面的,在父组件中的子
组件上面绑定click等事件都会解析为自定义事件,而如果想要绑定原生事件必须加.native修饰符
全局事件总线:实现了任意组件间传值
/****/
全局事件总线是由一个对象要实例中的所有vc和vm都能看见,且该对象上面有Vue原型的$on,$emit等等方法,windows和Vue等等都可以作为选择,如
new Vue({
el:'app',
...
beforeCreate(){
Vue.prototype.x = this:这个this具备$on,$emit等等一系列方法
}
})
第一步:在组件里面为对象绑定一个事件,如全局事件对象是x,则在组件内为x添加一个事件,且回调函数直接是该组件内的函数
如:this.x.$on('add',function(参数){用来访问所在组件的一系列方法等等})
第二布:在需要传值的组件之中触发该事件:
如this.x.$emit('add',传递参数)
消息的发布与订阅
在需要数据的组件之中订阅消息,在发布数据中发布消息
用到第三方库 pubsub-js
import pubsub(一个对象) from 'pubsub-js'
发布消息方法 subscribe('消息名',回调函数function(megName,data){第一个参数是消息名字,后面是发送的数据}):返回消息id
订阅消息 publish('消息名',data:数据)
取消订阅消息 unsubscribe(消息id)
计算属性与监听
- 计算属性
1.简易的计算属性
在methods之中创建一个方法return一个依赖data属性经过操作的值,放在模板语法中
如 methods:{
test(){
return x+y
}
}
{{test()}} 这种方法在vue中只有data里面的任何属性发生变化都会重新加载html模板
然后重新调用test(),依次得到最新的值,无缓存
---------------------------------------
将计算属性的返回值挂载到vm上面
computed:{
name:{
/*当读取计算属性name的时候就会调用get方法,返回值作为name的值**/
//getter初次访问name的时候会调用,所依赖的数据发生变化的时候也会调用//
get(){
}
set(){
//如果要手动修改计算属性的话要写setter,内容是赋值,不加内容的setter毫无意义
而将计算属性修改值之后,项目读取该计算属性的时候还是调用set,所以说在项目层面是没有被修改的
}
}
}
ps:当计算属性只考虑读不考虑写的时候,就可以使用简写的模式
- 监视
watch:{
name:{
immediate:false//初始化的时候调用一下
handle(newVaule,oldVaule){
}
}
}
----
全局:vm.$watch('name'{配置对象})
------------------------
深度监视
如果要监视一个对象里面的属性或者多级结构的属性
1. 'people.name':配置照旧
2.配置项deep:true
不配置的时候只有改变对象地址才会触发监视函数,但是加了之后对象的属性改变也会触发
ps:不需要配置项的时候可以简写
区别:
我们在计算开销比较大(计算次数多或者异步处理)的时候,会使用侦听器watch来得到计算结果。
而其他情况建议使用计算属性computed,因为缓存节省多次计算的性能。计算属性依赖元数据的值,而watch依赖元数据是否变化
prop与mixin
/**尽量不要直接修改prop值,赋值再修改*/
1.第一种配置:简单接收,不限制接收类型
在组件内部配置项中props:['name',...,age]
ps:注意父组件传值的时候都会以k-v形式,所以age="11"会将age解析为字符串用v-bind解决
2.限制类型接收
props:{
name:String,
age:Number...
//或者
age:{
type:Number
default:xx
requires:Boolean
}
}
-------------------------------------------
功能:可以将多个组件共用的配置提取成一个混入对象
使用方式: 1.定义mixin.js文件 暴露配置对象
如{
data(){...},
methods:{....}
}
2.引入 2.1全局引入Vue.mixin(xxx)
2.2import {xxx} from mixin.js
局部混入:mixins:["xxx"]
样式绑定
- vue允许额外有被vue接管的class属性
<div class = 'basic' :class='xxx' ></div>
- style样式绑定
<div class = 'basic' :class='xxx' :style=obj></div>
obj:{
fontSize:'50px'
}
键值命名:一个单词正常写,两个驼峰
---------------------
style也可以值为数组 :style=arr arr=[obj,obj1]
列表循环key值
表单绑定
收集表单数据:
若:.
则v-model收集的是value值,用户输入的就是value值。
若:tinput type=“radio”/
则v-model收集的是value值,且要给标签配置value值。
若:<input type=“checkbox”"/>
.
1.没有配置input的value属性,那么收集的就是checked(勾选or未勾选,是布尔值)
2.配置input的value属性:
(1)v-model的初始值是非数组,那么收集的就是checked(勾选or未勾选,是布尔值)(2)v-model的初始值是数组,那么收集的的就是value组成的数组
备注:v-model的三个修饰符:
lazy:失去焦点再收集数据
number:输入字符串转为有效的数字trim:输入首尾空格过滤
其他常用指令和自定义指令
v-cloak //当线程js阻塞的时候vue没有接管页面时候。vue代码如{{xxx}}会显示到页面,加这个属性 <div v—cloak></div>,当vue接管时移除v-cloak
v-once //v-once所在节点在初次动态渲染后,就视为静态内容了。
以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能。
v-pre //.跳过其所在节点的编译过程。
.可利用它跳过:没有使用指令语法、没有使用插值语法的节点,会加快编译。
-
自定义指令
1.函数式 如v-zf vue配置项 directives:{ zf(element,b){ //第一个参数是html元素 } }
关于vue组件补充
组件使用步骤
1.创建组件
Vue.extend({
template:'HTML模板'
data,等等配置项,实例vue上面data可以以对象形式,但是组件只能用函数形式
})
也可以直接const app = {配置项}不过底层还是调用了extend
2.注册组件
实例中或者组件中注册: 在配置项中components配置
全局注册Vue.component('APP',APP)
ps:但是组件里面不能传入el配置项
关于VueComponent:
1.组件本质是一个名为VueComponent的构造函数,且不是程序员定义的,是Vue.extend生:成的。
2.我们只需要写或<schoolx,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的实例对象,以后简称vm-I
.一个重要的内置关系:VueComponent.prototype.proto === Vue.prototype.为什么要有这个关系:让组件实例对象(vc)可以访问到 Vue原型上的属性、方法.
更多推荐
所有评论(0)