MVVM框架

1.旧的网页组成:3部分

HTML:提供网页的内容

CSS:为内容提供样式

JS:为内容提供行为/数据

问题:JS DOM操作,既要加工数据,又要承担大量琐屑的增删改查DOM的任务,代码繁琐。

解决:重新划分上述3部分

 

2.重新划分

View:视图,指网页中元素和样式,一般指HTML/CSS

其实,是.html网页中的一个需要动态加载内容的父元素:如div#app

html网页中的视图,也称为模板template。今后,只要看到模板template错误,就在html中查找原因。

 

Model:模型,指程序中创建的或远程获取的数据,一般用JS中的一个对象来保存。

以前,如何将Model中的数据显示到页面View中的指定位置?

DOM/JQUERY操作:手动查找元素,修改元素内容/属性/样式。

现在:

ViewModel:视图模型/控制器,替代之前的DOM/JQUERY操作,把模型中的数据和视图中的HTML元素“绑定”在一起。

什么是绑定:不需要写一行代码,就可让页面元素内容和数据联动变化。

Vue类型,提供的就是这样一种强大的ViewModel对象,可自动同步数据和页面元素。

 

3.ViewModel的核心原理:

1.响应系统(Reactivity System):内存中数据变,页面自动改,每个内存中的数据都被添加了访问器属性,受到一对儿get/set()

方法的保护,每次修改内存中的数据时,都会自动调用当前数据的set方法,其中,除了修改内容中的数据外,还会通知观察者,观察者自动触发重新加载方法,生成新的虚拟DOM树,然后自动更新到真实DOM树。

2.虚拟DOM(Virtaul DOM):用js面向对象虚拟的,保存当前视图内所有DOM节点对象基本描述属性和节点间关系的树结构。用js对象,描述每个节点,极其父子关系,形成虚拟DOM对象树结构,修改内存中的数据,触发重新加载操作,重新加载,用修改后的数据生成新虚拟DOM树,框架的加载功能会遍历并比对新虚拟树和旧虚拟树中每个节点的差别,并记录下来,最后,加载操作,将所有记录的不同点,局部修改到真实DOM树上。

为什么快:

1.局部更新真实DOM树,避免大范围重排重绘。

2.无需人工执行增删改查操作干预,自动化程度高。

 

4.如何使用vue框架?

首先,创建Vue类型的ViewModel对象vm:

1.要想享受Vue框架提供的便利,必须创建Vue类型的对象。

2.var vm=new Vue({ ... });

其次:在new Vue中,定义模型,并将vm对象与页面中某个父元素绑定起来。组合在一起:

1.Html中(View):

<div id="app">

       <xxx>显示数据的元素</xxx>

</div>

2.JS中var vm=new Vue({//ViewModel

    data:{//Model

           数据属性:值

           ...    :  ...

    }

     el:"#app",//指定将数据模型data,整体绑定给页面元素#app

})

2.强调:虽然el,后可跟任意选择器,但一个vm对象,只能绑定到一个DOM父元素上。

即使:el:"选择器"可以找到多个元素,也只能绑定到第一个符合条件的DOM元素上。

所以,通常都用#id选择器就够了。

 

5.{{}}语法

1.{{}}:双花括号语法,也叫大胡子语法(Mustache)

     官方名字:Interpolation补缺,插值的意思。

2.什么是:用于选择特定的Model数据绑定到View视图中

今后只希望Model数据发生了改变,所有用到该数据的{{}}都会自动更新。

3.如何:{{表达式}}其中的表达式可以是:

     注意:不能出现逻辑结构(if/for等)

     (1)Model变量名,如{{userName}}

     (2)算术/比较/逻辑/三目运算,如{{sex==0?'男':'女'}},可用过滤器代替

     (3)方法调用,如{{getSum()}},可用计算属性代替

     (4)属性访问,如{{book,price}}

     (5)数组下标访问,如{{list[2]}}

 

4.问题:

     (1)问题1:不能根据数组/集合中的记录条数,动态绑定到列表

     (2)问题2:不能使用{{}}语法动态绑定属性值!

     解决:使用指令

 

6.指令(directive)

    什么是:Vue.js提供的,专门增强html功能的特殊属性

    为什么:html本身是静态的,写死的,没有任何动态生成内容的能力

    何时:只要希望根据内容中的数据,动态生成html元素或属性时,都用指令。

    包括:看手册/指令

    如何:v-*凡是v-*开头的,都是增强型的html属性

(1)v-bind专门绑定属性值!

何时:只要绑定属性

如何:<any v-bind:属性="数据变量">

强调:不用写{{}}

简写:v-bind可省略,仅:   :属性="数据变量"

 

(2)v-for:根据数组/集合内容,反复生成多个相同的html元素

何时:只要根据数组/集合内容,反复生成多个相同的html内容时

如何:<any v-for="(变量名,下标名) in 数组/对象/字符串">

强调:v-for要写在要重复生成的元素上,而不是父元素上。

简写:如果不关心下标,只关心元素值,可简写为:<any v-for="变量名 in 数组/对象/字符串/数字">

in,可自动取出数组/集合中每个元素的值和下标保存到右边的变量中

//in 可用of替换,完全相同

如果in后是数字,则in会从1开始迭代递增到目标数字

 

(3)v-if:根据一个bool数据作为条件,控制是否创建该元素到DOM树(控制显示隐藏)

何时:根据条件,控制一个元素的显示和隐藏时。

如何:<any v-if="布尔">

