在这里插入图片描述

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 = 5let 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.属性来修改值
数据劫持响应式的原理

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GJEVu9yO-1653924615905)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220530182902314.png)]

  • _data里面的数据不是直接赋值,如下图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RkYGaFX8-1653924615906)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220530183040022.png)]

通过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"]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9bVrHlLS-1653999678097)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220531185640262.png)]

样式绑定
  • 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值

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GugcGemA-1653924615906)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220530163054857.png)]

表单绑定

收集表单数据:
若:.
则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原型上的属性、方法.

Logo

前往低代码交流专区

更多推荐