Vue 框架很核心的功能就是双向的数据绑定。 双向是指:HTML 标签数据 绑定到 Vue 对象,另外反方向数据也是绑定的。通俗点说就是,Vue 对象的改变会直接影响到 HTML 的标签的变化,而且标签的变化也会反过来影响 Vue 对象的属性的变化。
这样以来,就彻底变革了之前 Dom 的开发方式,之前 Dom 驱动的开发方式尤其是以 jQuery 为主的开发时代,都是 dom 变化后,触发 js 事件,然后在事件中通过 js 代码取得标签的变化,再跟后台进行交互,然后根据后台返回的结果再更新 HTML 标签,异常的繁琐。有了 Vue 这种双向绑定,让开发人员只需要关心 json 数据的变化即可,Vue 自动映射到 HTML 上,而且 HTML 的变化也会映射回 js 对象上,开发方式直接变革成了前端由数据驱动的 开发时代,远远抛弃了 Dom 开发主导的时代了。
一、Vue 绑定文本:
数据绑定最常见的形式就是使用 “Mustache” 语法(双大括号)的文本插值,比如模板引擎:handlebars 中就是用的{{}}。
创建的 Vue 对象中的 data 属性就是用来绑定数据到 HTML 的。如:
<span>Message: {{ msg }}</span>
<script>
var app = new Vue({ // 创建Vue对象。Vue的核心对象。
el: '#app', // el属性:把当前Vue对象挂载到 div标签上,#app是id选择器
data: { // data: 是Vue对象中绑定的数据
msg: 'Hello Vue!' // message 自定义的数据
}
});
</script>
对于所有的数据绑定, Vue.js 都提供了完全的 JavaScript 表达式支持。
1、简单的拼接:
<span>Message: {{ msg + ' - ' + name }}</span>
<script>
var app = new Vue({ // 创建Vue对象。Vue的核心对象。
el: '#app', // el属性:把当前Vue对象挂载到 div标签上,#app是id选择器
data: { // data: 是Vue对象中绑定的数据
msg: 'Hi', // message 自定义的数据
name: 'flydragon' // name自定义的属性,vue可以多个自定义属性,属性类型也可是复杂类型
}
});
</script>
Hi - flydragon
2、计算、函数处理:
<td>{{ user.name=== '' ? '-' : user.name.subString(0,5) }}</td>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue入门之数据绑定-表达式运算</title>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
{{ msg + ' - ' + name }}
<p>
{{ isOk ? '123' : '456' }}
</p>
<p>我的年龄是: {{ age *2 }}</p>
</div>
<script>
var app = new Vue({ // 创建Vue对象。Vue的核心对象。
el: '#app', // el属性:把当前Vue对象挂载到 div标签上,#app是id选择器
data: { // data: 是Vue对象中绑定的数据
msg: 'Hi', // message 自定义的数据
name: 'flydragon',
isOk: true,
age: 18
}
});
</script>
</body>
</html>
<template v-if="user">
<div>{{formatDate(user.updateTime)}}</div>
</template>
methods:{
formatDate(dateTime) {
if (!dateTime) return '';
return parseTime(dateTime);
},
}
3、计算属性:
在做数据的绑定的时候,数据要进行处理之后才能展示到 html 页面上,虽然 vue 提供了非常好的表达式绑定的方法,但是只能应对低强度的需求。比如: 把一个日期按照规定格式进行输出,可能就需要我们对日期对象做一些格式化的出来,表达式可能就捉襟见肘了。Vue 对象提供的 computed 属性,可以让我们开发者在里面可以放置一些方法,协助我们绑定数据操作,这些方法可以跟 data 中的属性一样用,注意这些方法用的时候不要加()
。 如:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue入门之htmlraw</title>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<table>
<tr>
<!-- computed里面的函数可以直接当成data里面的属性用,非常方便,注意没有括号!!!-->
<td>生日</td><td>{{ getBirthday }}</td>
</tr>
<tr>
<td>年龄</td><td>{{ age }}</td>
</tr>
<tr>
<td>地址</td><td>{{ address }}</td>
</tr>
</table>
</div>
<script>
var app = new Vue({
el: '#app',
data: {
birthday: 914228510514, // 这是一个日期对象的值:1998年11月1日
age: 19,
address: '北京昌平区龙泽飞龙'
},
computed: {
// 把日期换成 常见规格格式的字符串。
getBirthday: function () {
var m = new Date(this.birthday);
return m.getFullYear() + '年' + m.getMonth() +'月'+ m.getDay()+'日';
}
}
});
</script>
</body>
</html>
4、数据绑定过滤器:
{{ message | filterA | filterB }}
在这个例子中,filterA
被定义为接收单个参数的过滤器函数,表达式 message
的值将作为参数传入到函数中。然后继续调用同样被定义为接收单个参数的过滤器函数 filterB
,将 filterA
的结果传递到 filterB
中。
过滤器是 JavaScript 函数,因此可以接收参数:
{{ message | filterA('arg1', arg2) }}
这里,filterA
被定义为接收三个参数的过滤器函数。其中 message
的值作为第一个参数,普通字符串 'arg1'
作为第二个参数,表达式 arg2
的值作为第三个参数。
二、Vue 绑定html标签属性:
Vue 中不能直接使用{{ expression }}
语法对 html 的标签属性进行绑定,而是用它特有的 v-bind 指令。语法结构:
<标签 v-bind:html标签属性名="要绑定的Vue对象的data里的属性名"></标签>
属性绑定简写:由于v-bind
使用非常频繁,所以 Vue 提供了简单的写法,可以去掉 v-bind 直接使用:
即可。如
<div v-bind:id="MenuContaineId">等价于<div :id="MenuContaineId">
1、简单的属性绑定:
<span v-bind:id="menuId">{{ menuName }}</span>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue入门之数据绑定--属性绑定</title>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<div v-bind:id="MenuContaineId">
<a href="#" v-bind:class="MenuClass">首页</a>
<a href="#" v-bind:class="MenuClass">产品</a>
<a href="#" v-bind:class="MenuClass">服务</a>
<a href="#" v-bind:class="MenuClass">关于</a>
</div>
</div>
<script>
var app = new Vue({
el: '#app',
data: { // data: 是Vue对象中绑定的数据
MenuClass: 'top-menu',
MenuContaineId: 'sitemenu'
}
});
</script>
</body>
</html>
2、布尔类型值用于属性绑定:标签的布尔类型的特性(属性),比如: disabled
特性。这类属性特点只要存在就表示 true
,v-bind
应用于这类属性的时候,如果绑定值为真,则输出挣钱的对应属性。如果为假值,则不会渲染此特性。
<button v-bind:disabled="isButtonDisabled">按钮</button>
如果 isButtonDisabled
的值是 null
、undefined
或 false
,则 disabled
特性甚至不会被包含在渲染出来的 <button>
元素中。 如果为真值:<button disabled="disabled">按钮</button>。
3、样式绑定:
对于普通的属性的绑定,只能用上面的讲的绑定属性的方式。而 Vue 专门加强了 class 和 style 的属性的绑定。可以有复杂的对象绑定、数组绑定样式和类。:class = "{className1:条件1,className2:条件2}",其中,className可以加上'',也可以不加引号。
例1:
<div id="app">
<div v-bind:id="MenuContaineId" v-bind:class="{ active: isActive }">
绑定颜色类
</div>
</div>
<script>
var app = new Vue({
el: '#app',
data: { // data: 是Vue对象中绑定的数据
MenuContaineId: 'menu',
isActive: true
}
});
</script>
例2:
<div id="app">
<div class="static"
v-bind:class="{ active: isActive, 'text-danger': hasError }">
</div>
</div>
<script>
var app = new Vue({
el: '#app',
data: { // data: 是Vue对象中绑定的数据
isActive: true,
hasError: false
}
});
</script>
结果:
<div id="app">
<div class="static active">
</div>
</div>
例3:
<div id="app">
<div class="static"
v-bind:class="classObject">
</div>
</div>
<script>
var app = new Vue({
el: '#app',
data: {
classObject: {
active: true,
'text-danger': false
}
}
});
</script>
结果:
<div id="app">
<div class="static active">
</div>
</div>
例4:
<template>
<div>
<div>
<el-select v-model="editSatus" placeholder="请选择">
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
</div>
<div>
<el-form>
<el-input
v-model="redtext"
:class="{'my-disabled':(editSatus === false)}"
></el-input>
</el-form>
<div v-for=" item in colors" :key="item">
<span :class="{'mytrue':(obj[`my${item}Change`] === 1),myred:(item === 'redtext')}">{{item}}</span>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
colors:['redtext','greentext','yellowtext'],
redtext: "redtext",
greentext: "greentext",
yellowtext: "yellowtext",
myredtextChange:1,
obj:{ myredtextChange:1,
mygreentextChange:0},
//是否可以编辑,默认可以
editSatus: true,
options: [
{
value: true,
label: "编辑"
},
{
value: false,
label: "查看"
}
]
};
},
methods: {
getText(item){
let val = 'my'+item+'Change';
return this.obj.myredtextChange;
}
}
};
</script>
<style lang="scss">
.my-disabled {
pointer-events: none;
}
.myred {
color: red;
.ivu-input.ivu-input-default {
color: red;
}
.ivu-select.ivu-select-single.ivu-select-default {
color: red;
}
textarea {
color: red;
}
.ivu-form-item-label {
color: red;
}
}
.mytrue{
font-style:oblique
}
</style>
例5:删除某行页面上以中划线表示并字体标红:
<el-table-column label="项目合同金额">
<template slot-scope="scope">
<span
:style="{color:(scope.row.status==2) ? 'red' : '#007bd9',
'text-decoration': (scope.row.status==2) ? 'line-through' : 'none'}"
>{{scope.row.projectMoney}}</span>
</template>
</el-table-column>
例6:
<div
class="exam-calendar"
:class="getClassName(examDayMap[data.day].length)"
v-if="examDayMap[data.day] && examDayMap[data.day].length > 0"
>
<div @mouseenter="showDrawer(data.day)" class="exam-name">
<span> {{ examDayMap[data.day].length + '个考试' }}</span>
</div>
</div>
methods:{
getClassName(examCount) {
if (examCount >= 5) {
return 'red';
} else if ((examCount < 5) & (examCount >= 3)) {
return 'orange';
} else if (examCount < 3) {
return 'blue';
}
}
}
.exam-calendar {
margin-top: 5px;
display: flex;
justify-content: center; /* 水平方向 居中*/
align-items: center; /* 垂直方向 居中*/
color: #fff;
background-color: #f1c98d;
border-color: #f1c98d;
border-radius: 15px;
padding: 8px;
cursor: pointer;
}
.red {
background-color: red;
border-color: red;
}
.blue {
background-color: blue;
border-color: blue;
}
4、绑定样式数组:
<div v-bind:class="[activeClass, errorClass]">
data: {
activeClass: 'active',
errorClass: 'text-danger'
}
5、内联样式绑定:内联样式的绑定,非常类似于样式类的操作。v-bind:style 的对象语法十分直观——看着非常像 CSS ,其实它是一个 JavaScript 对象。 CSS 属性名可以用驼峰式(camelCase)或短横分隔命名(kebab-case)。v-bind:style会自动添加前缀,即当 v-bind:style 使用需要特定前缀的 CSS 属性时,如 transform ,Vue.js 会自动侦测并添加相应的前缀。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue入门之htmlraw</title>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<div v-bind:style="{fontSize: size + 'px', backgroundColor: bgcolor, width: width}">
vue 入门系列教程
</div>
</div>
<script>
var app = new Vue({
el: '#app',
data: {
size: 19,
width: 200,
bgcolor: 'red'
}
});
</script>
</body>
</html>
5、数据绑定过滤器写法:
<!-- 在双花括号中 -->
{{ message | capitalize }}
<!-- 在 `v-bind` 中 -->
<div v-bind:id="rawId | formatId"></div>
你可以在一个组件的选项中定义本地的过滤器
filters: {
capitalize: function (value) {
if (!value) return ''
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
}
}
或者在创建 Vue 实例之前全局定义过滤器:
Vue.filter('capitalize', function (value) {
if (!value) return ''
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
})
new Vue({
// ...
})
三、输出纯html:
由于 Vue 对于输出绑定的内容做了提前 encode,保障在绑定到页面上显示的时候不至于被 xss 攻击。但某些场景下,我们确保后台数据是安全的,那么我们就要在网页中显示原生的 HTML 标签。Vue 提供了v-html
指令。
<div id="app">
<div v-bind:id="MenuContaineId" v-html="MenuBody">
</div>
</div>
<script>
var app = new Vue({
el: '#app',
data: { // data: 是Vue对象中绑定的数据
MenuContaineId: 'menu',
MenuBody: '<p>这里是菜单的内容</p>'
}
});
</script>
结果:
<div id="app">
<div id="menu">
<p>这里是菜单的内容</p>
</div>
</div>
四、双向绑定:以上均为单向绑定。双向绑定指令为v-model:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue入门之htmlraw</title>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<!-- v-model可以直接指向data中的属性,双向绑定就建立了 -->
<input type="text" name="txt" v-model="msg">
<p>您输入的信息是:{{ msg }}</p>
</div>
<script>
var app = new Vue({
el: '#app',
data: {
msg: '双向数据绑定的例子'
}
});
</script>
</body>
</html>
最终的结果就是:你改变 input 文本框的内容的时候,p 标签中的内容会跟着进行改变。
1、双向绑定的修饰符:
(1).lazy
在默认情况下,v-model
在每次 input
事件触发后将输入框的值与数据进行同步 (除了上述输入法组合文字时)。你可以添加 lazy
修饰符,从而转变为使用 change
事件进行同步:
<!-- 在“change”时而非“input”时更新 -->
<input v-model.lazy="msg" >
(2).number
如果想自动将用户的输入值转为数值类型,可以给 v-model
添加 number
修饰符:
<input v-model.number="age" type="number">
(3).trim:
如果要自动过滤用户输入的首尾空白字符,可以给 v-model
添加 trim
修饰符:
<input v-model.trim="msg">
2、双向绑定案例:
(1)文本:
1)单行文本:
<div id="example-1">
<input v-model="message" placeholder="edit me">
<p>Message is: {{ message }}</p>
</div>
<script>
new Vue({
el: '#example-1',
data: {
message: ''
}
})
</script>
2)多行文本:
<div id="example-textarea">
<span>Multiline message is:</span>
<p style="white-space: pre-line;">{{ message }}</p>
<br>
<textarea v-model="message" placeholder="add multiple lines"></textarea>
</div>
<script>
new Vue({
el: '#example-textarea',
data: {
message: ''
}
})
</script>
在文本区域插值 (<textarea>{{text}}</textarea>) 并不会生效,应用 v-model
来代替。
2、复选框:
<div id="example-3">
<input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
<label for="jack">Jack</label>
<input type="checkbox" id="john" value="John" v-model="checkedNames">
<label for="john">John</label>
<input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
<label for="mike">Mike</label>
<br>
<span>Checked names: {{ checkedNames }}</span>
</div>
<script>
new Vue({
el: '#example-3',
data: {
checkedNames: []
}
})
</script>
3、单选按钮:
<div id="example-4">
<input type="radio" id="one" value="One" v-model="picked">
<label for="one">One</label>
<br>
<input type="radio" id="two" value="Two" v-model="picked">
<label for="two">Two</label>
<br>
<span>Picked: {{ picked }}</span>
</div>
<script>
new Vue({
el: '#example-4',
data: {
picked: ''
}
})
</script>
4、选择框:
1)单选:
<div id="example-5">
<select v-model="selected">
<option disabled value="">请选择</option>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
<span>Selected: {{ selected }}</span>
</div>
<script>
new Vue({
el: '#example-5',
data: {
selected: ''
}
})
</script>
如果 v-model
表达式的初始值未能匹配任何选项,select
元素将被渲染为“未选中”状态。在 iOS 中,这会使用户无法选择第一个选项。因为这样的情况下,iOS 不会触发 change 事件。因此,更推荐像上面这样提供一个值为空的禁用选项。
下拉框值回显问题:需要值和类型一致,如:以下isMultipleProject=1,回显不了,因为isMultipleProject值为整形,而下拉框value值为字符型,
<el-select
v-model="isMultipleProject"
placeholder="请选择"
:disabled="updateDisable"
>
<el-option value="1" label="多产品"></el-option>
<el-option value="0" label="单产品"></el-option>
</el-select>
可以把下拉框值改成整形,:value表示整数型:
<el-option :value=1 label="多产品"></el-option>
<el-option :value=0 label="单产品"></el-option>
2)多选:绑定到数组
<div id="example-6">
<select v-model="selected" multiple style="width: 50px;">
<option>A</option>
<option>B</option>
<option>C</option>
</select>
<br>
<span>Selected: {{ selected }}</span>
</div>
<script>
new Vue({
el: '#example-6',
data: {
selected: []
}
})
</script>
3)远程搜索下拉:回显不需要加载列表,常用于下拉列表数据量较大的场景。
<template>
<el-select
v-model="value"
multiple
filterable
remote
reserve-keyword
placeholder="请输入关键词"
:remote-method="remoteMethod"
:loading="loading">
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</template>
<script>
export default {
data() {
return {
options: [],
value: [],
list: [],
loading: false,
states: ["Alabama", "Alaska", "Arizona", "Washington", "West Virginia"]
}
},
mounted() {
this.list = this.states.map(item => {
return { value: `value:${item}`, label: `label:${item}` };
});
},
methods: {
remoteMethod(query) {
if (query !== '') {
this.loading = true;
setTimeout(() => {
this.loading = false;
this.options = this.list.filter(item => {
return item.label.toLowerCase()
.indexOf(query.toLowerCase()) > -1;
});
}, 200);
} else {
this.options = [];
}
}
}
}
</script>
更多案例详见官网https://element.eleme.cn/#/zh-CN/component/installation