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><p>Hello vue!</p></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不支持