Vue.js 的核心是一个允许采用简洁的模板语法来声明式地将数据渲染进 DOM 的系统。
文本插值 绑定元素属性
指令带有前缀 v-
,以表示它们是 Vue 提供的特殊 attribute。
以下是我学习中,自己对一些概念的理解,之后可以看看视频是否理解有误
数据和DOM是怎么产生联系的
我现在觉得是通过 vue 对象的 el 属性绑定 DOM ,data 属性中的 message 传递数据。
问题就是 el 和 data 是什么?message 是隐含对象嘛? message看上去只能传递数据而已,之后会有什么新的发现呢?
数据 和 DOM 建立了关联之后,所有东西都是响应式的?
修改 data 数据,页面显示的 DOM 元素内容就会立刻渲染为修改的内容。
v-bind 有什么用
我现在只能发现他是可以绑定 dom 元素的属性(这里的title),绑定之后,属性值可以接收 message 的值。
因此我现在觉得dom只有绑定到了vue对象上,才可以接受 data 里面的数据。
为什么叫 Vue 应用 ?
一个 Vue 应用会将其挂载到一个 DOM 元素上,然后对其进行完全控制。那个 HTML 是我们的入口,但其余都会发生在新创建的 Vue 实例内部。
v-if 可以控制 DOM 元素里的内容是否显示 true 和 false
Vue 也提供一个强大的过渡效果系统,可以在 Vue 插入/更新/移除元素时自动应用过渡效果。
Vue 还提供了
v-model
指令,它能轻松实现表单输入和应用状态之间的双向绑定。我的理解就是在表单输入一个值,可以显示在其他的dom元素里面
怎么理解 vue 中的实例
实例化了一个vue对象,只有创建实例了 才能用data啊 mounted啊 computed啊 created啊 之类的方法
- data 、computed怎么用
data :Vue 实例的数据对象,Vue 将会递归将 data 的 property 转换为 getter/setter,从而让 data 的 property 能够响应数据变化。
1 | data: { |
computed:计算属性将被混入到 Vue 实例中。所有 getter 和 setter 的 this 上下文自动地绑定为 Vue 实例。(特点是会把计算属性缓存起来,跟随依赖属性的变化而发生响应式变化。)
1 | computed: { |
就比如说一些需要计算得到值的函数 写在 methods 那里执行比较好 比如计算页面与视口的高度差 当用户向下翻动页面到一个值 就展示搜索框在最上面 这个功能 你写在 methods 里面也行 区别就是 在计算属性内部执行的函数只会在用到的时候才计算 并且有缓存功能 当前用户下次使用不用重新计算了 。
methods :methods 将被混入到 Vue 实例中。可以直接通过 VM 实例访问这些方法,或者在指令表达式中使用。方法中的 this
自动绑定为 Vue 实例。
什么是组件化应用构建
目前不懂的问题
- v-for 与 v-if 一同使用的问题现在仍然不清楚
- $emit 触发当前实例上的事件。附加参数都会传给监听器回调。
- 组件和 vue 实例之间的关系,实例化一个 vue 实例会发生什么变化
v-bind
来动态传递 prop 之间一些属性的关系
1 vue 实例
创建一个 Vue 实例
每个 Vue 应用都是通过用 Vue
函数创建一个新的 Vue 实例开始的:
1 | var app = new Vue({ |
当创建一个 Vue 实例时,你可以传入一个选项对象,使用选项对象来创建你想要的行为。
所有的 Vue 组件都是 Vue 实例,并且接受相同的选项对象 (一些根实例特有的选项除外)
数据与方法
数据 property(data 的属性)
当一个 Vue 实例被创建时,它将 data
对象中的所有的 property 加入到 Vue 的响应式系统中。当这些 property 的值发生改变时,视图将会产生“响应”,即匹配更新为新的值。
当这些数据改变时,视图会进行重渲染。但是只有当实例被创建时就已经存在于 data
中的 property 才是响应式的。也就是说如果你添加一个新的 property,它是不会触发任何视图的更新。
但是我们有时候就是一开始的时候不需要这个变量,之后想要添加,怎解决?我们需要一开始的时候定义这些变量,赋初始值就可以。类似下面这种,
1 | data: { |
Object.freeze() 阻止修改现有的 property
Object.freeze() 的位置需要编辑在定义的数据对象和创建vue 之间,否则不起作用,如图中所示:
1 | var obj = { |
实例 property 和实例方法
实例 property 与方法。它们都有前缀 $
,实例化对象使用 data 的 property 前面需要加一个 $
,以便与用户定义的 property 区分开来。
1 | // 数据与方法 |
实例生命周期钩子
每个 Vue 实例在被创建的时候都要经历一系列的初始化过程,比如设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化的时候更新 DOM 等。同时,在这个过程中也会运行一些叫做生命周期钩子的函数,这些函数可以让我们在不同时段添加自己的代码。
如 mounted
、updated
和 destroyed
。生命周期钩子的 this
上下文指向调用它的 Vue 实例。
不要在选项 property 或回调上使用箭头函数,比如
created: () => console.log(this.a)
或vm.$watch('a', newValue => this.myMethod())
。因为箭头函数并没有this
,this
会作为变量一直向上级词法作用域查找,直至找到为止,经常导致Uncaught TypeError: Cannot read property of undefined
或Uncaught TypeError: this.myMethod is not a function
之类的错误。
2 模板语法
插值
1)文本
数据绑定最常见的形式就是使用“Mustache”语法 (双大括号) 的文本插值:
2)原始 HTML
双大括号会将数据解释为普通文本,而非 HTML 代码。为了输出真正的 HTML,你需要使用 v-html
指令
1 | Using v-html directive: <span v-html="rawHtml"></span> |
3) Attribute
使用 v-bind 指令绑定属性,html 元素的属性。但是对于布尔 attribute (它们的值默认是true
),v-bind
中设置的变量,比如下面这个 isButtonDisabled 不赋值就是 true ,但是如果值是 null
、undefined
或 false
,则 disabled
attribute 不会被渲染,也不会起作用。
1 | <button v-bind:disabled="isButtonDisabled">Button</button> |
4)使用 JavaScript 表达式
使用“hexoMustache”语法 (双大括号),在大括号里面加入表达式,这些表达式会在所属 Vue 实例的数据作用域下作为 JavaScript 被解析。每个绑定都只能包含单个表达式。
1 | {{ number + 1 }} |
指令
指令 (Directives) 是带有 v-
前缀的特殊 attribute。指令 attribute 的值预期是单个 JavaScript 表达式。
指令的职责是,当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM。
1 | <p v-if="seen">现在你看到我了</p> //如果seen是false,那么p元素就会在文档中删除 |
参数:
某些指令可以接收一个参数,比如 v-bind
指令可以用于响应式地更新 HTML attribute:
1 | <a v-bind:href="url">...</a> //参数是href,html元素的 attribute |
动态参数
从 2.6.0 开始,可以用方括号括起来的 JavaScript 表达式作为一个指令的参数:比如下面的 attributeName 就是动态参数。
1 | <a v-bind:[attributename]="url"> ... </a> |
对动态参数的值的约束(对应于上例子的 url )
动态参数预期会求出一个字符串,异常情况下值为 null
。这个特殊的 null
值可以被显性地用于移除绑定。任何其它非字符串类型的值都将会触发一个警告。
对动态参数表达式的约束(对应于上例子的 attributename )
动态参数表达式有一些语法约束,因为某些字符,如空格和引号,放在 HTML attribute 名里是无效的,在 DOM 中使用模板时你需要回避大写键名。原因如下:
浏览器会将v-bind:[特性名]里的特性名强制转换为小写,导致vue实例的data属性特性名没有对应,才会导致错误,所以特性名直接写为小写就行了。
修饰符
1 | <form v-on:submit.prevent="onSubmit">...</form> |
修饰符 (modifier) 是以半角句号 .
指明的特殊后缀,用于指出一个指令应该以特殊方式绑定。.prevent
修饰符告诉 v-on
指令对于触发的事件调用 event.preventDefault()
:
v-bind 缩写
v-
前缀作为一种视觉提示,用来识别模板中 Vue 特定的 attribute。Vue为某些指令提供了简写,在所有支持 Vue 的浏览器都能被正确地解析。
v-bind
的缩写::
v-on
的缩写:@
3 计算属性和侦听器
计算属性
在vue中,模板内的表达式可以用于简单运算,但是对于复杂逻辑,应当使用计算属性。绑定计算属性和绑定普通的 property 一样。
有一个需求是把 message 里面的内容取反,我们可以通过一些方法计算出取反之后的值,如下我们用 reversedMessage 来获取这个最终取反的结果,reversedMessage 就是一个计算属性。在 dom 里面通过“Mustache”语法绑定这个属性,computed 里可以写成属性的具体算法,也就是getter函数。
1 | <p>Computed reversed message: "{{ reversedMessage}}"</p> |
计算属性和方法
计算属性是基于它们的响应式依赖进行缓存的。比如上面那个例子,当 message 发生变化之后, reversedMessage 就会相应变化。反之,reversedMessage 的值她缓存中的值。也就是,只要 message
还没有发生改变,多次访问 reversedMessage
计算属性会立即返回之前的计算结果,而不必再次执行函数。
计算属性的优点和适用条件
因此当我们遇到一个性能开销很大的计算属性,计算属性的缓存机制就非常的有用。如果没有缓存的话,每次访问计算属性就会执行 getter 函数,势必会造成占用内存。
计算属性有时候也可以用方法来替代,以上面取反为例,计算属性和方法的结果是一样的。
1 | <p>Computed reversed message: "{{ reversedMessage () }}"</p> //和计算属性的语法区别是() |
如果计算属性函数里面的属性不是响应式依赖,比如下面的 时间函数 ,计算属性可能一直不会更新,此时使用 方法会更好。
1 | computed: { |
计算属性和侦听属性
侦听属性:Vue 提供了一种更通用的方式来观察和响应 Vue 实例上的数据变动。
但是当一些数据需要随着其它数据变动而变动时,我们可能会滥用 wathch ,相反使用计算属性效率会更高。
计算属性的 setter
计算属性默认只有 getter,不过在需要时你也可以提供一个 setter
1 |
|
侦听器
Vue 通过 watch
选项提供了一个更通用的方法,来响应数据的变化。当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。
4 Class 与 Style 绑定
操作元素的 class 列表和内联样式是数据绑定的一个常见需求, v-bind
用于绑定 class
和 style
,只需要通过表达式计算出结果即可,表达式结果的类型除了字符串之外,还可以是对象或数组。
绑定 HTML Class
对象语法
我们可以传给 v-bind:class
一个对象,以动态地切换 class:
1 | <div v-bind:class="{ active: isActive }"></div>//isActive 为true则这个类,反之没有 |
v-bind:class
指令可以与普通的 class attribute 共存,当 isActive
或者 hasError
变化时,class 列表将相应地更新。
1 | <divclass="static" v-bind:class="{ active: isActive, 'text-danger': hasError }"></div> |
绑定的数据对象可以通过一个对象替代
1 | <div v-bind:class="classObject"></div> |
也可以通过 v-bind 绑定一个返回对象的计算属性。
数组语法
我们可以把一个数组传给 v-bind:class
,以应用一个 class 列表:
1 | <div v-bind:class="[activeClass, errorClass]"></div> |
用在组件上
当在一个自定义组件上使用 class
property 时,这些 class 将被添加到该组件的根元素上面。这个元素上已经存在的 class 不会被覆盖。
绑定内联样式
对象语法
v-bind:style
的对象语法十分直观,看着非常像 CSS,但其实是一个 JavaScript 对象。CSS property 名可以用驼峰式 (camelCase) 或短横线分隔 (kebab-case,记得用引号括起来) 来命名:
1 | <div v-bind:style="{color:activeColor,fontSize:fontSize + 'px'}">红色字体大小20px</div> |
数组语法
v-bind:style
的数组语法可以将多个样式对象应用到同一个元素上:
1 | <div v-bind:style="[baseStyles, overridingStyles]"></div> |
当 v-bind:style
使用需要添加浏览器引擎前缀的 CSS property 时,如 -webkit-transform
,Vue.js 会自动侦测并添加相应的前缀。
5 条件渲染
1) v-if
v-if
指令用于条件性地渲染一块内容。这块内容只会在指令的表达式返回 truthy 值(即除 false
、0
、""
、null
、undefined
和 NaN
以外皆为真值)的时候被渲染。也可以用 v-else
添加一个“else 块”:
1 | <h1 v-if="awesome">Vue is awesome!</h1> |
v-else
v-else
元素必须紧跟在带 v-if
或者 v-else-if
的元素的后面,否则它将不会被识别。
v-else-if
1 | <div v-if="type === 'A'"> |
用 key 管理可复用的元素
vue通常会复用已有元素而不是从头开始,高效的渲染元素,但是复用元素在某些场合并不合适,比如 在允许用户切换不同登录方式中,两个模板里面的input元素不会发生替换,更换的仅仅是 placeholder 。
1 | <template v-if="loginType === 'username'"> |
如下如在 username 状态下输入的用户名‘admin’,点击切换到 emai 状态用户名依然存在。

因此,我么需要给每个 input 添加一个具有唯一值的 key
attribute 。key 表示该元素是完全独立的,不要复用它们。修改之后的结果如上图第二个输入框。
1 | <input placeholder="Enter your username" key="username-input"> |
2) v-show
v-show
指令也可以根据条件展示元素
不同的是带有 v-show
的元素始终会被渲染并保留在 DOM 中。v-show
只是简单地切换元素的 CSS property display
。
v-show
不支持 元素,也不支持 v-else
。
v-if 和 v-show
一般来说,v-if
有更高的切换开销,而 v-show
有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show
较好;如果在运行时条件很少改变,则使用 v-if
较好。
3)v-if
与v-for
一起使用
当 v-if
与 v-for
一起使用时,v-for
具有比 v-if
更高的优先级。永远不要把 v-if
和 v-for
同时用在同一个元素上。v-for 具有更高的优先级,可能会渲染本应该被隐藏的数据。
6 列表渲染
用 v-for
把一个数组对应为一组元素
我们可以用 v-for
指令基于一个数组来渲染一个列表。v-for
指令需要使用 item in items
形式的特殊语法,其中 items
是源数据数组,而 item
则是被迭代的数组元素的别名。
在 v-for
块中,我们可以访问所有父作用域的 property。v-for
还支持一个可选的第二个参数,即当前项的索引( index )。
1 | <li v-for="(item,index) in items"> |
1) 在 v-for 里使用对象
遍历对象和遍历数组类似,使用 v-for=value in object
,同样可以添加第二个参数 key (键名),此外对象还可以用第三个参数作为索引 ( index ):
1 | <li v-for="(value,key,index) in object"> {{key}} : {{value}} </li> |
2 )维护状态
为了能跟踪每个节点的身份,从而重用和重新排序现有元素,解决解决就地复用产生的问题,需要给每项提供一个唯一的key attribute。
1 | <li v-for="(item,index) in items " :key='item.id'> |
3) 数组更新检测
Vue 将被侦听的数组的变更方法进行了包裹,所以它们也将会触发视图更新
1 | example.items.push({message:'AS'})//依然会更新页面 |
替换数组
非变更方法,例如 filter()
、concat()
和 slice()
。它们不会变更原始数组,而总是返回一个新数组,使用非变更方法时,可以用新数组替换旧数组:
4) 显示过滤/排序后的结果
有时,我们想要显示一个数组经过过滤或排序后的版本,而不实际变更或重置原始数据。在这种情况下,可以创建一个计算属性,来返回过滤或排序后的数组。
在计算属性不适用的情况下 (例如,在嵌套 v-for
循环中) 可以使用一个方法
组件
1) 组件基础
组件是可复用的 Vue 实例,且带有一个名,如下 button-counte
就是一个组件名。我们可以在一个通过 new Vue
创建的 Vue 根实例中,把这个组件作为自定义元素来使用:
1 | //创建一个名为 button-counte 的组件 |
因为组件是可复用的 Vue 实例,所以它们与 new Vue
接收相同的选项,例如 data
、computed
、watch
、methods
以及生命周期钩子等。仅有的例外是像 el
这样根实例特有的选项。
组件进行任意次数的复用,且每个组件都是独立的,因为没用一次组件,就会有一个它的新实例被创建。
在组件里data 必须是函数
因为 data 里面的数据是对象的话,当有多个组件实例的时候,他们会公用一个属性,数值一样并且相互影响。如果通过一个函数返回对象,那么每个组件实例可以维护一份被返回对象的独立的拷贝。
1 | //vue实例里面 data 对象 |
组件的组织
一个应用会以一棵嵌套的组件树的形式来组织:例如,你可能会有页头、侧边栏、内容区等组件,每个组件又包含了其它的像导航链接、博文之类的组件。
组件必须先注册才能被 Vue 识别,组件的注册类型:全局注册和局部注册
全局注册
通过 Vue.component
注册的组件就是全局组件。
1 | Vue.component('my-component-name', { |
全局注册的组件可以用在其被注册之后的任何 (通过 new Vue
) 新创建的 Vue 根实例,也包括其组件树中的所有子组件的模板中。
2) Prop
组件通过 prop 向子组件传递数据,Prop 是在组件上注册的一些自定义 attribute,当一个值传递给一个 prop attribute 的时候,它就变成了那个组件实例的一个 property。
1 | //这是一个定义好的组件 |
除了上面这中直接在模板名中写出 attribute 的值之外,我们还可以通过v-bind
来动态传递 prop,类似这样
1 | <blog-post v-for='post in posts' v-bind:key='post.id' v-bind:title='post.title'></blog-post> |
3)单个根元素
每个组件必须只有一个根元素,
深入了解组件
1 )组件注册
组件名
组件名是必须的,在 dom 里面可以直接把组件名当做一个 html 标签来使用。
组件名的命名方式:建议 :字母全小写且必须包含一个连字符 ,避免和 html元素冲突。
- 使用 kebab-case
当使用 kebab-case (短横线分隔命名) 定义一个组件时,你也必须在引用这个自定义元素时使用 kebab-case,例如<my-component-name>
。
- 使用 PascalCase
1 | Vue.component('MyComponentName', { /* ... */ }) |
当使用 PascalCase (首字母大写命名) 定义一个组件时,你在引用这个自定义元素时两种命名法都可以使用。也就是说<my-component-name>
和 MyComponentName
都是可接受的。
但是,直接在 DOM (即非字符串的模板) 中使用时,只有 kebab-case 是有效的。
全局注册
通常通过 Vue.component
来创建组件:
1 | //1.创建组件 |
全局注册的组件可以在子组件里面使用,也就是组件之间可以相互使用。
局部注册
在webpack 这样的构建系统, 全局注册所有的组件意味着即便你已经不再使用一个组件了,它仍然会被包含在你最终的构建结果中。这造成了用户下载的 JavaScript 的无谓的增加。这时我们可以选择局部注册组件。
1.通过一个普通的 JavaScript 对象来定义组件
1 | var ComponentA = { /* ... */ } |
2.在 components
选项中定义你想要使用的组件:
1 | new Vue({ |
对于 components
对象中的每个 property 来说,其 property 名就是自定义元素的名字( <component-a></component-a>
),其 property 值就是这个组件的选项对象。
局部注册的组件不可以在子组件之间相互使用。
Prop
HTML 中的 attribute 名是大小写不敏感的,所以浏览器会把所有大写字符解释为小写字符。这意味着当你使用 DOM 中的模板时,camelCase (驼峰命名法) 的 prop 名需要使用其等价的 kebab-case ( 短横线分隔命名 ) 命名: