声明式渲染
Vue.js 的核心是一个允许采用简洁的模板语法来声明式地将数据渲染进 DOM 的系统
{{ message }}
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
}
})
除了文本插值,我们还可以像这样来绑定元素 attribute:
鼠标悬停几秒钟查看此处动态绑定的提示信息!
var app2 = new Vue({
el: '#app-2',
data: {
message: '页面加载于 ' + new Date().toLocaleString()
}
})
条件与循环
控制元素是否显示
现在你看到我了
var app3 = new Vue({
el: '#app-3',
data: {
seen: true
}
})
在控制台输入 app3.seen = false,你会发现之前显示的消息消失了。
v-for指令可以绑定数组的数据来渲染一个项目列表
-
{{ todo.text }}
var app4 = new Vue({
el: '#app-4',
data: {
todos: [
{ text: '学习 JavaScript' },
{ text: '学习 Vue' },
{ text: '整个牛项目' }
]
}
})
在控制台里,输入 app4.todos.push({ text: ‘新项目’ }),你会发现列表最后添加了一个新项目。
处理用户输入
v-on 指令添加一个事件监听器,通过它调用在 Vue 实例中定义的方法:
{{ message }}
var app5 = new Vue({
el: '#app-5',
data: {
message: 'Hello Vue.js!'
},
methods: {
reverseMessage: function () {
this.message = this.message.split('').reverse().join('')
}
}
})
v-model 指令,它能轻松实现表单输入和应用状态之间的双向绑定
{{ message }}
var app6 = new Vue({
el: '#app-6',
data: {
message: 'Hello Vue!'
}
})
computed计算属性
计算属性结果会被缓存起来,当依赖的响应式属性 发生变化时,才会重新计算,返回最终结果
1
监听属性:
watch:{
aaa:function(){}
}//侦听 监视的作用:他依赖的属性有没有改变,如果改变,aaa2就会改变
插值
文本
数据绑定最常见的形式就是使用“Mustache”语法 (双大括号) 的文本
插值:
Message: {{ msg }}
通过使用 v-once 指令,你也能执行一次性地插值,当数据改变时,
插值处的内容不会更新。但请留心这会影响到该节点上的其它数据绑定:
这个将不会改变: {{ msg }}
使用 JavaScript 表达式
模板中,我们一直都只绑定简单的 property 键值。但实际上,对于所有的数据绑定,Vue.js 都提供了完全的 JavaScript 表达式支持
{{ number + 1 }}
{{ ok ? 'YES' : 'NO' }}
{{ message.split('').reverse().join('') }}
这些表达式会在所属 Vue 实例的数据作用域下作为 JavaScript 被
解析。有个限制就是,每个绑定都只能包含单个表达式,所以下面的例
子都不会生效。
{{ var a = 1 }}
{{ if (ok) { return message } }}
指令
v-bind 缩写
v-on 缩写
看起来可能与普通的 HTML 略有不同,但 : 与 @ 对于 attribute 名来说都是合法字符,在所有支持 Vue 的浏览器都能被正确地解析。
条件渲染
v-if 指令用于条件性地渲染一块内容。这块内容只会在指令的表达式返回 truthy 值的时候被渲染。
Vue is awesome!
也可以用 v-else 添加一个“else 块”:
Vue is awesome!
no
在 元素上使用 v-if 条件渲染分组
因为 v-if 是一个指令,所以必须将它添加到一个元素上。但是如果想切换多个元素呢?此时可以把一个 元素当做不可见的包裹元素,并在上面使用 v-if。最终的渲染结果将不包含 元素。
Title
Paragraph 1
Paragraph 2
v-else
你可以使用 v-else 指令来表示 v-if 的“else 块”:
Now you see me
Now you don't
v-else 元素必须紧跟在带 v-if 或者 v-else-if 的元素的后面,否则它将不会被识别。
v-else-if,顾名思义,充当 v-if 的“else-if 块”,可以连续使用:
A
B
C
Not A/B/C
类似于 v-else,v-else-if 也必须紧跟在带 v-if 或者 v-else-if 的元素之后。
v-show 指令
Hello!
不同的是带有 v-show 的元素始终会被渲染并保留在 DOM 中。v-show 只是简单地切换元素的 CSS property display
注意,v-show 不支持 元素,也不支持 v-else。
列表渲染
v-for 指令基于一个数组来渲染一个列表。v-for 指令需要使用 item in items 形式的特殊语法,其中 items 是源数据数组,而 item 则是被迭代的数组元素的别名。
-
{{ item.message }}
var example1 = new Vue({
el: '#example-1',
data: {
items: [
{ message: 'Foo' },
{ message: 'Bar' }
]
}
})
v-for 来遍历一个对象的 property。
-
{{ value }}
new Vue({
el: '#v-for-object',
data: {
object: {
title: 'How to do lists in Vue',
author: 'Jane Doe',
publishedAt: '2016-04-10'
}
}
})
数组检测
变更方法
Vue 将被侦听的数组的变更方法进行了包裹,所以它们也将会触发视图更新。这些被包裹过的方法包括:
push()
pop()
shift()
unshift()
splice()
sort()
reverse()
你可以打开控制台,然后对前面例子的 items 数组尝试调用变更方法。比如 example1.items.push({ message: ‘Baz’ })。
变更方法,顾名思义,会变更调用了这些方法的原始数组。相比之下,也有非变更方法,
例如 filter()、concat() 和 slice()。它们不会变更原始数组,而总是返回一个新数组。
当使用非变更方法时,可以用新数组替换旧数组:
example1.items = example1.items.filter(function (item) {
return item.message.match(/Foo/)
})
你可能认为这将导致 Vue 丢弃现有 DOM 并重新渲染整个列表。幸运的是,事实并非如此。Vue 为
了使得 DOM 元素得到最大范围的重用而实现了一些智能的启发式方法,所以用一个含有相同元素的
数组去替换原来的数组是非常高效的操作。
显示过滤/排序后的结果
我们想要显示一个数组经过过滤或排序后的版本,而不实际变更或重置原始数据。在这种情况下,可以创建一个计算属性,来返回过滤或排序后的数组。
例子:
1
data: {
array: [ 1, 2, 3, 4, 5 ]
},
computed: {
dianji: function () {
return this.array.filter(function (number) {
return number % 2 === 0
})
}
}
在计算属性不适用的情况下 (例如,在嵌套 v-for 循环中) 你可以使用一个方法:
- {{ n }}
data: {
sets: [[ 1, 2, 3, 4, 5 ], [6, 7, 8, 9, 10]]
},
methods: {
even: function (numbers) {
return numbers.filter(function (number) {
return number % 2 === 0
})
}
}
事件处理
监听事件
可以用 v-on 指令监听 DOM 事件,并在触发时运行一些 JavaScript 代码。
例子:
The button above has been clicked {{ counter }} times.
var example1 = new Vue({
el: '#app',
data: {
counter: 0
}
})
事件处理方法
然而许多事件处理逻辑会更为复杂,所以直接把 JavaScript 代码写在 v-on 指令中是不可行的。因此 v-on 还可以接收一个需要调用的方法名称。
例子:
var example2 = new Vue({
el: '#example-2',
data: {
name: 'Vue.js'
},
// 在 `methods` 对象中定义方法
methods: {
greet: function (event) {
// `this` 在方法里指向当前 Vue 实例
alert('Hello ' + this.name + '!')
// `event` 是原生 DOM 事件
if (event) {
alert(event.target.tagName)
}
}
}
})
// 也可以用 JavaScript 直接调用方法
example2.greet() // => 'Hello Vue.js!'
内联处理器中的方法
除了直接绑定到一个方法,也可以在内联 JavaScript 语句中调用方法:
new Vue({
el: '#example-3',
methods: {
say: function (message) {
alert(message)
}
}
})
有时也需要在内联语句处理器中访问原始的 DOM 事件。可以用特殊变量 $event 把它传入方法:
Submit
methods: {
warn: function (message, event) {
// 现在我们可以访问原生事件对象
if (event) {
event.preventDefault()
}
alert(message)
}
}
事件修饰符
.stop 阻止事件冒泡
.prevent阻止事件的默认行为
.capture事件捕获
.self自身触发
.once只触发一次
使用修饰符时,顺序很重要;相应的代码会以同样的顺序产生。因此,用 v-on:click.prevent.self 会阻止所有的点击,而 v-on:click.self.prevent 只会阻止对元素自身的点击。
.once 修饰符还能被用到自定义的组件事件上
Vue 还对应 addEventListener 中的 passive 选项提供了 .passive 修饰符。
这个 .passive 修饰符尤其能够提升移动端的性能。
不要把 .passive 和 .prevent 一起使用,因为 .prevent 将会被忽略,同时浏览器可能会向你展示一个警告。请记住,.passive 会告诉浏览器你不想阻止事件的默认行为。
按键修饰符
在监听键盘事件时,我们经常需要检查详细的按键。Vue 允许为 v-on 在监听键盘事件时添加按键修饰符:
你可以直接将 KeyboardEvent.key 暴露的任意有效按键名转换为 kebab-case 来作为修饰符。
在上述示例中,处理函数只会在 $event.key 等于 PageDown 时被调用。
表单输入绑定
你可以用 v-model 指令在表单 、 及 元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。尽管有些神奇,但 v-model 本质上不过是语法糖。它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。
基础用法
文本
Message is: {{ message }}
多行文本
Multiline message is:
{{ message }}
在文本区域插值 ({{text}}) 并不会生效,应用 v-model 来代替。
复选框
单个复选框,绑定到布尔值:
多个复选框,绑定到同一个数组:
Checked names: {{ checkedNames }}
new Vue({
el: '#example-3',
data: {
checkedNames: []
}
})
单选按钮
Picked: {{ picked }}
new Vue({
el: '#example-4',
data: {
picked: ''
}
})
选择框
Selected: {{ selected }}
new Vue({
el: '...',
data: {
selected: ''
}
})
多选时 (绑定到一个数组):
Selected: {{ selected }}
new Vue({
el: '#example-6',
data: {
selected: []
}
})
用 v-for 渲染的动态选项:
{{ option.text }}
Selected: {{ selected }}
new Vue({
el: '...',
data: {
selected: 'A',
options: [
{ text: 'One', value: 'A' },
{ text: 'Two', value: 'B' },
{ text: 'Three', value: 'C' }
]
}
})
值绑定
对于单选按钮,复选框及选择框的选项,v-model 绑定的值通常是静态字符串 (对于复选框也可以是布尔值):
但是有时我们可能想把值绑定到 Vue 实例的一个动态 property 上,这时可以用 v-bind 实现,并且这个 property 的值可以不是字符串。
复选框
type="checkbox"
v-model="toggle"
true-value="yes"
false-value="no"
>
// 当选中时
vm.toggle === 'yes'
// 当没有选中时
vm.toggle === 'no'
单选按钮
// 当选中时
vm.pick === vm.a
选择框的选项
// 当选中时
typeof vm.selected // => 'object'
vm.selected.number // => 123
修饰符
.lazy
.number
如果想自动将用户的输入值转为数值类型,可以给 v-model 添加 number 修饰符:
这通常很有用,因为即使在 type=“number” 时,HTML 输入元素的值也总会返回字符串。如果这个值无法被 parseFloat() 解析,则会返回原始的值。
.trim
如果要自动过滤用户输入的首尾空白字符,可以给 v-model 添加 trim 修饰符:
组件
组件式vue最强大的功能之一
可以扩展html元素,封装可以重用的代码
优点:
能减少代码的重用,提高开发效率
降低页面的融合度,使页面更方便维护和管理
// `` es6模板字符串
var str = "hello world";
var str = `hello world`;
//``支持强制换行不出错! 而''强制换行会报错
组件注册
在注册一个组件的时候,我们始终需要给它一个名字。比如在全局注册的时候我们已经看到了:
Vue.component('my-component-name', { /* ... */ })
组件名就是 Vue.component 的第一个参数
组件名大小写
定义组件名的方式有两种:
使用 kebab-case
Vue.component('my-component-name', { /* ... */ })
当使用 kebab-case (短横线分隔命名) 定义一个组件时,你也必须在引用这个自定义元素时使用 kebab-case,例如 。
使用 PascalCase
Vue.component('MyComponentName', { /* ... */ })
当使用 PascalCase (首字母大写命名) 定义一个组件时,你在引用这个自定义元素时两种命名法都可以使用。也就是说 和 都是可接受的。注意,尽管如此,直接在 DOM (即非字符串的模板) 中使用时只有 kebab-case 是有效的
全局注册
Vue.component 来创建组件:
Vue.component('my-component-name', {
// ... 选项 ...
})
这些组件是全局注册的。也就是说它们在注册之后可以用在任何新创建的 Vue 根实例 (new Vue) 的模板中。比如:
Vue.component('component-a', { /* ... */ })
Vue.component('component-b', { /* ... */ })
Vue.component('component-c', { /* ... */ })
new Vue({ el: '#app' })
在所有子组件中也是如此,也就是说这三个组件在各自内部也都可以相互使用。
局部注册
全局注册往往是不够理想的。比如,如果你使用一个像 webpack 这样的构建系统,全局注册所有的组件意味着即便你已经不再使用一个组件了,它仍然会被包含在你最终的构建结果中。这造成了用户下载的 JavaScript 的无谓的增加。
在这些情况下,你可以通过一个普通的 JavaScript 对象来定义组件:
var ComponentA = { /* ... */ }
var ComponentB = { /* ... */ }
var ComponentC = { /* ... */ }
然后在 components 选项中定义你想要使用的组件:
new Vue({
el: '#app',
components: {
'component-a': ComponentA,
'component-b': ComponentB
}
})
对于 components 对象中的每个 property 来说,其 property 名就是自定义元素的名字,其 property 值就是这个组件的选项对象。组件代码!
注意局部注册的组件在其子组件中不可用。例如,如果你希望 ComponentA 在 ComponentB 中可用,则你需要这样写:
var ComponentA = { /* ... */ }
var ComponentB = {
components: {
'component-a': ComponentA
},
// ...
}
或者如果你通过 Babel 和 webpack 使用 ES2015 模块,那么代码看起来更像:
import ComponentA from './ComponentA.vue'
export default {
components: {
ComponentA
},
// ...
}
注意在 ES2015+ 中,在对象中放一个类似 ComponentA 的变量名其实是 ComponentA: ComponentA 的缩写,即这个变量名同时是:
用在模板中的自定义元素的名称
包含了这个组件选项的变量名
Vue.component('cpn',{
template:`
这里是组件啊
`
})
Vue.component('cpn1',{
template:`
这个更简单诶
`
})
var vm = new Vue({
el:"#app",
data:{
},
components:{
}
})
组件之间的通信传值
父组件给子组件传值(当只有一个组件时,vue传值 vue实例是父组件)
Vue.component('cpn',{
template:`
这里是子组件 父组件是vue实例哦
{{txt}}
`,
props:['txt']
})
var vm = new Vue({
el:"#app",
data:{
cccc:"这里是父组件哦"
}
})
父传子组件传值
Vue.component('fu',{
template:`
`,
data:function(){
return{
array:["苹果","香蕉","桔子"],
sj:""
}
},
methods:{
add:function(){
this.$data.array.push(this.sj);
this.sj=""
}
}
})
Vue.component('zi',{
props:["list"],
template:`
- {{item}}
`
})
var vm = new Vue({
el:"#app",
data:{
}
})
子组件给父组件传值($emit(“事件”,“参数”))
Vue.component('fu',{
template:`
我是父组件
{{aaa}}
`,
data:function(){
return{
aaa:""
}
},
methods:{
rev:function(txt){
this.aaa=txt
}
}
})
Vue.component('zi',{
template:`
我是子组件
`,
data:function(){
return{
aa:"我是子组件,传值给父组件"
}
},
methods:{
add:function(){
this.$emit('zidingyi',this.aa)
}
}
})
var vm = new Vue({
el:"#app",
data:{
}
})
子组件给父组件传值 ($emit(“事件”,“参数”))
Vue.component('fu',{
template:`
这里是父组件
- {{item}}
`,
data:function(){
return{
message:[],
name:1,
nam:2
}
},
methods:{
adda:function(ss){
this.message.push(ss);
}
}
})
Vue.component('zi',{
template:`
`,
data:function(){
return{
mes:""
}
},
props:['txt'],
methods:{
add:function(){
this.$emit('zidingyi',this.txt+":"+this.mes);
this.mes=""
}
}
})
var vm = new Vue({
el:"#app",
data:{
}
})