Vue 2.0(二)基础,样式操作,v for循环等

1,029 阅读17分钟

vue概述sd

在官方文档中,有一句话对Vue的定位说的很明确: Vue.js 的核心是一个允许采用简洁的模板语法来声明式地将数据渲染进 DOM 的系统

Vue在我的理解下,其实很像mvvm架构中,对vm的实行。在mvvm架构中,viewModel是负责把view和model关联起来,把model的数据同步到view显示出来,把view的修改同步回model。在Vue的data属性中可设定相关变量,并把这些变量和Dom进行关联,达到修改data中属性即可修改Dom的功能 ( model(data) --> Vue --> view(dom) )。在Dom上,通过触发绑定方法,对相关数据进行修改 ( view(dom) --> Vue --> model(data) )。按这个思路来理解Vue,可以大概猜想出Vue有些功能为什么要被设计出来。

  • 插值:快速实现data和view的快速绑定,
  • 指令:对插值的补充,作用于模板上,用来实现模板的重复生成(v-for),动态显示(v-show, v-if),属性绑定(v-bind),事件绑定(v-on),对表单的增强(v-model)
  • 计算属性和观察属性:对插值和指令的补充,动态响应更新数据达到动态更新Dom的功效
  • 过滤:对插值和v-bind指令的补充,对要绑定到Dom上的数据进行过滤
  • 组件:Vue最强大的功能,对viewModel的实现,template就是view层,script就是model层

这些内容组成了Vue的骨架,掌握以上内容基本就能上手开发。下面我就利用上一章的例子把这些内容详细的介绍下(我按照我的理解打乱了官方的介绍顺序)

##1. 插值

<template>
    <div class="wrap">
        <p>{{info}}</p>
    </div>
</template>
<script>
    export default {
        data () {
            return {
                info: 'Hello world!'
            }
        }
    }
</script>

文本插值

处于data中返回值的info就是一个文本插值,这时如果修改info的值,对应DOM(p标签)的就会发生改变

上面data必须是函数的写法,是因为这是在一个组件内部,如果使用对象形式的写法,这个组件在经过多个实例化后,实际上是在共享一个data对象,更改任一组件data中的值,就会影响所有组件,所以组件内的data必须是函数,这样每个组件就形成独立的函数作用域,彼此不冲突。

属性插值

如果想把data中的值绑定成为html元素的属性,需要使用v-bind指令(简写方式是 : ),代码改造如下:

<p v-bind:title="info">{{info}}</p>

这个绑定值可以是普通的html属性,也可以是自定义属性

<p v-bind:data-cusData="info">{{info}}</p>

这时如果看最终渲染的页面,其效果是忽略cusData的大写,只显示为cusdata

<p data-cusdata="Hello vue!">Hello vue!</p>

如果这里是设置常用的class,id,title属性是没什么问题,但如果是自定义属性比如data-cusData这种类型的数据,就会被强制转为data-cusdata

如果要绑定多个属性值可以使用对象的形式

<p v-bind='{id: elemId, class: elemClass, "data-cusData": cusData}'>{{info}}</p>

Data中设置修改如下

data () {
    return {
        info: 'Hello vue!',
        elemId: 'pId',
        elemClass: 'pClass',
        cusData: 'hello world'
    }
}

因为class和style是我们常用的属性值,Vue针对这两个属性做了特殊处理

##2. 样式 ####1):class绑定对象语法

改造代码如下

<p class=‘static’ :class='{red: redFlag, font: fontFlag }'>{{info}}</p>

:class是v-bind:class的简写

对应data修改如下:

{
    ...
    redFlag: true,
    fontFlag: false
}

页面渲染结果如下:

<p class="static red">Hello vue!</p>

如例子显示,绑定对象的形式可以动态切换多个class,同时也支持与普通class共存

当绑定对象要进行多个class值的设定,沿用上面的写法会显得繁琐,我们可以把绑定的对象换成一个计算属性,在计算属性中动态的设定返回值。

