为什么学vue?
- vue是中国大神尤雨溪创建的js框架。
- Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。
- 任何描述都不及这个视频介绍来的有效:How to use Vue?
安装Vue
- 通过直接饮用在线的js库
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- 生产环境版本,优化了尺寸和速度 -->
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
- 通过npm包管理器
# 最新稳定版
$ npm install vue
在 NPM 包的 dist/ 目录你将会找到很多不同的 Vue.js 构建版本:
npm安装请查看官方详细介绍
第一次使用vue
- Hello Vue!
vue通过Vue构造函数创建实例对象,传递参数1,el:元素节点ID值,data:数据,最后再通过插值符号将data里的数据按需渲染到html页面里。
<body>
<div id="app">
{{ message }}
</div>
</body>
<script src="https://vuejs.org/js/vue.js"></script>
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
}
})
</script>
数据就是数据,text和html的区别,如果直接在数据里包裹标签:
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
message: '<h1>Hello Vue!</h1>'//没有效果
}
})
</script>
Vue基本语法、指令
基本指令
v-text:
-
期望值类型:
string
; -
用法:
用于更新元素的textContent,可以通过
{{}}
插值符号控制。 -
示例:
<!-- 两种写法一样 -->
<span v-text="msg"></span>
<span>{{msg}}</span>
- 完整实例:
<body>
<div id="app" v-text="message"></div>
</body>
<script src="https://vuejs.org/js/vue.js"></script>
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
}
})
</script>
虽然上面两个用法可以达到相同结果,但是仍然有细节的却别,如果用插值符号写在标签里面
<span>{{message}}</span>
会出现js文件没加载完,{{message}}
直接显示出来:
就像这样:
而把message写在属性里,就不会将变量暴露出来。
- 当然插值也可以拼接:
<body>
<div id="app">
The new guy said something:{{message}}
</div>
</body>
<script src="https://vuejs.org/js/vue.js"></script>
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
}
})
</script>
v-html:
-
期望值类型:
string
; -
用法:更新元素的 innerHTML 。注意:内容按普通 HTML 插入 - 不会作为 Vue 模板进行编译 。如果试图使用 v-html 组合模板,可以重新考虑是否通过使用组件来替代。
-
禁忌:
禁止在用户提交数据的内容部分使用v-html这样会非常容易导致xss攻击,一些用心不良的用户会利用脚本植入到提供给用户的其他页面中,在其他用户使用被篡改的页面时触发脚本,将用户信息数据发送给植入者!
-
示例:
<div v-html="html"></div>
- 完整示例:
<body>
<div id="app">
The new guy said something:{{message}}
<h1 v-text="vText"></h1>
<h1 v-html="vHtml"></h1>
<!-- <h1 v-text=""></h1> -->
</div>
</body>
<script src="./js/vue.js"></script>
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!',
vText:"<em>This is a v-text</em>,<i>Just like innerText</i>",
vHtml:"<em>This is a v-text</em>,<i>Just like innerText</i>",
// vText2:""
}
})
</script>
v-show:
- 期望值类型:都可;
- 用法:根据表达式的真假值切换display属性;
- 示例:
<span v-show="vShow">{{}}</span>
<span v-show=true/false>string</span>
- 完整实例:
<body>
<div id="app">
The new guy said something:{{message}}
<h1 v-text="vText"></h1>
<h1 v-html="vHtml"></h1>
<h1 v-show="vShow">vShow控制的元素</h1>
</div>
</body>
<script src="./js/vue.js"></script>
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!',
vText:"<em>This is a v-text</em>,<i>Just like innerText</i>",
vHtml:"<em>This is a v-text</em>,<i>Just like innerText</i>",
vShow:true//false
}
})
</script>
如果我改成false了:
v-if,v-else,v-else-if:
-
v-if,v-esle-if期望值:都可,v-else无值;
-
用法:
呈兄弟级节点关系,if值为false显示else的节点,一次类推,与jsif判断类似。 -
示例:
<div v-if="firstif">This is the if node</div>
<div v-else-if="secondeif">This is the else if node</div>
<div v-else>This is the else node</div>
- 完整实例:
<body>
<div id="app">
The new guy said something:{{message}}
<h1 v-text="vText"></h1>
<h1 v-html="vHtml"></h1>
<h1 v-show="vShow">vShow控制的元素</h1>
<div v-if="firstif">This is the if node</div>
<div v-else-if="secondeif">This is the else if node</div>
<div v-else>This is the else node</div>
</div>
</body>
<script src="./js/vue.js"></script>
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!',
vText:"<em>This is a v-text</em>,<i>Just like innerText</i>",
vHtml:"<em>This is a v-text</em>,<i>Just like innerText</i>",
vShow:false,
firstif:false,
secondeif:false
}
})
</script>
另外两个节点不会渲染:
- 同时控制一组元素:
//依旧是刚才的js代码:
<div v-if="firstif">This is the if node</div>
<div v-else-if="secondeif">This is the else if node</div>
<template v-else>
<h1>This is the else node</h1>
<h2>This is the else node</h2>
<h3>This is the else node</h3>
<h4>This is the else node</h4>
<h5>This is the else node</h5>
</template>
template并不会被显示出来:
v-for:
-
期望值类型:
Array
|Object
|number
|string
; -
用法:
基于源数据多次渲染元素或模板块。此指令之值,必须使用特定语法 alias in expression ,为当前遍历的元素提供别名
-
示例:
<div v-for="item in items">
{{ item.text }}
</div>
另外也可以为数组索引指定别名 (或者用于对象的键):
<div v-for="(item, index) in items"></div>
<div v-for="(val, key) in object"></div>
<div v-for="(val, key, index) in object"></div>
v-for 默认行为试着不改变整体,而是替换元素。迫使其重新排序的元素,你需要提供一个 key 的特殊属性:
<div v-for="item in items" :key="item.id">
{{ item.text }}
</div>
- 完整实例:
<ol>
<li v-for="item in items">{{item}}</li>
</ol>
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
items:["The","arr","list"]
}
})
</script>
- 但是更高明或者说更标准的用法是给渲染的元素添加Key值,更有性能的提升:
<ol>
<li v-for="(item,index) in items2" :key="index">{{item}}</li>
</ol>
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
items2:["The","arr2","list","and","get","keys"]
}
})
</script>
对比上一次的结果:
- 有时候,遍历对象往往比遍历数组多:
<ol>
<li v-for="(item,index) in objPerson" :key="index">name:{{item.name}},age:{{item.name}}</li>
</ol>
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
objPerson:[
{name:"Lucy",age:"18"},
{name:"Bob",age:"19"},
{name:"Tom",age:"21"}
]
}
})
</script>
输出结果:
- 遍历对象属性:
<ol>
<li v-for="(value,key,index) in objInfo" :key="index">
value:{{value}},
key:{{key}},
index:{{index}}
</li>
</ol>
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
objInfo:{
name:"Lucy",
age:"18",
sex:"girl",
hobby:"ride"
}
}
})
</script>
值得注意的是,vue和react的组件渲染列表时都会有个key值的,这个key是用于组件渲染时的索引,方便的是后续的更多操作,这个在vue的官网展示视频里有很好的体现,而这个key值同样可以根据自己定义id值绑定,只需要写成这样就是,{id:1}==>key:“id”
vue的数组方法
- 双向数据绑定的vue肯定支持数据的动态渲染!
- 新的代码加入,控制一个数组的数据添加:
<input type="button" value="Push" onclick="pushArr()">
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
objPerson: [
{ name: "Lucy", age: "18" },
{ name: "Bob", age: "19" },
{ name: "Tom", age: "21" }
]
}
})
function pushArr() {
console.log(app._data.objPerson.push({
name:"Ally",
age:"25"
}));
}
</script>
- 支持变化的元素渲染:
同样,vue实现了众多数组方法改变数据时的渲染:
- push()
- pop()
- shift()
- unshift()
- splice()
- reverse()
数据的筛选重组和排序
-
目前来说,可以将数据通过外部函数更改数据内容,外部函数要么主动触发,要么自动执行,自执行又会涉及到异步问题!vue为了解决对数据的加工,在实例化vue对象的时候,可以为对象添加一个用于更改数据的方法,这个方法包含在computed属性里。
-
来看一个完整的实例:
<ol>
<li v-for="(item,index) in sortedArr" :key="index">{{item}}</li>
</ol>
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
arrData:[9,7,10,4,15,20,3,0,8,11,27]//测试的数组,现在是无序的
},
computed:{
sortedArr:function(){
return this.arrData.sort(function(a,b) {
return a-b;
})
}
}
})
</script>
- 当然,也已通过if进行判断渲染:
<ol>
<template v-for="(item,index) in sortedArr" :key="index" v-if="item%2==0">
<li>{{item}}</li>
<li>uper index:{{index}}</li>
</template>
</ol>
//还是原来的数据
注释是vue自动产生的,因为使用了模板
v-on:
-
简写:
@
; -
期望值类型:
Function
|Inline Statement
|Object
; -
参数:
event
; -
修饰符:
.stop
- 调用event.stopPropagation()
。.prevent
- 调用event.preventDefault()
。.capture
- 添加事件侦听器时使用capture
模式。.self
- 只当事件是从侦听器绑定的元素本身触发时才触发回调。.{keyCode | keyAlias}
- 只当事件是从特定键触发时才触发回调。.native
- 监听组件根元素的原生事件。.once
- 只触发一次回调。.left
- (2.2.0) 只当点击鼠标左键时触发。.right
- (2.2.0) 只当点击鼠标右键时触发。.middle
- (2.2.0) 只当点击鼠标中键时触发。.passive
- (2.3.0) 以{ passive: true }
模式添加侦听器。
-
用法:
绑定事件监听器。事件类型由参数指定。表达式可以是一个方法的名字或一个内联语句,如果没有修饰符也可以省略。
用在普通元素上时,只能监听原生 DOM 事件。用在自定义元素组件上时,也可以监听子组件触发的自定义事件。
在监听原生 DOM 事件时,方法以事件为唯一的参数。如果使用内联语句,语句可以访问一个 $event 属性:v-on:click=“handle(‘ok’, $event)”。
从 2.4.0 开始,v-on 同样支持不带参数绑定一个事件/监听器键值对的对象。注意当使用对象语法时,是不支持任何修饰器的。
-
示例:
<!-- 方法处理器 -->
<button v-on:click="doThis"></button>
<!-- 内联语句 -->
<button v-on:click="doThat('hello', $event)"></button>
<!-- 缩写 -->
<button @click="doThis"></button>
<!-- 停止冒泡 -->
<button @click.stop="doThis"></button>
<!-- 阻止默认行为 -->
<button @click.prevent="doThis"></button>
<!-- 阻止默认行为,没有表达式 -->
<form @submit.prevent></form>
<!-- 串联修饰符 -->
<button @click.stop.prevent="doThis"></button>
<!-- 键修饰符,键别名 -->
<input @keyup.enter="onEnter">
<!-- 键修饰符,键代码 -->
<input @keyup.13="onEnter">
<!-- 点击回调只会触发一次 -->
<button v-on:click.once="doThis"></button>
<!-- 对象语法 (2.4.0+) -->
<button v-on="{ mousedown: doThis, mouseup: doThat }"></button>
- 一个完整的实例:
<h1>{{calcNum}}</h1>
<button v-on:click="addition">加一</button>
<button @click="substraction">减一</button>
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
calcNum:10
},
methods:{
addition:function(){
this.calcNum++
},
substraction(e){
this.calcNum--;
console.log(e);
}
}
})
</script>
原来:
减一:
加一:
其他的事件相关的只是其实和js一样,在这里不做详细解释。
修饰符
<!-- 阻止单击事件继续传播 -->
<a v-on:click.stop="doThis"></a>
<!-- 提交事件不再重载页面 -->
<form v-on:submit.prevent="onSubmit"></form>
<!-- 修饰符可以串联 -->
<a v-on:click.stop.prevent="doThat"></a>
<!-- 只有修饰符 -->
<form v-on:submit.prevent></form>
<!-- 添加事件监听器时使用事件捕获模式 -->
<!-- 即元素自身触发的事件先在此处理,然后才交由内部元素进行处理 -->
<div v-on:click.capture="doThis">...</div>
<!-- 只当在 event.target 是当前元素自身时触发处理函数 -->
<!-- 即事件不是从内部元素触发的 -->
<div v-on:click.self="doThat">...</div>
- 链式调用:修饰符可以像链式调用一样一次触发;
- 顺序问题:既然可以链式调用,那么触发顺序就变得非常重要了
使用修饰符时,顺序很重要;相应的代码会以同样的顺序产生。因此,用
v-on:click.prevent.self
会阻止所有的点击,而 v-on:click.self.prevent
只会阻止对元素自身的点击。
更详细的介绍请参照vue的文档
v-model:
-
期望值类型:依照表单而定;
-
限制:
<input/>
<select/>
<textarea/>
<components/>
-
修饰符:
.lazy
- 取代input
监听change
事件;.number
- 输入字符串转为有效的数字;.trim
- 输入首尾空格过滤。
-
双向的数据绑定:
你可以用
v-model
指令在表单<input>
、<textarea>
及<select>
元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。尽管有些神奇,但v-model
本质上不过是语法糖。它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。双向数据绑定通过表单改变数据的值,值反馈给vue对象的data属性,data属性同时修改内存内存的值内容,所有应用该内存的组件里的数据都会得到响应而改变其他元素渲染出来的值!
-
注意:
v-model 会忽略所有表单元素的 value、checked、selected 特性的初始值而总是将 Vue 实例的数据作为数据来源。你应该通过 JavaScript 在组件的 data 选项中声明初始值。
对于需要使用输入法 (如中文、日文、韩文等) 的语言,你会发现 v-model 不会在输入法组合文字过程中得到更新。如果你也想处理这个过程,请使用 input 事件。
-
示例:
The new guy said something:{{message}}
<input v-model="message" placeholder="edit me">
<p>Message is: {{ message }}</p>
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
</script>
初始状态:
开始删:
添加些单词:
你会发现原来的也改变了:
查看更多绑定请移步vue官方教程
v-bind:
操作元素的 class 列表和内联样式是数据绑定的一个常见需求。因为它们都是属性,所以我们可以用 v-bind 处理它们:只需要通过表达式计算出字符串结果即可。不过,字符串拼接麻烦且易错。因此,在将 v-bind 用于 class 和 style 时,Vue.js 做了专门的增强。表达式结果的类型除了字符串之外,还可以是对象或数组。
-
简写:
:
-
期望的值的类型:
any (with argument)
|Object (without argument)
; -
参数:
attrOrProp(optional)
; -
修饰符:
.prop
- 被用于绑定 DOM 属性(property)
。(差别在哪里?).camel
- (2.1.0+) 将kebab-case
特性名转换为camelCase
. (从 2.1.0 开始支持).sync
(2.3.0+) 语法糖,会扩展成一个更新父组件绑定值的v-on
侦听器。
-
用法
动态地绑定一个或多个特性,或一个组件
prop
到表达式。在绑定
class
或style
特性时,支持其它类型的值,如数组或对象。可以通过下面的教程链接查看详情。在绑定
prop
时,prop
必须在子组件中声明。可以用修饰符指定不同的绑定类型。没有参数时,可以绑定到一个包含键值对的对象。注意此时 class 和 style 绑定不支持数组和对象。
-
示例:
<!-- 绑定一个属性 -->
<img v-bind:src="imageSrc">
<!-- 缩写 -->
<img :src="imageSrc">
<!-- 内联字符串拼接 -->
<img :src="'/path/to/images/' + fileName">
<!-- class 绑定 -->
<div :class="{ red: isRed }"></div>
<div :class="[classA, classB]"></div>
<div :class="[classA, { classB: isB, classC: isC }]">
<!-- style 绑定 -->
<div :style="{ fontSize: size + 'px' }"></div>
<div :style="[styleObjectA, styleObjectB]"></div>
<!-- 绑定一个有属性的对象 -->
<div v-bind="{ id: someProp, 'other-attr': otherProp }"></div>
<!-- 通过 prop 修饰符绑定 DOM 属性 -->
<div v-bind:text-content.prop="text"></div>
<!-- prop 绑定。“prop”必须在 my-component 中声明。-->
<my-component :prop="someThing"></my-component>
<!-- 通过 $props 将父组件的 props 一起传给子组件 -->
<child-component v-bind="$props"></child-component>
<!-- XLink -->
<svg><a :xlink:special="foo"></a></svg>
- 一个完整的实例:
<template v-else>
<h1 :class="{colorblue:colorBlue}">This is the else node</h1>
<h2 :style="{fontSize: size + 'px'}">This is the else node</h2>
<h3>This is the else node</h3>
<h4>This is the else node</h4>
<h5>This is the else node</h5>
</template>
<ol>
<li v-for="(item,index) in arrData" :key="index" :class='color_+item'>{{item}}</li>
</ol>
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
vHtml: "<em>This is a v-text</em>,<i>Just like innerText</i>"
arrData:[9,7,10,4,15,20,3,0,8,11,27],
calcNum:10,
colorBlue:true,
size:30,
color_:"color_"
},
computed:{
sortedArr:function(){
return this.arrData.sort(function(a,b) {
return a-b;
})
}
}
</script>