Vue是一套构建用户界面的渐进式框架。
文档:https://cn.vuejs.org/v2/guide
所有api:https://cn.vuejs.org/v2/api/
模板语法
声明时渲染
Vue.js 的核心是一个允许你采用简洁的模板语法来声明式的将数据渲染进 DOM 的系统。
- 文本插值
|
|
- v-text:更新元素的 textContent
其实,双花括号就是v-text
的语法糖123<p>{{msg}}</p>等同于<p v-text="msg"></p>
|
|
此时,#app里的内容会变成Hello Vue
响应式修改:
ps:除了数据属性,Vue 实例还提供了一些有用的实例属性与方法,它们都有前缀 $,以便与用户定义的属性区分开来
- v-html:更新元素的 innerHTML
|
|
|
|
参考文档:https://cn.vuejs.org/v2/guide/
菜鸟教程:vue模板语法
补充知识
- el:挂载点,不能是body
- data:数据对象,推荐在实例创建之前就预设好所有的数据
- 双花括号其实是v-text的语法糖
响应式系统
|
|
计算属性computed
双括号里面一般用作声明,所以不推荐里面进行太过复杂的运算,在模板中放入太多的逻辑会让模板过重且难以维护
推荐改成计算属性
|
|
通过修改app.message
可以得到不同的结果
除了计算属性,还能通过methods渲染
|
|
p标签内最终呈现颠倒字符串:54321
计算属性的get和set
计算属性默认只有 getter ,不过在需要时你也可以提供一个 setter:查看在线例子
通过计算属性的setter,我们可以间接修改它所依赖的属性
|
|
【计算属性是通过别的属性计算而来的,所以,直接修改this.fullName
的值是没有用的;可以通过计算属性的setter,将它依赖的属性先修改了,从而改变计算属性】
计算属性的get和set实现全选返现功能
|
|
v-model绑定了isAll,当勾选了这个框,就会调用set
计算属性computed vs 方法methods vs 侦听器watch
计算属性有缓存:https://cn.vuejs.org/v2/guide/computed.html
计算属性是基于它们的依赖进行缓存的,只有在它的相关依赖发生改变时才会重新求值。这就意味着只要 message 还没有发生改变,多次访问 reversedMessage 计算属性会立即返回之前的计算结果,而不必再次执行函数。
而使用 methods ,每当触发渲染时,函数总会重新调用执行。
来看个具体的例子
|
|
【点击查看例子】
打开控制台,可以看到computed打印了1次,而methods打印了3次。
另外,从命名上可以看出,计算属性是一个属性,因此一般用于return一个具体的值,且在双括号中当做属性使用
而methods一般用于执行方法,当它有return时才与计算属性类似,在双括号中必须执行这个方法
计算属性的应用场景
如果是简单的处理,且最后将处理结果return出去作为属性值,推荐使用计算属性
如果data里的属性是需要依靠其他属性计算得出,就将这个属性移到计算属性里(比如sum需要用到data里的其他属性计算后得出,那么就将这个sum属性移到计算属性里)
- 求总分
- 求平均分
- 处理简单字符串
vue的计算属性,通过调用缓存的sum求出average,提高了性能
|
|
如果用methods,那么每次都会重新调用sum
计算属性 vs 侦听器
|
|
侦听属性watch
https://cn.vuejs.org/v2/api/#watch
侦听属性watch,当侦听到data里数据的变化时,执行方法
指令v-
- v-text:更新元素的 textContent
- v-html:更新元素的 innerHTML
- v-bind:动态地绑定一个或多个属性,或一个组件 prop 到表达式。
- v-on:绑定事件监听器。
- v-once:进入页面时 只渲染一次 之后即使数据变更也不再进行渲染
模板语法-指令:https://cn.vuejs.org/v2/guide/syntax.html
指令中,等号后面的冒号可以省略
v-bind:xxx="yyy"
表示:将这个元素的xxx属性和 Vue 实例data中的yyy保持一致【用于绑定class、id、等各种属性,支持js语法】v-on
:绑定用户事件函数v-model
:在表单控件上双向绑定数据v-html
:双大括号里的内容默认以text的显示呈现,想要转换成html标签想要用v-html指令
v-bind用于绑定属性
动态地绑定一个或多个特性,或一个组件 prop 到表达式。
模板语法-特性:https://cn.vuejs.org/v2/guide/syntax.html
绑定data里的imgSrc
内联字符串拼接
绑定data里的songUrl
绑定多个属性api:v-bind
|
|
<span v-bind:title="message">
将这个元素的 title 属性和data中的message保持一致
|
|
响应式修改:
ps:
使用 JavaScript 表达式
双大括号里的内容可以看成是一个JS表达式
只能包含单个表达式,判断语句请改成三元表达式
此外,支持window自身的全局变量,如 Math 和 Date
v-bind绑定样式
class与style绑定:https://cn.vuejs.org/v2/guide/class-and-style.html
菜鸟教程:样式绑定
v-bind:class绑定class
基础用法
我们可以使用三元表达式来切换样式
固定绑定class
|
|
最终结果:<div class="btn active"></div>
除了固定绑定class,我们还可以通过设置true/false来动态切换class
对象语法绑定class
我们可以传给 v-bind:class 一个对象,以动态地切换 class,key为className,value为布尔值:
|
|
最终渲染成<div class="active"></div>
通过app.isActive = false
可以动态切换
!注意
当中有横杠的class名要加单引号
|
|
最终渲染为
上面的写法过于臃肿,如果有多个class名,可以写到同一个对象中,这样就不需要一个个单独写class名了,直接写这个对象名就行了
|
|
单独添加一个class名
|
|
数组语法绑定class
|
|
|
|
最终渲染为<div class="active text-danger"></div>
三目运算
|
|
|
|
当data中的a为真值时,渲染为<div class="b d"></div>
数组和对象语法混用绑定class
|
|
|
|
最终渲染为<div class="active abc"></div>
v-bind绑定内联样式style
- 对象语法绑定style
|
|
|
|
如果有多个样式,直接绑定到一个对象通常更好,这会让模板更清晰:
|
|
各种写法
作业:
v-bind的作用,并分别写出v-bind的变量语法,数组语法,对象语法?
v-bind通常用来绑定属性的,格式是v-bind:属性名 = “值”,简写:属性名 = “值”
变量语法:v-bind:class = “变量”,变量形式 ,这里的变量的值,通常是在css定义好的类名
数组语法:v-bind:class= “[变量1,变量2]” ,数组形式,其实跟上面差不多,只不过可以同时绑定多个class名
对象语法:v-bind:class = {classname1:boolean,classname2:boolean},对象形式,这里的classname1(2)其实就是样式表中的类名,这里的boolean通常是一个变量,也可以是常量、计算属性等,这种方法也是绑定class最常用的方式。
v-on事件处理
绑定事件监听器
绑定用户事件函数
click时执行doSomething
<button v-on:click="reverseMessage">逆转消息</button>
:click时执行reverseMessage函数
|
|
PS:
Vue的data里的内容和methods里的内容都会挂载到实例对象之下,所以可以直接this.message
和this.reverseMessage()
绑定多个方法
除了绑定事件,还能绑定属性值
|
|
v-on绑定属性值
修饰符
模板语法-指令-修饰符:https://cn.vuejs.org/v2/guide/syntax.html
修饰符 (Modifiers) 是以.
指明的特殊后缀,用于指出一个指令应该以特殊方式绑定。
.prevent
修饰符用于阻止浏览器默认行为event.preventDefault().stop
修饰符用于阻止冒泡.enter
表示敲的是Enter键@keyup.enter="xxx"
事件修饰符
|
|
按键修饰符
- enter
- tab
- delete (捕获 “删除” 和 “退格” 键)
- esc
- space
- up
- down
- left
- right
- ctrl
- alt
- shift
- meta(windows键,就是那个’田’字键)
|
|
你也可直接将 KeyboardEvent.key
暴露的任意有效按键名转换为 kebab-case 来作为修饰符:
v-on多个事件
|
|
|
|
v-model表单控件双向绑定
普通html用name=’xxx’来传递数据
vue中用v-model替代name
v-model实际上是个语法糖:
|
|
v-model可用于:
- input
- textarea
- select
普通input-text
<input v-model="message">
:将输入框里的值与data里的message双向绑定
|
|
单选⊙和多选框□
一个简单的单选例子:
|
|
一个简单的多选框例子:
|
|
checkbox
在checkbox中,v-model双向绑定多选框的勾选状态
全选与取消全选:https://c.runoob.com/codedemo/3870
select
|
|
|
|
v-model的修饰符
- v-model.lazy :v-model默认实时监听数据的变化,添加lazy修饰符后,只有当blur或者按下Enter时才变更数据
- v-model.trim:去除输入框前后空格
- v-model.number
v-model.lazy
|
|
v-model,当在输入框输入内容时,实时动态更新数据
添加修饰符.lazy
之后,只有当blur或按下Enter键时才更新数据
应用场景:表单验证时,用户一个字一个字输入时,我们不需要实时验证,等到用户把内容输入完后再验证用户信息
JS Bin
v-model.trim去除前后空格
|
|
v-model.number转成数字
|
|
输入框里的内容是字符串形式,如果后期需要对输入框里的值进行加减乘除运算,需要parseInt
通过v-model.number可以简化上述操作,直接将字符串数字转成数字类型
v-html
v-html:更新元素的innerHTML
语法:<p v-html="xxx"></p>
或者自闭合 <p v-html="xxx" />
文档:模板语法-原始HTML
将data里的rawHtml以html标签的形式呈现
!!你的站点上动态渲染的任意 HTML 可能会非常危险,因为它很容易导致 XSS 攻击。请只对可信内容使用 HTML 插值,绝不要对用户在input中输入的内容使用v-html。
v-text:更新元素的 textContent
其实,双花括号就是v-text
的语法糖
条件渲染与循环渲染
v-if
:true时插入DOM,false时从DOM中删除【对比v-show,true时显示,false时隐藏】v-for
:绑定数组里的数据来渲染一个项目列表
v-if条件渲染
用于动态在DOM内添加或删除DOM元素
注意,v-if会复用已有元素,如果不想复用,需要添加唯一的key
<p v-if="true">我被插入到DOM中</p>
|
|
Vue 在插入/更新/移除元素时自动应用过渡效果
v-if搭配template标签使用
|
|
当Seen为true时,template包含的内容会被渲染出来(template标签本身不会渲染)
template只能和v-if搭配,不能和v-show搭配!
v-if,v-if-else,v-else
https://cn.vuejs.org/v2/guide/conditional.html#v-else-if
为了防止复用原有元素,需要指定唯一的key
|
|
|
|
|
|
v-for列表渲染
绑定数组里的数据来渲染一个项目列表<li v-for="todo in todos">
|
|
数组的响应式变更
数组的更改
响应式修改:
无法响应式修改:
或者用this.$set(this.arr, index, newValue)
https://cn.vuejs.org/v2/guide/list.html#%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9
v-for配合函数运算
|
|
可以通过app.foods.push({name:'辣椒',price:3,discount:.4})
进行添加
v-for数组渲染与对象渲染
|
|
v-for迭代对象
|
|
|
|
最后会将obj里的所有value渲染出来:查看在线例子
v-for迭代整数
|
|
|
|
v-cloak
由于css先加载,vue后加载,所以双括号一开始会闪现;
解决办法:添加v-cloak,然后设置css。当vue加载完成后,这个v-cloak就会自动删除
|
|
|
|
这样一来,双括号就不会闪现了
结合v-if和loading动画
v-cloak可以不显示双花括号,但是会留白,此时用v-if配合loading动画
v-cloak起到不显示双花括号的功能,v-if
在生命周期获得msg后才显示页面内容,负责显示loading
缩写(v-bind与v-on)
|
|
组件component
组件系统是 Vue 的一个重要概念,因为它是一种抽象,允许我们使用小型、独立和通常可复用的组件构建大型应用。
在一个大型应用中,有必要将整个应用程序划分为组件,以使开发更易管理。
组件用于提高代码的复用性,便于开发和维护。
组件 (Component) 是 Vue.js 最强大的功能之一。组件可以扩展 HTML 元素,封装可重用的代码。在较高层面上,组件是自定义元素,Vue.js 的编译器为它添加特殊功能。在有些情况下,组件也可以表现为用 is 特性进行了扩展的原生 HTML 元素。所有的 Vue 组件同时也都是 Vue 的实例,所以可接受相同的选项对象 (除了一些根级特有的选项) 并提供相同的生命周期钩子。
组件的注册(组件的作用域)
全局组件
将组件的template写到html里,然后在组件里传选择器
局部组件
父子组件通信
父组件将数据传给子组件的props
子组件无法直接修改父组件的数据,必须通过$emit()托付父组件,让父组件帮忙修改父组件的数据
|
|
|
|
组件绑定原生事件
在 Vue 2.0 中,为自定义组件绑定原生事件必须使用 .native
修饰符:
.sync 修饰符
在有些情况下,我们可能需要对一个 prop 进行“双向绑定”,使子组件的prop修改时,父组件的data也跟着改变。为了方便起见,我们为这种模式提供一个缩写,即 .sync
修饰符,其实它是v-on:update
的语法糖
|
|
上面的代码用.sync
语法糖改写如下:
动态组件
https://cn.vuejs.org/v2/guide/components.html#%E5%8A%A8%E6%80%81%E7%BB%84%E4%BB%B6
Vue内置了一个component
标签,依:is="组件名"
的值,来决定哪个组件被渲染。
在动态组件上使用 keep-alive
https://cn.vuejs.org/v2/guide/components-dynamic-async.html#%E5%9C%A8%E5%8A%A8%E6%80%81%E7%BB%84%E4%BB%B6%E4%B8%8A%E4%BD%BF%E7%94%A8-keep-alive
异步组件(按需加载,懒加载)
如果一开始打开页面加载所有的组件,加载起来比较耗时,我们可以把一些组件定义为异步组件,在需要使用的时候再加载。
优点:
- 按需加载,可以节省首次加载的时间,提高页面打开的速度
- 第一次按需加载完成之后,会被缓存下来,再次使用这个组件时就不会重复加载了
默认情况下,webpack会把所有组件打包在一个js文件里,导致js文件过大;异步组件可以打包成独立的js文件,并且只有在这个组件需要被渲染的时候(比如 v-if 触发渲染)才会触发
|
|
解析 DOM 模板时的注意事项
有些 HTML 元素,诸如 ul、ol、table 和 select,对于哪些元素可以出现在其内部是有严格限制的。而有些元素,诸如 li、tr 和 option,只能出现在其它某些特定的元素内部。
如果想让这个组件插入ul的内部,就要使用is
属性
过滤器
|
|
文档:【过滤器】
语法:
默认第一个参数value是管道符前面的值,剩下的参数是人为传入的其他参数
过滤器一般用于处理文本的格式化,比如将data里的name变成大写,将data里的长度变成米,将data里的价格后面添上“元”等。又比如,过滤出todoLists里的所有、已完成、未完成 过滤器不会修改data里的值,只用于将data里的值格式化后渲染出来。
过滤器由“管道”符号|
表示:
Vue.filter(‘过滤器名称’, (管道前面的值,自定义传的值)={});
除了全局过滤器,还可以用局部过滤器
- 除了双括号里可以用过滤器外,v-bind也可以
|
|
简单的数据格式化可以用filter,如果是复杂的数据格式化推荐用计算属性,因为计算属性本身带有缓存。
自定义指令
自定义指令用于对普通 DOM 元素的复杂操作进行封装(比如元素的拖拽)。
文档:【自定义指令】
全局指令
|
|
|
|
局部指令
除了全局指令,我们也可以注册局部指令
一个最简单的例子:
|
|
另一个例子:
一个最简单的例子:
当todoList的长度大于0时,才触发指令
对象字面量
如果指令需要多个值,可以传入一个 JavaScript 对象字面量。记住,指令函数能够接受所有合法的 JavaScript 表达式。
|
|
钩子函数
- bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
- inserted:被绑定元素插入父节点时调用(父节点存在即可调用,不必存在于 document 中)
- update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。
- componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。
- unbind:只调用一次,指令与元素解绑时调用。
钩子函数参数
|
|
|
|
自定义指令实现拖拽
mixins混入(复用)
将new Vue({options})
里的options提取出来,从而使相同option得到复用
混入 (mixins) 是一种分发 Vue 组件中可复用功能的非常灵活的方式。
文档:【混入】
|
|
|
|
!注意:当混入的数据和组件原有的数据重名时,以组件数据优先。
插件
在utils文件夹下,新建util.js
然后在main.js中使用它:
组件插槽
插槽用于内容的分发。 将 <slot>
元素作为承载分发内容的出口。
文档:【插槽】
单个插槽
一个最简单的例子:
|
|
当组件渲染的时候,这个 slot
标签将会被替换为<h3>自定义内容</h3>
。
最终渲染成:
多个插槽,取个名字
有些时候我们需要多个插槽,这时可以给这些slot取个名字
|
|
作用域插槽
用途:从子组件的slot
中获取数据
通过slot-scope="slotProps"
获取子组件的数据
访问插槽
通过this.$slots.插槽名[0]
来访问插槽
ref注册引用
api:refref
被用来给元素或子组件注册引用信息。引用信息将会注册在父组件的 $refs
对象上。如果在普通的 DOM 元素上使用,ref
指向的就是 DOM 元素;如果用在子组件上,ref
就指向组件实例:
|
|
【点击查看例子】
注册单个元素时,相当于querySelector()
在v-for中要有下标[0],因为$refs是个数组
|
|
注册多个元素时,相当于querySelectorAll()
过渡&动画
在下列情形中,可以添加transition组件
- v-show
- v-if
- 动态组件
- 组件根节点
|
|
|
|
vue的响应式更改
数组的更新
由于 JavaScript 的限制,Vue 不能检测以下变动的数组:
- 当你利用索引直接设置一个项时,例如:this.items[index] = newValue
- 当你修改数组的长度时,例如:this.items.length = newLength
|
|
为了解决第一类问题,可以用以下两种方式,达到响应式更改
为了解决第二类问题,你可以使用 splice:
对象的更新
还是由于 JavaScript 的限制,Vue 不能检测对象属性的添加或删除:
可以使用 Vue.set(obj, key, value)来解决这个问题
另外,你也可以使用Object.assign,但是要注意
VUE的练习题
|
|
|
|
答案:
补充
Vue的data里的内容和methods里的内容都会挂载到实例对象之下,所以可以直接
this.message
和this.reverseMessage()
computed 对象内的方法如果在初始化时绑定到元素上的事件会先执行一次这个方法 ,而 methods 内的方法则不会;
|
|
|
|
进入页面时会自动执行computed里的方法
设置图片的默认值
通过表达式||
,当imgUrl为假值时,显示默认图片
vue中引入图片
在html中
这种方式是按照正常HTML语法引用路径
在js中
接着就可以在html里绑定 <img :src="avatar" />
通过require引入图片
|
|
通过require可以实现动态设置图片
踩坑
methods的方法名不能叫do
|
|
|
|
方法名叫do
会报错
methods的方法名不能叫delete
|
|
方法名叫delete
会报错
初始值为null时
如果数据的初始值是null
上述代码不加key,那么在input输入内容后,切换另一个input会被复用
添加上唯一的key,可解决该问题
数组与对象的更新
数组的更新
|
|
对象的更新
在遍历对象时,是按 Object.keys() 的结果遍历,因此obj格式的数据可能在不同的 JavaScript 引擎下渲染出来的顺序不一致。
对象的更新方法: