Vue实例

每个Vue程序都要进行实例化之后使用,实例有两种。

  • 一个是Vue实例
  • 一个是组件实例。
  • 对于Vue的插件,比如router和resource也有实例,称其为插件实例。

对于Vue的MVVM视图的解析

对于M-V-VM模型,由M-V-C模型衍生。

只不过M-V-C中的C在M-V-VM中变为了VM。在M-V-VM中VM就是逻辑操作。通过VM,我们去控制视图和数据之间 的变化。

构建一个Vue实例逐步解析

//创建一个Vue实例
var vm= new Vue();  -->这个Vue实例就是VM

//挂载一个DOM元素,作为数据展示的容器  -->这个el选项就是V
var vm =new Vue({
    el:'#XXX'
})

//设置一个data选项,作为一个对象,只保存数据,并且其属性被Vue实例代理。 -->这个data对象就是M
var vm =new Vue({
    el:'#Name',
    data:{
        key:value,
        .....
    }
})

构造器

每个Vue实例都是通过构造函数Vue创建一个Vue的根实例

var vm = new Vue({
  //options
})

在实例化Vue时,需要传入一个选项对象,它可以包含数据(data),模板挂载元素(el),方法生命周期钩子等选项。

Vue就是用选项对象中的data,created...等选项,来创建你想要的行为。这些选项可以在Vue中的API文档查看。

组件构造器

可以扩展的Vue构造器,从而用预定义选项创建复用组件构造器

//定义一个组件构造器
var myComponent =Vue.exted({
    //扩展选项
});
//所有的 myComponent的实例都将以扩展的组件构造器创建
var mycomponentExp=new myComponent(); //mycomponentExp是一个组件

所以我们现在知道,所有Vue.js组件都是被扩展的Vue构造器的实例

实例属性(数据代理和响应)

//html代码
<div id="app">
    <p>{{name}}</p>
</div>

//javascript代码
  var vm = new Vue({
            el: '#app',
            data: {
            name: 'huang'
         }
  });

通过上面的代码思考,为什么可以在视图中直接使用name属性?

每个Vue实例都会代理选项对象中data对象的所有属性。

这就关于Vue的另一个概念,数据代理

所谓数据代理(另称数据劫持),指的是在访问或修改对象的某个属性时,通过一段代码拦截这个行为,并进行额外的操作或者返回修改结果。比较典型的是Object.defineProperty()和E2015的Proxy对象。

对于数据劫持,最著名的应用就是双向绑定。

Vue2.x中使用的就是Object.defineProperty()(Vue 3.x改用Proxy进行实现)

这里只作大概了解。

详细: 参考末尾链接

所以,Vue实例通过数据劫持,代理data对象的属性。我们可以通过Vue实例来访问data对象中的属性。

上面的代码完整写法

//html代码
<div id="app">
  <p>{{this.$data.name}}</p>  //通过vm.$data访问源数据
  <p>{{$data.name}}</p>     //上一种的简写
  <p>{{this.name}}</p>        //与上等价,Vue实例代理data属性
  <p>{{name}}</p>              //上一种的简写    
</div>

//javascript代码
  var vm = new Vue({
            el: '#app',
            data: {
            name: 'huang'
         }
  });

//注1:this指向的是挂载在该元素的或是该元素的祖先元素的Vue实例。这里指向vm
//注2:data对象中,以$或_开头的属性不会被Vue实例代理,因为它们是Vue定义私有属性的写法可能和 Vue 内置的属性、API 方法冲突。可以通过$data.privateName来访问这些属性
//注3:privateName就是$,_ 开头的属性。

注意:只有这些被实例代理的属性是与视图响应的,代理的属性变化,源数据也会发生变化。同理,源数据变化,代理的属性也会变化

如果是实例被创建后添加新属性给实例,它是不会触发视图更新的。

//html代码
<div id="app">
    <p>{{name}}</p>
</div>

//javascript代码
 var mydata = {
            a: 1,
            name: 'huang'
        }
        var vm = new Vue({
            el: '#app',
            data: mydata
        });

//视图响应数据,发生变化。代理属性改变,mydata对象name属性也改变
        vm.name = 'new';

        //创建Vue实例后给实例添加属性,视图对其无响应
        vm.age = 22;

指令

什么是指令?

指令(Directives)是带有v-前缀的特殊属性。指令属性的值预期是Javascript表达式 (这点很重要 !)v-for例外。

借助尤雨溪的话:基于指令的数据绑定使得具体的DOM操作都被合理地封装在指令定义中

简单来说,指令的指责就是当其表达式的值改变时相应地将某些行为应用到DOM上。

指令怎么使用?

只需要将指令作为html元素的属性来使用就可以了,