<p class='static' :class='classObj'>{{info}}</p>

在计算属性中设定相关值

computed: {
    classObj () {
        let classStr = '';
        if (this.redFlag) {
            classStr += 'red';
        }
        if (this.fontFlag) {
            classStr += 'font';
        }
        return classStr;
    }
}

渲染结果如上,除了上面的写法,也可以结合下面介绍的绑定数组语法,把上面的例子再简化些

<p :class='[classObj, "static"]'>{{info}}</p>

####2) :class绑定数组语法

代码如下:

<p :class="[basicClass, redClass]">{{info}}</p>

data下数据修改如下:

{
    ...
    basicClass: 'f20 mb20',
    redClass: 'red'
}

这样最终渲染如下:

<p class="f20 mb20 red">Hello vue!</p>

在数组语法中,可以使用三元运算符控制某个元素class的添加和隐藏 代码改造如下:

<p :class="[showInfo ? basicClass : '', redClass]">{{info}}</p>

data数据修改如下:

{
    ...
    showInfo: false,
    ...
}

这时渲染的最早结果如下:

<p class="red">Hello vue!</p>

如果把showInfo设为true,渲染结果和上例一致

官方文档这里还介绍了对组件的class绑定处理,不过我觉得这样做其实会破坏组件的封装型,就算要添加或者移除某个class,最好还是通过props传值在组件内部自行处理

####3) :style绑定对象语法

:style的绑定对象语法和:class绑定对象语法使用方法一样,只是在写css属性名要注意下

<p :style='{color: redColor, "font-size": fontSize, backgroundColor: bgColor }'>{{info}}</p>

data数据修改如下:

{
    ...
    redColor: 'red',
    fontSize: '16px',
    bgColor: '#FF0'
    ...
}

如例css的属性名,可以改写成驼峰形式(backgroundColor),或者使用引号包裹起来("font-size")

当使用对象语法进行多个css属性设置时,可以使用计算属性进行绑定

<p :style='styleObj'>{{info}}</p>

计算属性设置如下

computed: {
    styleObj () {
        return `color: ${this.redColor}; fontSize: ${this.fontSize}; backgroundColor: ${this.bgColor}`; 
    }
}

渲染结果如下:

<p style="color: red; font-size: 16px; background-color: rgb(255, 255, 0);">Hello vue!</p>

上面设定样式的方式如果只是绑定单个对象是没问题的,但如果要使用数组的形式绑定多个对象就无法生效(解决方法参看下面)。

####4) :style绑定数组语法

使用:class绑定数组使用方法见下例:

<p :style='[colorStyle, fontStyle, backgroundColor]'>{{info}}</p>

这个时候要保证对应数组对象是对象的形式(上例是字符串形式):

这个例子中绑定对象的值分别在data和计算属性中设定,只是做演示,表示这个绑定值,可以是不同的来源值进行混合

在data中设定colorStyle

{
...
    colorStyle: {
        color: 'red'
    }
...
}

在计算属性中设定fontStyle和backgroundColor

computed: {
    fontStyle () {
       return {fontSize: this.fontSize}
    },
    backgroundColor () {
        return {backgroundColor: this.bgColor}
    }
}

这时的渲染结果和上例是一致的,但如果你把其中一个值,改成字符串形式

fontStyle () {
   return `fontSize: ${this.fontSize};`
}

这时你会发现Vue会忽略当前值的设定,所以在使用:style形式时,最好按对象形式返还设定的style。

###3.指令

我对指令的理解就是:指令是使模板具备了逻辑处理的能力,是对插值的一种补充,因为指令的存在才使得数据层和Dom层具备了相互绑定的能力。

按官方api,vue的指令如下:

v-text
v-html
v-show
v-if
v-else
v-else-if
v-for
v-on
v-bind
v-model
v-pre
v-cloak
v-once