强调:不是用display:none隐藏,而是彻底删除不显示的元素

 

(4)v-else:与v-if组合应用

<any v-if="布尔"></any>

<any v-else></any>

 

(5)v-else-if:与v-if组合应用

<any v-if="布尔"></any>

<any v-else-if="布尔"></any>

<any v-else></any>

强调:v-if  v-else if  v-else元素必须是紧邻的兄弟元素,中间不能阻隔任何其他元素

<!--坑!!!父元素div,不能换成p元素,因为html中规定p元素不允许嵌套块元素!!!-->

 

(6)v-show:用法类似于v-if只不过,总是创建该元素到DOM树,但使用display:block/none控制显示隐藏。

vs v-if:通过创建/删除元素来控制显示隐藏。

何时:如果隐藏后,还需要重新显示回来,就用v-show,不用反复创建DOM元素,效率高。

如果隐藏后,不会再显示回来,就用v-if,删除元素,减小DOM树的内容。

 

(7)v-on:为当前元素绑定指定事件的处理函数

1.问题:真正项目中:var vm=new Vue(),会造成全局污染,所以通常不写var vm,直接new  Vue()

就不可能在Vue以外的事件处理函数中,使用vm变量来操作对象的内容

 

2.解决:利用面向对象思想,在new Vue()对象内部,添加方法。对象自己的方法,

访问自己的属性,不需要对象变量名,一切都用this代替即可!

如何添加方法:

        1.new Vue({ 

                    methods:{   

                          方法名:function(){ this指向当前vm对象 }因为methods中的方法和data中的属性一样,

                          都会被提升到vm对象上

                          //可简写为:方法名(){ .... }

                    }

            })

         2.强调:方法名不能用js中的关键字,比如delete,不能用,因为delete是Js中专门删除对象属性的关键词!

         3.如何让页面上的元素的事件属性,找到当前对象的方法?

         4.必须用v-on:事件名="方法名()"   ------- 看手册

          简写:如果没有参数,可省略()

          语法糖:v-on:事件名=可简写为@click=

 

3.Html中:<button @clcik="add">+</button>

问题:如果换成a当按钮,href="...."属性,默认会擅自改变地址栏或跳转其他页面。

解决:阻止默认行为

问题:methods中的方法,本质不是直接的事件处理函数,不能自动获得事件对象

解决:2种方法:

          1.使用Vue对象内置变量$event

               ①Html中绑定时,手工传入Vue内置对象$event:

               <a href="#" @clcik="sub($event)"></a>   

               ②JS中,为methods中的方法定义参数e

                js中:methods:{

                   sub(e){ ... }

                  }     

               ③$event,是Vue对象内,将DOM对象e封装后的产物,是现成的内置变量,可直接使用。

               ④何时:只要想在Vue的处理函数中使用事件对象,必须在html绑定中调用方法时,传入$event.

               ⑤强调:html中实参$event名不能变,但js中形参名可变$event可和其他参数一同传入,且没有顺序限制。

2.使用事件修饰符:

               问题:使用$event,html和js都要修改,少改一处,就错!

               解决:其实可以更简化:

               ①事件修饰符:自动实现原DOM事件对象操作的特殊属性

               ②何时:只要希望修改事件的行为时,都要用事件修饰符,不用$event

               ③包括:手册/v-on/修饰符:

                .stop代替stopPropagation()

                .prevent代替preventDefault()

                如何:js中,不要加e,更不要调用e的方法了

                 Html中:@click.修饰符=“....”

                 强调:多个修饰符可同时修饰一个事件:比如:@click.stop.prevent=且顺序无关

                 但是:如果想要获得鼠标位置,则必须使用$event!所以!两种方法都要会!

(8)v-html:使用模型数据替换当前元素的innerHTML

                   何时:专门加载一段html代码片段

(9)v-text:使用模型数据替换当前元素的innerText

                  何时:专门加载一段文本内容

(10)v-cloak:(哈利波特的隐身斗篷)强调:不是clock!!!

问题:首次加载页面时,如果加载稍微延迟,用户就可能看到{{}}语法!

如何:2步:必须配合css使用

           写在元素开始标签中即可,不用给值!!!

           在css中必须添加:[v-cloak]{display:none;}

           强调:VUE官方本身,没有提供v-cloak的隐藏样式,所以,必须我们自己写

           VUE只负责自动移除v-cloak

原理:开始时由我们手动加上display:none,准备就绪后,vue自动删除v-cloak属性,

也就删除了display:none属性,元素显示出来        

(11)v-pre:保留当前元素中的{{}}语法,不进行绑定渲染

何时:如果元素内容中,有{{}}原文,但不想作为绑定语法解析,可用v-pre,保留{{}}为原文,不再编译。

(12)v-once:当前元素的{{}}语法对应的数据只绑定一次,以后即使模型数据改变,也不再随着改变。

何时:如果数据,只在加载时,绑定一次即可,后续不再改变时

底层原理:只在首次加载时,一次性将模型数据显示在当前元素,不会将当前元素注册

到监听队列中。

正常:watcher中,有一个队列,维护者每个数据变量和页面之间元素的对应关系。每次数据模型发生改变后,都会通知

watcher,watcher会遍历受该数据变量影响的元素,并逐个修改他们。

优化:减少被监听的元素个数,可以优化页面绑定的效率。

 

posted @ 2020-06-05 20:43  平凡人的普通修仙之路  阅读(309)  评论(0编辑  收藏  举报