目录
1 vue介绍
Vue渐进式框架:
- 可以将vue作为应用的一部分嵌入,带来更丰富的交互
- Core+Vue-router+Vuex:全家桶1
vue特点:
- 解耦数据和视图
- 可复用组件
- 前端路由
- 状态管理
- 虚拟DOM
vue.js自底向上逐层应用 ,只关心视图层(HTML+CSS+JS)直观展示,其他交给第三方:
- 网络通信Axios
- 页面跳转:vue-router
- 状态管理:vuex
- UI:ice.work elementUI AmazeUI iview
- MV*模式
MVC:同步通信为主:Model View Controller
MVP:异步通信为主:Model View Presenter
MVVM:异步通信为主:Model View ViewModel
- 构建工具:
Babel:JS编译工具,主要用于浏览器不支持的ES新特性,比如编译TypeScrip
Webpack:模块化打包,主要是打包、压缩、合并和按需加载
SOC原则:关注点分离原则
vue特点:引入计算属性
vue-element-admin:一个后台的前端解决方案
VUE的分层:
Model层:表示JS对象
VIew层:表示HTML
ViewModel:连接视图和模型的中间件,Vue.js就是MVVM的ViewModel实现者
注意:在MVVM架构中,不允许模型和视图直接通信,只能通过VIewModel来通信,而ViewModel就是定义了一个Observer,他能监听视图变化并通知数据发生改变;他能监听数据变化,并通知视图进行更新
VUE优点:体积小,生产版本:20kb,相比Augular56kb和React44kb,适配移动端好,易上手,文档全,集合Aungualr模块化和React虚拟DOM长处,且有自己的优点:计算属性并且开源
1.1 安装
有三种方式:
- cdn引入
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- 生产环境版本,优化了尺寸和速度 -->
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
- 下载引入
- npm安装(webpack和cli使用)
注意:不推荐新手直接使用vue-cli
1.2 简单使用
这里选择下载vue.js文件来引入,引入方式和引入其他js文件一样,放在script标签的src中,注意如果将vue其他代码放到了别的js中,在index入口必须先加载vue的框架,将其他的js放在后面加载!
es6:let和const
let为普通变量,可以重复赋值
const为常量,只能赋值一次
尽量不要使用var
Vue编程方式为声明式:使用声明式开发有利于数据和代码进行分离,数据改变页面自动重新渲染
如:在控制台中输入:app.message="123"
则页面显示也被改变,这也称为响应式
案例:声明式渲染{{}}
<!DOCTYPE html>
<html lang="en">
<head>
<script src="../js/vue.js"></script>
<title>Document</title>
</head>
<body>
<div id="app">{{message}}</div>
</body>
<script>
const app = new Vue({
el:"#app",
data:{
message:"abc"
}
})
</script>
</html>
案例:加减计数器(属性绑定v-bind
和事件v-on
)
<!DOCTYPE html>
<html lang="en">
<head>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
<h2 v-bind:title="message">当前计数:{{counter}}</h2>
<button v-on:click="add">+</button>
<button v-on:click="sub">-</button>
</div>
</body>
<script>
const app = new Vue({
el:"#app",
data:{
message:"123",
counter:0
},
methods:{
add: function(){
this.counter++
},
sub: function(){
this.counter--
}
}
})
</script>
</html>
注意:v-on:click
可以简写为@click
注意:v-
开头的称为指令,是Vue提供的特殊属性
案例:条件表达式v-if
<div id="app-3">
<p v-if="seen">现在你看到我了</p>
</div>
<script>
var app3 = new Vue({
el: '#app-3',
data: {
seen: true
}
})
</script>
案例:循环表达式
<div id="app-4">
<ol>
<li v-for="todo in todos">
{{ todo.text }}
</li>
</ol>
</div>
<script>
var app4 = new Vue({
el: '#app-4',
data: {
todos: [
{ text: '学习 JavaScript' },
{ text: '学习 Vue' },
{ text: '整个牛项目' }
]
}
})
</script>
注意:app4.todos.push({ text: '新项目' })
可以动态增加列表项目
this.message = this.message.split(‘’).reverse().join(‘’)
可以将字符串反转
案例:组件化开发
<div id="app-7">
<ol>
<!--
现在我们为每个 todo-item 提供 todo 对象
todo 对象是变量,即其内容可以是动态的。
我们也需要为每个组件提供一个“key”,稍后再
作详细解释。
-->
<todo-item
v-for="item in groceryList"
v-bind:todo="item"
v-bind:key="item.id"
></todo-item>
</ol>
</div>
<script>
Vue.component('todo-item', {
props: ['todo'],
template: '<li>{{ todo.text }}</li>'
})
var app7 = new Vue({
el: '#app-7',
data: {
groceryList: [
{ id: 0, text: '蔬菜' },
{ id: 1, text: '奶酪' },
{ id: 2, text: '随便其它什么人吃的东西' }
]
}
})
</script>
1.3 MVVM
分析M V VM
view层:el指定的模板(就是html)
model层:app里的js数据,一般是data属性
viewmodel层:即app对象,监听数据,且双向绑定,改变app里的数据,页面同时会改变(Proxy原理)
1.4 option之生命周期钩子
在new一个Vue对象时,需要传递一个option对象,该对象有很多属性可以定义
vue八大对象:
- el 指示浏览器从哪里开始解析vue语法,可以是字符串或者html节点
- data 数据,可以是对象或者函数(组件中data必须是函数)
- methods(函数必须写在这里面)放置业务逻辑,js方法放在这里面,是键值对的回调方法集合
- template 设置模板,会替换页面元素,包括占位符
- render 虚拟dom
- computed 计算属性
- watch 监听data数据变换:watch:function(new,old){}
- 生命周期钩子
1.4.1 生命周期钩子
有个知识点:outerHTML指包括root标签的html节点,innerHTML值root标签里的html节点
<div id="root">
<h2>{{n}}</h2>
</div>
- beforeMount:页面呈现的是未经编译的DOM结构,所有对DOM的操作不奏效
- mounted:挂载完成,可以操作DOM,发送网络请求,开定时器等
如果写template字段,则会用该字段编译后的节点整个替换root标签节点(root节点没了),如果不写,则会使用el指定的标签作为根节点去解析(root节点存在)
注意:生命周期中的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 基本语法
模板语法:
- 插值语法:在标签体之间用
{{}}
包裹来插入JS的表达式:<div>{{time}}</div>
,只能接受表达式! - 指令语法:在标签内部属性前加上指令来声明标签表现形式,使用
""
包裹JS语句:<div v-bind:a="time">abc</div>
,注意:其中用到的变量或者函数都必须是vue实例中有的,如果没有就会报错(如直接调用window.alert就会报错)
2.1 引入变量 v-bind v-html
- 引入变量 v-bind:模板标签中,标签属性使用
v-bind:属性="属性变量"
来引入,"属性变量"
会自动被解析(可以解析简单的表达式:<div v-bind:id="'list-' + id"></div>
),如果在数据模型中没有找到这个变量则该属性不会被渲染;
标签之间的使用{{属性变量}}
来引入,在{{}}
中可以写js语法
特殊的: 使用v-bind=对象
来传递一个对象给组件:v-bind=$attrs
(将当前父组件传递过来的所有变量:$attrs
中记录了当前组件被绑定的所有属性,原封不动传递给子组件)
v-bind:xxx.sync=“a”
绑定变量时可以有一个.sync
修饰符,是一个语法糖,含义为监听内部的@update:xxx
的方法(即监听内部对xxx属性的更新调用,this.$emit('update:xxx',100)
,并将其值赋值给外部的a
变量
即::xxx.sync="a"
等价于:@update:xxx="value=>a=value"
如果使用v-model去绑定,则只能绑定value,因为默认绑定的是内部的value和input事件
即:value.sync="a"
等价于:@update:value="value=>a=value"
等价于v-model="a"
- 引入原始HTML v-html:使用指令:
v-html
,该指令的值为原始HTML
<p>Using mustaches: {{ rawHtml }}</p>
<p>Using v-html directive: <span v-html="rawHtml"></span></p>
其中:rawHtml
变量的值为:<p style="color:red">123</p>
会解析HTML显示
注意:切勿对用户提供的内容使用该指令,容易导致XSS攻击
2.2 指令
指令有很多种:
- 逻辑指令:其中包括:判断、选择、循环
- 事件指令:
v-on
- 绑定指令:
v-bind
v-model
(涉及到表单,内容单独列出来) - 其他
判断指令通常用于切换渲染组件,需要注意的是组件的key。当组件没有key
时,默认会在多种状态切换时如果有可复用的(相同元素)会直接复用!导致之前的输入遗留等(这也是优点,渲染高效)。
案例:输入遗留
<template v-if="loginType === 'username'">
<label>Username</label>
<input placeholder="Enter your username">
</template>
<template v-else>
<label>Email</label>
<input placeholder="Enter your email address">
</template>
在切换时会发现input中输入的值出现了遗留,如果想要切换时进行清空数据,则必须手动赋予组件key
,表示唯一。
案例:
<template v-if="loginType === 'username'">
<label>Username</label>
<input placeholder="Enter your username" key="username-input">
</template>
<template v-else>
<label>Email</label>
<input placeholder="Enter your email address" key="email-input">
</template>
2.2.1 流程指令 v-if
v-if
v-else-if
v-else
,常用于条件渲染,只有表达式为true时渲染该内容,false时不渲染
<h1 v-if="type=='A'">A</h1>
<h1 v-else>Oh no 😢</h1>
注意:可以使用<template>
来包裹多个标签,该模板标签实际并不渲染
2.2.2 显示指令 v-show
v-show
:一定渲染该标签,但是根据值决定是否显示标签(控制display)
注意:v-show
不支持 <template>
元素,也不支持 v-else
。
<h1 v-show="ok">Hello!</h1>
v-if还是v-show取决于切换频率,如果高切换频率,选择v-show,不用重复渲染,低切换频率选择v-if,节省时间
v-if和v-for一起使用时,v-for优先级更高。v-if会作用在v-for将要渲染的项上,不推荐
<!--只渲染未完成的 todo--> <li v-for="todo in todos" v-if="!todo.isComplete"> {{ todo }} </li>
2.2.3 循环指令 v-for
v-for
,遍历器,其中in可以使用of代替,建议渲染的对象加上key,便于复用提升性能,key不要绑定为索引
<div id="app">
<!--遍历数组-->
<li v-for="item in items">
{{item.message}}
</li>
<li v-for="(item,index) in items">
{{item.message}}---{{index}}
</li>
<!--遍历对象-->
<li v-for="value in object">
{{ value }}
</li>
<li v-for="(value, key) in object">
{{ key }} : {{ value }}
</li>
<li v-for="(value, key, index) in object">
{{ key }} : {{ value }}
</li>
</div>
<script>
var vm = new Vue({
el:'#app',
data:{
items:[
{message:"abc"},
{message:"aaa"},
{message:"ooo"}
],
object: {
title: 'How to do lists in Vue',
author: 'Jane Doe',
publishedAt: '2016-04-10'
}
}
})
</script>
注意:for循环渲染时,如果被渲染数据顺序改变则默认策略为就地更新属性的值!!这种情况虽然比移动DOM效率高,但是如果每个循环项有自己的状态,会导致状态错误或者丢失!
解决方案:使用v-bind:key
来绑定唯一key
属性,该属性建议使用字符串或者数值来标识。
特殊的:v-for
可以接受整数,会重复整数次,从1开始
<span v-for="n in 10">{{ n }} </span>
<!--输出结果:1 2 3 4 5 6 7 8 9 10-->
2.2.4 事件指令 v-on
v-on
绑定事件,事件肯定是需要触发一个函数,而函数如果不带参数的话,可以不加括号,此时默认参数为事件对象
,如果带参数则需要加括号,且事件参数需要显式传递:$event
<!--打印:event对象 undefiend-->
<div @click="run">123</div>
<!--打印:1 undefiend-->
<div @click="run(1)">123</div>
<!--打印:1 event对象-->
<div @click="run(1,$event)">123</div>
<script>
var vm = new Vue({
el:'#app',
data:{},
methods:{
run: function(x,e){console.log(this.x,e)}
}
})
</script>
其他案例:
<div id="app">
<li v-on:click="say">
点击这里
</li>
<button v-on:click="counter += 1">Add 1</button>
<p>The button above has been clicked {{ counter }} times.</p>
</div>
<script>
var vm = new Vue({
el:'#app',
data:{message:"abc",counter:0},
methods:{
say: function(msg){alert(this.message+msg)}
}
})
</script>
注意:可以在命令值字符串中写简单的表达式
可以在事件绑定中传递参数:v-on:click="say('hi')"
,可以在函数中传递接收一个$event
的参数,代表原始的DOM事件
特殊的: 可以使用:v-on=$listeners
,将父组件绑定给当前组件的所有事件对象:$listeners
,传递给子组件,$listeners
存了当前组件被绑定的所有事件
2.2.5 指令的动态参数
指令后有些可以带参数:v-bind:title
如果写死了则不灵活,可以使用动态参数来获取参数:v-bind:[变量]
<!--如果attributeName的值为"href",则该指令相当于v-bind:href-->
<a v-bind:[attributeName]="url"> ... </a>
注意:动态参数会解析成变量,最终获取到一个字符串,任何不为字符串的都会出发警告,如果为null则会移除该属性。
注意:动态指令参数中不能有空格或者引号,如果要做复杂计算,可以使用计算属性代替,且不能使用大写字母,因为会被转换成小写。
2.2.6 事件修饰符
修饰符是告知指令执行的一些特殊方式,如.prevent
修饰符告诉 v-on
指令对于触发的事件调用 event.preventDefault()
:如<form v-on:submit.prevent="onSubmit">...</form>
v-on
事件修饰符有:.stop|.prevent|.captrue|.self|.once|.passive|.native
<!-- 阻止单击事件继续传播 -->
<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>
<!-- 点击事件将只会触发一次 -->
<a v-on:click.once="doThis"></a>
<!-- 滚动事件的默认行为 (即滚动行为) 将会立即触发,常用于移动端,优先响应滚动 -->
<!-- 而不会等待 `onScroll` 完成 -->
<!-- 这其中包含 `event.preventDefault()` 的情况 -->
<div v-on:scroll.passive="onScroll">...</div>
<!--一般用于自定义组件上,调用根元素的原生方法,而不是自定义属性-->
<abc @click.native="xxx"></abc>
事件修饰符书写顺序很重要!按照逻辑来
注意:这个 .passive
修饰符尤其能够提升移动端的性能,但是不要把 .passive 和 .prevent 一起使用,因为 .prevent 将会被忽略,同时浏览器可能会向你展示一个警告。请记住,.passive 会告诉浏览器你不想阻止事件的默认行为。
键盘事件:@keyup
或者@keydown
,键修饰符:enter
等等,可以用于监听特定按键的键盘事件:@keyup.enter
监听回车键并回调
对于vue没有提供的按键,可以通过event.key的名字来使用,如
@keyup.Enter
同样可以
特别注意:对于两个单词拼起来的键名需要转换成小写用-链接:@keyup.caps-lock
特别注意:tab键由于本身功能会切换焦点,所以必须绑定回调在@keydown.tab
中!!
对于系统修饰键:ctr alt shift meta
:
配合keyup使用:按下修饰键再按其他键,释放其他键时才会触发事件,常用组合:@keyup.ctrl.a
标识ctrl+a按下后才触发
配合keydown使用:正常触发
2.2.7 指令缩写
对于常用的指令来说,使用缩写能加快开发速度,目前v-bind
和v-on
提供了缩写
- v-bind
<!-- 完整语法 -->
<a v-bind:href="url">...</a>
<!-- 缩写 -->
<a :href="url">...</a>
<!-- 动态参数的缩写 (2.6.0+) -->
<a :[key]="url"> ... </a>
- v-on
<!-- 完整语法 -->
<a v-on:click="doSomething">...</a>
<!-- 缩写 -->
<a @click="doSomething">...</a>
<!-- 动态参数的缩写 (2.6.0+) -->
<a @[event]="doSomething"> ... </a>
2.2.8 v-once
一次性响应指令,只会渲染一次,改变数据后不会再次渲染
<div v-once>{{message}}</div>
2.2.9 v-html
将vue数据中的变量从字符串解析成html格式,永远不要在用户提交的地方使用该指令(XSS攻击)
<div v-html="url"></div>
<!-- url:<a href="http://www.baidu.com">baidu</a> -->
2.2.10 v-text
向其所在的标签中,渲染文本内容,其值当作文本插入到节点文本属性中,不做解析(可防止注入攻击)
<!--渲染结果就是msg变量代表的值,12345被替换了-->
<div v-text="msg">12345</div>
2.2.11 v-pre
跳过解析,直接输出,对于不需要解析的节点建议加上,可以加快编译速度
2.2.12 v-cloak
该属性作用是:在vue解析前存在,在vue解析后删除(Vue会删除标签中的该属性,解析前该属性作为正常html属性使用)。这样可以控制解析前的行为或者样式。如:使用选择器选择有该属性的标签,将其显示样式设置为none,当vue解析完成后,就可以正常显示
<div v-cloak>{{ message }}</div>
<style>[v-cloak] {display: none;}</style>
2.2.13 v-bind
使用v-bind可以动态绑定标签中的属性值!非常常用。注意:在标签属性中不能使用{{}}
语法,且所有字符串会被认为是普通字符串,要想解析变量只能使用v-bind
来动态赋值
2.2.14 自定义指令
模板中指令名称以v-
开头,定义时无需
格式:
// 简写
directives:{
abc(element,binding){
// 此处element为真实dom,bingding为指令相关信息,操作真实dom即可改变渲染结果
}
}
// 全写
directives:{
abc:{
bind(){
// 指令与元素成功绑定后调用,适用于元素值的操作
},
inserted(){
// 元素被插入到页面后调用,适用于有关DOM结构的操作,比如获取父元素,获取焦点等
},
update(){
// 指令所在模板重新解析时调用
}
}
}
调用时机(简写形式):
- 指令与元素建立关系成功后,渲染到页面上前,会调用
- 指令所在的模板被重新解析时(每次重新渲染)
一些坑:
- 指令名不要大写(html中不区分大小写),可以使用连字符,不过定义指令时需要加引号
- 指令内部的this指向是window
定义全局指令:
Vue.directive('abc',{
bind(){},
inserted(){},
update(){}
})
// 简写
Vue.directive('abc',function(){})
2.3 计算属性
为了简化模板中的语法,减少逻辑部分而只负责展示,所以引入计算属性,对于任何复杂逻辑,都因该使用计算属性,且存在缓存,效率比较高
计算属性计算时机:
- 第一次读取时计算
- 依赖的数据发生改变时计算(当在一个函数内依赖的多个属性被改变了,也只会计算一次,因为JS是串行执行的)
注意:依赖的数据必须要备VUE管理才行
<div id="example">
<p>逻辑放在模板中: "{{ message.split('').reverse().join('') }}"</p>
<p>逻辑放在计算中: "{{ reversedMessage }}"</p>
</div>
<script>
var vm = new Vue({
el: '#example',
data: {
message: 'Hello'
},
computed: {
// 计算属性的 getter
reversedMessage: function () {
// `this` 指向 vm 实例
return this.message.split('').reverse().join('')
},
x(){console.log(123)}
}
})
</script>
计算属性最大的优点是存在缓存!!即计算一遍,后面用到的地方可以直接使用不会再计算。除去该优点,其实所有的计算属性都可以使用函数来代替。
计算属性VS函数:当计算属性依赖的属性没有变化时,计算属性不会更新,这样获取速度更快,而如果是函数,则每次获取都会更新。
计算属性VS侦听属性:计算属性是一系列逻辑运算的结果,只要涉及的相关属性没有发生改变,则计算属性不会变,只需要定义一次,而侦听需要达到同样的结果需要对涉及的每个属性进行侦听定义,比较繁琐。同时计算属性依赖于返回值,即返回值必须是一个值!(类似于map和forEach)
计算属性的setter:计算属性也可以有setter,它显式的传入一个参数(计算值),然后根据该值可以自定义相关属性值
// 完整的计算属性定义
computed: {
fullName: {
// getter
get: function () {
return this.firstName + ' ' + this.lastName
},
// setter
set: function (newValue) {
var names = newValue.split(' ')
this.firstName = names[0]
this.lastName = names[names.length - 1]
}
}
}
2.4 侦听器
使用watch
来定义,当需要在数据变化时执行异步操作或者大开销操作时比较实用,可以监测data中的值和computed值
// html代码: <input v-model="question">
watch: {
// 如果 `question` 发生改变,这个函数就会运行
question: function (newQuestion, oldQuestion) {
this.answer = 'Waiting for you to stop typing...'
this.debouncedGetAnswer()
},
x(nv,ov){} //也可以这样简写,监视x属性变化,函数名和属性名相同
},
注意:这里使用到了v-mode
,该指令用于表单数据的双向数据绑定,相当于在vue实例的data中添加了该属性,无论是vue中的数据变化还是ui控件中该值变化都会触发进行同步
watch属性配置对象:
// 方法一
watch:{
x:{
immediate:true, // 表示初始渲染页面时是否更新,默认false
handler(newValue,oldValue){} // 观测值变化时调用该函数
}
}
// 方法二
vm.$watch('x',{
immediate:true, // 表示初始渲染页面时是否更新,默认false
handler(newValue,oldValue){} // 观测值变化时调用该函数
})
vm.$watch('x',function(newValue,oldValue){}) // 简写
当输入频繁时,希望停止输入一段时间才调用函数,即限定函数访问频率,可以使用debounce方法!
/** * 空闲控制 返回函数连续调用时,空闲时间必须大于或等于 idle,action 才会执行 * @param fn {Function} 相关执行函数 * @param delay {Number} 延迟时间,也就是阈值,单位是毫秒 * @return {function} 返回一个“去弹跳”了的函数 */ debounce(fn,delay) // 相关参考:https://www.cnblogs.com/songyz/p/10310491.html
对于debounce的实现,Lodash库有现成方法:_.debounce
是一个通过 Lodash 限制操作频率的函数。 this.debouncedGetAnswer = _.debounce(this.getAnswer, 500)
2.4.1 数组更新检测
vue对数被侦听的数组的方法(只有方法,不包括方法外的改变,如直接拿到下表赋值)进行了包裹(Vue3中使用代理,更加全面,包括直接操作索引设置值也能检测到)
包括新增元素、切片、排序、反转(push|pop|shift|unshift|splice|sort|reverse)——原数组被改变(不包括filter,因为不影响原数组)
还有一部分原数组不变而返回新数组(filter|concat|slice),需要自己手动完成新旧数组替换。(有时不需要改变原数组但是要显示新数组,可以使用计算属性!)
注意:这种替换操作非常高效,会复用DOM
Vue.set(对象,索引,值)
这种方式也能响应式修改
2.4.2 深度侦听(监视)
对于多级数据:x:{y:{z:{m:10}}}
,如果想侦听其中的y的数据变化,写法:'x.y':{handler(nv,ov){}}
,注意要还原成字符串格式
对于引用类型数据进行侦听,侦听的是引用数据的地址值,无法监听其中数据变化,可以开启深度属性:deep:true
data:{
x:{
a:1,
b:2
}
},
watch:{
x:{
deep:true, // 此时无论x中a和b变化都会调用handler
handler(){}
}
}
2.5 样式类
样式分为class样式和内联style样式
在自定义组件上使用该样式语法,会作用在模板的根标签上
class样式语法:顾名思义,专门给css样式类class使用的语法,主要用于动态切换class,对class的绑定:v-bind:class
内联样式语法:专门用来为对象的style使用的语法
2.5.1 class对象语法
对象语法格式:{key:value}
,value是一个变量,该变量为bool值,指示key是否存在,key为class
该语法和普通class可以并存,最终结果会合并
<div v-bind:class="{ active: isActive }"></div>
<div
class="static"
v-bind:class="{ active: isActive, 'text-danger': hasError }"
></div>
如果isActive值为true,hasError值为false,则相当于<div class="static active"></div>
注意:绑定的数据对象也可以写在data中!或者使用计算属性获得结果
2.5.2 class数组语法
格式为:"[activeClass, errorClass]"
,数组中的值为变量,变量的值为class
特殊的:数组中可以使用三元表达式:<div v-bind:class="[isActive ? activeClass : '', errorClass]"></div>
,且可以和对象语法混用:<div v-bind:class="[{ active: isActive }, errorClass]"></div>
2.5.3 style对象语法
对象语法格式:v-bind:style
,绑定的是一个js对象,可以使用驼峰或者中横线分割命名(如果使用-命名,key要加引号)
<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
data: {
activeColor: 'red',
fontSize: 30
}
// 也可以直接绑定一个样式对象:
// <div v-bind:style="styleObject"></div>
data: {
styleObject: {
color: 'red',
fontSize: '13px'
}
}
// 也可以结合计算属性
对象语法中也可以使用数组,表示多重值!通常用来提供多个带前缀的值,只会渲染其中支持的一个
<div :style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }"></div>
2.5.4 style数组语法
与class的数组语法相似:<div v-bind:style="[baseStyles, overridingStyles]"></div>
注意:当 v-bind:style 使用需要添加浏览器引擎前缀的 CSS property 时,如 transform,Vue.js 会自动侦测并添加相应的前缀。
2.6 表单输入绑定(v-model)
v-model
指令用于表单输入元素的双向绑定,会忽略表单的默认值或者选定属性,全部从vue实例中读取!
内部使用:
text/textarea:value值、input事件
checkbox/radio:checked值、change事件
select:将value作为prop传给change
注意:输入法组合文字时不会触发更新,如果需要,可以使用input事件
v-model和sync修饰符,都可用于双向绑定,但是也有区别:https://zhuanlan.zhihu.com/p/338392152
原理:v-model相当于两个指令的组合:v-bind + 变更事件(input)
<input type="text" v-model="message">
<input type="text" :value="message" @input="message = $event.target.value">
案例:
<!--单行输入-->
<input v-model="message" placeholder="edit me">
<p>Message is: {{ message }}</p>
<!--注意:多行文本的输入值不在标签之间,而在标签属性中了-->
<textarea v-model="message" placeholder="add multiple lines"></textarea>
<p style="white-space: pre-line;">{{ message }}</p>
<!--复选框,绑定到单个数值,值为true/false-->
<input type="checkbox" id="checkbox" v-model="checked"><label for="checkbox">{{ checked }}</label>
<!--复选框,绑定到数组,值为value-->
<input type="checkbox" id="jack" value="Jack" v-model="checkedNames"><label for="jack">Jack</label>
<input type="checkbox" id="john" value="John" v-model="checkedNames"><label for="john">John</label>
<input type="checkbox" id="mike" value="Mike" v-model="checkedNames"><label for="mike">Mike</label>
<br>
<span>Checked names: {{ checkedNames }}</span>
<!--单选框,绑定到同一个值即可放入同组中,值为Value-->
<input type="radio" id="one" value="One" v-model="picked"> <label for="one">One</label>
<br>
<input type="radio" id="two" value="Two" v-model="picked"> <label for="two">Two</label>
<br>
<span>Picked: {{ picked }}</span>
<!--下拉框,单选绑定数值,值为option中的内容,IOSBUG:初始值没匹配任何选项,默认第一个选项无法选中,可以人为让第一个选项为禁用以此来规避-->
<select v-model="selected">
<option disabled value="">请选择</option>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
<span>Selected: {{ selected }}</span>
<!--下拉框,多选绑定数组,值为option中内容,多选框不存在BUG-->
<select v-model="selected" multiple style="width: 50px;">
<option>A</option>
<option>B</option>
<option>C</option>
</select>
2.6.1 值绑定
以上表单组件在使用时,有些组件需要配合value
属性,如单选框、复选框,而select
组件也可以配合value
(默认是option
标签中的值),复选框在只有绑定单值时可以不用value
,默认是true/false
特殊的有两个组件:复选框和下拉列表
复选框存在属性:true-value/false-value
,下拉列表的option
的value
可以接收对象
<!--当选中时为yes,没有选中为no-->
<input
type="checkbox"
v-model="toggle"
true-value="yes"
false-value="no"
>
2.6.2 表单修饰符
.lazy
:将表单的数据绑定从input事件转换成change事件( input输入框的onchange事件,要在 input 失去焦点和回车的时候才会触发)
<input v-model.lazy="msg">
.number
:强制输入转换成数字,注意:代码取值时也是数字,和type=number这点不同(获取到的是string),如果无法解析则返回原始值(这点没测出来)
<input v-model.number="age" type="number">
.trim
:去除首尾的空白字符
<input v-model.trim="msg">
2.7 过滤器 filters(vue3已经废弃)
过滤器其实就是一个函数,只是使用方法更为直观,只能用在两个地方:插值语法、v-bind中
,用于简单处理数据!
定义一个过滤器:
// 在vue中和data同级别
filters: {
abc(x){return x+"---"}
}
调用过滤器也很简单,只要在数据后加|
即可,会将前面的数据传递给相应过滤器
// 此时abc只会收到一个参数param
{{param | abc}}
// 传参,此时func会收到两个参数value1和value2
{{value1 | func(value2)}}
// 过滤器可以串联,前一个过滤器的结果会传递给后者
{{value1 | func1 | func2}}
全局过滤器:定义在vue实例内部的filter字段中的为局部
过滤器,只有当前实例可以使用,而在创建实例前使用Vue.filter(过滤器名,函数)
方式定义的为全局过滤器,全局可用
Vue.filter("f1",function(){})