1)v-text和v-bind

v-text实现文本绑定的能力,期望值是string

<p v-text="info"></p>
<p>{{info}}</p>

上面两种写法渲染后的结果一致,通常我们会使用第二种写法,比较简洁。这个指令期望的值是string,但如果绑定的值是一个对象,就会原样把对象输出。

<p>{{infoObj}}</p>

在data中设定一个infoObj

{
...
    infoObj: {
        msg: 'Hello vue!'
    }
...
}

这时页面渲染为

<p>{
  "msg": "Hello vue!"
}</p>

如果你进行下面的设定

infoObj: true,              // => true
或
infoObj: 3 > 2,             // => true
或
infoObj: Math.random(),     // => 渲染为一个不确定的随机数
或
infoObj: 2 + 3,             // => 5

所以这个指令会对传入的值进行一个转换,转换成string。事例中该指令的绑定值,我只使用了data下的值,但实际上这个值还可以是计算属性。

computed: {
    infoObj () {
        return 'Hello vue by computed!'
    }
}

对页面进行渲染时,页面的展示数据分为静态数据和动态数据,一般情况下静态数据存放在data属性下,动态数据通过计算属性进行返回(上例只是个样式,正常情况下计算属性会包含相关逻辑处理,相关会在计算属性那部分讲解,这里就不展开了)

v-bind用来动态的绑定一个或者多个属性

在属性插值部分已经对v-bind指令做了比较详细的介绍,有一些特殊点要特别说下:

绑定值可以是一个表达式

<p v-bind:title="info + ' 这时行内添加的信息'">{{info}}</p>

这时页面渲染结果为

<p title="Hello vue! 这时行内添加的信息">Hello vue!</p>

这是一个比较有用的特性,在开发过程中我们很容易碰到根据数据的不同展示不同的样式(比如符合某个条件时文案颜色变红)

<p :class='[this.login ? "red" : "", "static", elemClass]'>{{info}}</p>

在data中我们假定一个login的字段

{
...
    login: true
...
}

这时页面就会渲染为

<p class="red static pClass">Hello vue!</p>

如例中假设,比如我现在有个接口返回用户是否登陆,拿到接口返回数据,我们就可以根据接口返回的相关字段,动态的设定某一处的class。

通过修饰符.prop绑定DOM属性

如果在绑定属性后使用.prop修饰符,会忽略其他对该值的设定,强制使用设定的属性值

<p class="testProp" v-bind:text-content.prop="info" v-bind:className.prop="elemId">测试数据</p>

这时页面会渲染为

<p class="pId">Hello vue!</p>

如果删掉一个prop值

<p class="testProp" v-bind:text-content="info" v-bind:className.prop="elemId">测试数据</p>

对应的绑定值就会变成一个普通的属性值

<p class="pId" text-content="Hello vue!">测试数据</p>

####2) v-html

该指令是用来直接输出HTML内容

<div v-html="html"></div>

在data中设定如下值

{
...
    html: '<p>Hello vue!</p>',
...
}

这时页面的渲染结果为

<div><p>Hello vue!</p></div>

如果使用v-text会原样把字符串内容输出

<div v-text="html"></div>

渲染为

<div>&lt;p&gt;Hello vue!&lt;/p&gt;</div>

在官方文档中强调这种写法很容易引起XSS攻击,不能把这个能力开放给普通用户,在实际开发中,我也没碰到什么地方需要使用该指令。。。

3)v-show

根据表达式之真假值(这个值可以是data中的值,也可以是计算属性,后续不再赘述),切换元素的 display CSS 属性。

<p v-show="showFlag">{{info}}</p>

在data中设定showFlag的值

{
...
    showFlag: true,
...
}

这时页面渲染为

<p>Hello vue!</p>

如果showFlag设为false,页面渲染为

<p style="display: none;">Hello vue!</p>

v-show指令使用时有如下内容需要注意:

  • v-show不支持