例如:

<div v-if="expression">

指令只对当前所在的这个元素起作用,它在哪个元素上,就对哪个元素做出对应的DOM操作。

指令的值的解释

我更愿意将指令的值叫做指令的"表达式",为什么这么说?

例如:

  <div v-if="expression">

expression在模板中所对应的是this.expression

眼熟吗?这就是Vue实例代理data的属性。

既然是表达式,那么就一定会有返回值

它的值被传给指令,指令根据表达式返回的结果来决定所在的元素进行怎样的操作。

而表达式的变量,都来自Vue实例代理的data选项的属性。

条件判断指令(条件渲染)

v-if:依照起Value是否为Truthy来决定是否渲染此元素

<div v-if="expression">
    {{...}}
</div>

如果this.expression值为真,元素则被插入到Dom中,this.expression为假,则当前元素会从Dom中移出。

当我们有多个元素需要用同一个判断怎么办?

 <div v-if="expression">
     .....
 </div>
 <p v-if="expression">
     .....
 </p>

这种写法,有些繁琐。我们可以用<template>标签,根据元素的株连性把这个标签作为父元素,操作这个元素,并且此元素在渲染后不会影响到页面结构。

<template  v-if="expression">
     <div>
             .....
     </div>
     <p>
         .....
     </p>
</template>

v-show:依照起Value是否为Truthy来决定改变其Css的display属性值。

v-if在页面上的效果相同,都是决定元素是否显示,但是两者的渲染方式不同。

v-if在初始渲染时条件若为假,则什么也不做,直到第一次条件为真,才会渲染元素并将其插入DOM中

v-show不管初始条件是什么,都会对元素进行一次初始渲染,在接下来的操作中,就是Css的切换。

那么,我们知道,移除元素会导致DOM树变化,产生一次回流(reflow),它会重新计算样式和渲染DOM树。

而改变Css属性这类值改变某个节点的一些样式,只会引发重绘(repaint),只会绘制这个元素。

这么一对比,v-if频繁切换对浏览器性能开销影响更大,所以建议在运行时,如果条件的Truthy频繁的切换,则我们应该优先考虑v-show。而运行时条件很少改变,我更觉得是条件锁死,v-if的Truthy为false时,则更推荐v-if,因为它没有初始渲染开销。

v-else:v-if的else语句块,当v-if的expression的值为Truthy,则执行v-else指令,将元素渲染在页面上,否则,不渲染。

使用注意:必须紧跟在v-if后,否则不会有任何作用

循环调用指令(列表渲染)

v-for:指令基于源数据重复渲染该元素或模板块。

数组迭代:  用 v-for 指令根据一组数组的选项列表进行渲染

支持第二个参数为当前项的索引

语法:

v-for="(every, index) in expression"

every:可以用任意名字,表示迭代的数组元素的别名,可以用这个别名访问数组元素

index:任意名称,表示迭代的数组索引的别名,可以用这个别名访问数组索引

expression: 要迭代的源数据数组

实例:


 <div v-for="i in arr">
       {{i}}
  </div>

var vm = new Vue({
        el: '#app',
        data: {
            arr: [{
                name: 'li'
            }, {
                name: 'huanghao'
            }, {
                name: 'wang'
            }]
        }
    })

对象迭代:v-for 通过一个对象的属性来迭代

还可以有两个额外参数,第二个参数为键名,第三个参数为索引(这个索引更像是for循环的 i)

语法:

v-for="(value, key, index) in object"

value:任意名称,表示迭代的对象属性值的别名,可以用这个别名访问对象属性值

key:任意名称,表示迭代的对象的键值的别名,可以用这个别名访问对象键值

index:任意名称,表示迭代的对象的索引的别名 ..

object:要迭代的源数据对象。

实例


    <div id="app">
        <div v-for="(value,key1,index1) in obj">
            {{value}} --{{key1}} ---{{index1}}
        </div>
     
    </div>
  var vm = new Vue({
        el: '#app',
        data: {
            obj: {
                name: 'huang',
                age: 22,
                sex: 'man'
            }
        }
    })

v-for块中,拥有对父作用域属性的完全访问权限,v-for块中,其内部的模板语法,可以将v-for块中别名作为变量使用

那么模板语法有哪些?

绑定型指令

绑定型指令会有参数,参数是绑定的属性或事件。

v-bind:

绑定一个属性

语法: v-bind:prop="expression "

prop:绑定的属性

expression:表达式

v-bind绑定一个属性,如果expression的值为真,则表达式的值被添加到绑定的属性上,否则不被添加

以一个<img>元素的src属性举例

 <img  alt="" :src="src">  // <img  alt="" :src="1.img">
    new Vue({
        el: '#app',
        data: {
            Src:'1.img'
        }
    });

