原文链接
Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。
对于前端开发人员来说,大家使用过很多的Javascript框架。比如原生的JavaScript,Jquery,angularjs和rectjs等。那么Vue与这些框架相比,它的优势体现在哪里?
<div id="app">
{{ message }}
div>
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
}
})
如上几行代码就是一个简单的vue程序,你会发现id为app的div里显示了message的值,看起来这跟渲染一个字符串模板非常类似,但是 Vue 在背后做了大量工作。现在数据和 DOM 已经被建立了关联,所有东西都是响应式的。我们要怎么确认呢?打开你的浏览器的 JavaScript 控制台 (就在这个页面打开),并修改 app.message
的值,你将看到上例相应地更新。
Vue有很多v-
开头的指令,其本质是自定义属性。比如v-cloak
, v-text
, v-bind
, v-model
, v-on
等等,下面将逐个介绍。
在上面的程序中,如果你的网速太慢,会发现最一开始网页会显示{{message}}而非它的值,这涉及到Vue的生命周期,我们以后再聊。不过这样一个过程可能给用户带来不好的体验,因此你可以使用v-cloak
指令防止页面加载时的闪烁。
<style type="text/css">
/*
1、通过属性选择器 选择到 带有属性 v-cloak的标签 让他隐藏
*/
[v-cloak]{
/* 元素隐藏 */
display: none;
}
style>
<body>
<div id="app">
<div v-cloak >{{msg}}div>
div>
<script type="text/javascript" src="js/vue.js">script>
<script type="text/javascript">
var vm = new Vue({
// el 指定元素 id 是 app 的元素
el: '#app',
// data 里面存储的是数据
data: {
msg: 'Hello Vue'
}
});
script>
body>
html>
v-text
指令用于将数据填充到标签中,作用于插值表达式类似,但是没有闪动问题<div id="app">
<p v-text="msg">p>
<p>
{{msg}}
p>
div>
<script>
new Vue({
el: '#app',
data: {
msg: 'Hello Vue.js'
}
});
script>
v-text
相似 但是他可以将HTML片段填充到标签中v-html
,永不用在用户提交的内容上(因为谁也不知道某些傻叉用户会提交啥。。。)<div id="app">
<p v-html="html">p>
<p>{{message}}p>
<p v-text="text">p>
div>
<script>
let app = new Vue({
el: "#app",
data: {
message: "通过双括号绑定",
html: "html标签在渲染的时候被解析",
text: "html标签在渲染的时候被源码输出",
}
});
script>
<span v-pre>{{ this will not be compiled }}span>
<span v-pre>{{msg}}span>
<script>
new Vue({
el: '#app',
data: {
msg: 'Hello Vue.js'
}
});
script>
<span v-once>{{ msg}}span>
<script>
new Vue({
el: '#app',
data: {
msg: 'Hello Vue.js'
}
});
script>
v-on
是用来绑定事件的指令,如:v-on:click<body>
<div id="app">
<div>{{num}}div>
<div>
<button v-on:click="num++">点击1button>
<button @click="num++">点击2button>
<button @click='handle'>点击3button>
<button @click='handle()'>点击4button>
div>
div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js">script>
<script>
var vm = new Vue({
el: '#app',
data: {
num: 0
},
methods: {
handle: function(){
this.num ++;
}
},
})
script>
body>
上面代码中四个按钮都可以实现对num加一 的操作,但是按钮3和4值得注意一下,按钮3在调用方法时没有加括号而按钮4加了括号,两种方式都是可以的。原因在于如果我们的方法不需要参数,在调用时就无须括号。
实际上,如果方法内只需要一个event事件对象参数,我们在调用时也无须写括号,因为vue会帮助我们自动传入event对象,前提是方法的声明处只有一个参数。如果方法需要多个参数而我们没有传入,则默认传入event作为第一个参数,其他的会是undefined。
event.preventDefault()
或 event.stopPropagation()
是非常常见的需求。v-on
提供了事件修饰符
<a v-on:click.stop="doThis">a>
<form v-on:submit.prevent="onSubmit">form>
<a v-on:click.stop.prevent="doThat">a>
<div v-on:click.self="doThat">...div>
使用修饰符时,顺序很重要;相应的代码会以同样的顺序产生。因此,用 v-on:click.prevent.self 会阻止所有的点击,而 v-on:click.self.prevent 只会阻止对元素自身的点击。
v-on
在监听键盘事件时添加按键修饰符
<input v-on:keyup.13="submit">
<input v-on:keyup.enter="submit">
<input type="text" v-on:keyup.enter.space="alertMe" >
常用的按键修饰符
.enter => enter键
.tab => tab键
.delete (捕获“删除”和“退格”按键) => 删除键
.esc => 取消键
.space => 空格键
.up => 上
.down => 下
.left => 左
.right => 右
<script>
var vm = new Vue({
el:"#app",
methods: {
submit:function(){},
alertMe:function(){},
}
})
script>
config.keyCodes
自定义按键修饰符别名<div id="app">
预先定义了keycode 116(即F5)的别名为f5,因此在文字输入框中按下F5,会触发prompt方法
<input type="text" v-on:keydown.f5="prompt()">
div>
<script>
Vue.config.keyCodes.f5 = 116;
let app = new Vue({
el: '#app',
methods: {
prompt: function() {
alert('我是 F5!');
}
}
});
script>
<img v-bind:src="imageSrc">
<img :src="imageSrc">
1、 v-bind 中支持绑定一个对象
如果绑定的是一个对象 则 键为 对应的类名 值 为对应data中的数据
<ul class="box" v-bind:class="{textColor:isColor, textSize:isSize}">
<li>学习Vueli>
<li>学习Nodeli>
<li>学习Reactli>
ul>
<div v-bind:style="{color:activeColor,fontSize:activeSize}">对象语法div>
<sript>
var vm= new Vue({
el:'.box',
data:{
isColor:true,
isSize:true,
activeColor:"red",
activeSize:"25px",
}
})
sript>
<style>
.box{
border:1px dashed #f0f;
}
.textColor{
color:#f00;
background-color:#eef;
}
.textSize{
font-size:30px;
font-weight:bold;
}
style>
2、 v-bind 中支持绑定一个数组 数组中classA和 classB 对应为data中的数据
这里的classA 对用data 中的 classA
这里的classB 对用data 中的 classB
<ul class="box" :class="[classA, classB]">
<li>学习Vueli>
<li>学习Nodeli>
<li>学习Reactli>
ul>
<script>
var vm= new Vue({
el:'.box',
data:{
classA:‘textColor‘,
classB:‘textSize‘
}
})
script>
<style>
.box{
border:1px dashed #f0f;
}
.textColor{
color:#f00;
background-color:#eef;
}
.textSize{
font-size:30px;
font-weight:bold;
}
style>
<div v-bind:style="styleObject">绑定样式对象div>'
<div v-bind:style="{ color: activeColor, fontSize: fontSize,background:'red' }">内联样式div>
<div v-bind:style="[styleObj1, styleObj2]">div>
<script>
new Vue({
el: '#app',
data: {
styleObject: {
color: 'green',
fontSize: '30px',
background:'red'
},
activeColor: 'green',
fontSize: "30px"
},
styleObj1: {
color: 'red'
},
styleObj2: {
fontSize: '30px'
}
script>
<div id="app">
<span v-if="flag">
如果flag为true则显示,false不显示!
span>
div>
<script>
var vm = new Vue({
el:"#app",
data:{
flag:true
}
})
script>
----------------------------------------------------------
<div v-if="type === 'A'">
A
div>
<div v-else-if="type === 'B'">
B
div>
<div v-else-if="type === 'C'">
C
div>
<div v-else>
Not A/B/C
div>
<script>
new Vue({
el: '#app',
data: {
type: 'C'
}
})
script>
<ul id="example-1">
<li v-for="item in items">
{{ item.message }}
li>
ul>
<script>
new Vue({
el: '#example-1',
data: {
items: [
{ message: 'Foo' },
{ message: 'Bar' }
],
}
})
script>
v-if
和 v-for
v-if
与 v-for
一起使用时,v-for
具有比 v-if
更高的优先级。
<div v-if='v==13' v-for='(v,k,i) in obj'>{{v + '---' + k + '---' + i}}div>
<script>
new Vue({
el: '#example-1',
data: {
items: [
{ message: 'Foo' },
{ message: 'Bar' }
],
obj: {
uname: 'zhangsan',
age: 13,
gender: 'female'
}
}
})
script>
key 的作用
<ul>
<li v-for="item in items" :key="item.id">...li>
ul>
需求说明:
实现图:
代码:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
head>
<body>
<div id="app" class="container">
<table class="table table-hover table-bordered">
<thead>
<tr>
<th scope="col">IDth>
<th scope="col">书籍名称th>
<th scope="col">出版日期th>
<th scope="col">价格th>
<th scope="col">购买数量th>
<th scope="col">操作th>
tr>
thead>
<tbody>
<tr v-for="(book,index) in books">
<td>{{index+1}}td>
<td>{{book.name}}td>
<td>{{book.date}}td>
<td>{{book.price | showPrice}}td>
<td>
<button class="btn btn-sm btn-secondary" @click="decrement(index)">-button>
{{book.count}}
<button class="btn btn-sm btn-secondary" @click="increment(index)">+button>
td>
<td>
<button class="btn btn-sm btn-danger" @click="removeItem(index)">删除button>
td>
tr>
tbody>
table>
<span>总价格:{{totalPrice | showPrice}}span>
div>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous">script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous">script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous">script>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js">script>
<script>
const app = new Vue({
el: "#app",
data: {
books: [
{
name: '《算法导论》',
date: '2016-9',
price: 85,
count: '1'
},
{
name: '《UNIX编程艺术》',
date: '2016-2',
price: 99,
count: '1'
},
{
name: '《编程珠玑》',
date: '2008-10',
price: 108,
count: '1'
},
{
name: '《代码大全》',
date: '2006-3',
price: 79,
count: '1'
}
],
},
filters: {
showPrice(value){
return '¥' + value.toFixed(2);
}
},
computed: {
totalPrice(){
let total = 0;
for (let item of this.books){
total += item.price * item.count;
}
return total;
}
},
methods: {
increment(index){
this.books[index].count++;
},
decrement(index){
if (this.books[index].count > 0){
this.books[index].count--;
}
},
removeItem(index){
this.books.splice(index,1);
}
}
});
script>
body>
html>