v-bind绑定了一个src属性,并且属性值为 this.Src,当表达式的值为真时,src属性的属性值就是this.Src

v-bind绑定class和style有些特殊,可以使用对象和数组形式绑定

绑定html元素的class

对象语法:

语法: v-bind:class="{className:expression,className2:expression2...}"

计算expression是否为Truthy,如果为真,则className/className2将被添加到class属性中,否则不会添加.

也可以直接绑定data选项中的一个对象

<div id="app" :class="classObject"></div>

var app = new Vue({
  el: '#app',
  data:{
    classObject: {
      active: true,
      'text-danger': false
    }
  }
})

或者绑定一个返回对象的计算属性

<div id="app" :class="classObject"></div>

var app = new Vue({
  el: '#app',
  data: {
    isActive: true,
    error: null
  },
  computed: {
    classObject: function () {
      return {
        active: this.isActive && !this.error,
        'text-danger': this.error && this.error.type === 'fatal',
      }
    }
  }
})

数组语法:和对象语法有不同,它添加的类名是被实例代理的data对象中的属性的属性值,并且此属性值必须的字符串。

例子

 <div 
   v-bind:class="[app,cls]"   //<div class="sss"></div>
  >
  
    new Vue({
        el: '#app',
        data: {
            cls:"sss",
            app:true
        }
    });

为了更加方便,还可以在数组中使用对象语法,对象语法在模板中照常解析

例子

 <div 
    v-bind:class="[app,cls,expression]"  //<div class="sss active error click"></div>
  >

new Vue({
        el: '#app',
        data: {
            name: '黄昊',
            src:'1.img',
            expression:{
                active:"class1",
                error:'class2',
                click:789
            },
            cls:"sss",
            app:true
        }
    });

关于绑定style

对象语法: v-bind:style="{style1:expression,style2:expression2}"

style1/style2:为style属性添加的样式名

expression/expression2:表达式的值必须为字符串,数字例外。表达式的值符合样式属性。

举例


 <div 
   :style="{color:'red'}"   //<div style="color: red;"></div>
 >
 </div>
//上方等同下方
 <div 
   :style="{color:red}"
 >
  </div>
new Vue({
        el: '#app',
        data: {
            red:'red',
        }
    });
    

或者为了让模板更加清晰,我们直接给定一个对象表达式

举例

 <div 
   :style="styleObject"   ///<div style="color: red; font-size: 16px;"></div>
 >
  </div>
   new Vue({
        el: '#app',
        data: {
            styleObj:{
                color:'redd
                fontSize:'16px'//样式按照Js的写法,因为我们一切模板语法的操作都是基于挂载的Dom对象
            }
        }
    });

数组语法:将多个样式对象应用到同一个元素上

需要注意的是,数组语法中的元素必须是对象形式。

例子:

 <div
   :style="[styleObj,styleObj2]"
   >
 </div>
   new Vue({
        el: '#app',
        data: {
            styleObj:{
                color:'red',
                fontSize:'16px'
            },
            styleObj2:{
                width:'100px',
                height:'100px'
            }
        }
    });

在Vue2.3.0+,style绑定的属性提供一个包含多个值 的数组,常用于提供多个带前缀的值

例子

<div :style="{ display: ['-webkit-box', '-ms-flexbox', 'flex','inline','a'] }"></div>
//<div style="display: inline;"></div>

这样写只会渲染数组中最后一个被浏览器支持的值

计算属性

我们通过computed选项来添加计算属性

对于任何复杂的逻辑,都应该使用计算属性

当我们在computed声明一个计算属性时,我们提供的函数将用作vm.computed_prop的getter函数 当计算属性被调用时,触发这个函数执行。

怎么使用?vm.computed_prop 简化--->computed_prop

组件

组件化思维
组件化针对的是页面中的整个完整的功能模块划分 (项目的分工)

组件的概念( 一个文件 )
组件是一个html、css、js、image等外链资源,这些部分组成的一个聚合体

优点:代码复用,便于维护
划分组件的原则:复用率高的,独立性强的

组件基础:

vue.js文件中暴露出一个Vue的构造器函数, 这个函数的作用,是用来实例化出来一个实例, 这个实例也是一个组件, 我们称之为 '根实例'

Vue为了扩展功能, 给了一个方法 , 这个方法叫 extend Vue.extend()

组件的表现形式是标签

使用组件必须遵守H5的标准,组件需要合法,必须注册组件。

组件使用前必须注册

组件的注册

全局注册

局部注册

在使用组件时,要注意会不会与原有的标签冲突


大明
7 声望0 粉丝

« 上一篇
浅解Promise