Vue的概述
渐进式JavaScript框架
前端三大框架(React,Vue,Angular)
vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。
简单,高效,生态丰富(插件多)
Vue的安装与使用
安装
1.直接引用
CDN
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
下载地址
https://v2.cn.vuejs.org/v2/guide/installation.html
2.安装脚手架
npm install -g @vue/cli
使用
new Vue 函数创建一个新的应用实例
new Vue({
el:"#box",//指定vue的模板css选择器
data:{msg:"你好"}// 指定data数据
})
模板指定
<div id="box">
<h1>{{msg}}</h1>
</div>
完整代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="box">
<h1>{{msg}}</h1>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>//vue的cdn
<script>
new Vue({
el: "#box",//指定vue的模板css选择器
data: {
msg: '你好'//指定data数据
},
})
</script>
</body>
</html>
Vue模板语法-文本渲染
模板语法介绍
指令 是带有 v- 前缀的特殊 attribute。指令 的属性值预期是单个 JavaScript 表达式
文本渲染-{{}}
{{ }} 语法
<h1>{{msg}}</h1>
new Vue({
el:"#box",//指定vue的模板css选择器
data:{msg:"你好"}// 指定data数据
})
{{ }} 中的表达式
对于所有的数据绑定,Vue.js 都提供了完全的 JavaScript 表达式支持。
{{ 1+1 }}//2
{{2+3>8?'大于':'小于'}}//小于
{{ msg.split('').reverse().join('') }}//好你
// 01渲染Vue的数据
// 02数学运算
// 03执行js的普通方法split分割, reverse反转数组
// join连接数组
// 04三元运算(不能使用if, for等多行命令)
v-text指令
指令是带有 v- 前缀的特殊属性。
<h1 v-text="msg">{{msg}}</h1>//你好
new Vue({
el:"#box",//指定vue的模板css选择器
data:{msg:"你好"}// 指定data数据
})
v-html指令
输出真正的html
<h1 v-html="'<strong>中国</strong>,'+msg">{{msg}}</h1>//中国,你好
new Vue({
el:"#box",//指定vue的模板css选择器
data:{msg:"你好"}// 指定data数据
})
Vue模板语法-属性渲染
指令参数
指令是带有 v- 前缀的特殊 attribute。指令 属性值预期是单个 JavaScript 表达式
一些指令能够接收一个“参数",在指令名称之后以冒号表示。例如,v-bind 指令可以用于响应式地更新 HTML 属性:
属性渲染
v-bind指令给html标签动态的绑定属性
<h1 v-bind:title="str">这是一个title</h1>
<script type="text/javascript">
new Vue({
el:'#box',
data:{
str:'一句简单的话',
}
})
//v-bind指令
//( :title :disable :class :id等 )指令参数
//str 指令的值
</script>
属性渲染简写
v-bind可以简写为:
<h1 :title="str">这是一个title</h1>
<script type="text/javascript">
new Vue({
el:'#box',
data:{
str:'一句简单的话',
}
})
//v-bind指令
//:title指令参数
//str 指令的值
</script>
条件渲染
v-if v-else-if v-else
<p v-if="score>90">就把潘金莲送给你了</p>
<p v-else-if="score>80">武大郎</p>
<p v-else-if="score>70">武松</p>
<p v-else>逐出师门</p>
<input type="text" v-model="score"/>
new Vue({
el: "#box",//指定vue的模板css选择器
data: {
score:91,//指定data数据
},
})
// v-model 指令,它能轻松实现表单输入和应用状态之间的双向绑定
v-show
<p v-if="flag">v-if</p>
<p v-show="flag">v-show</p>
new Vue({
el:'#box',
data:{
flag:false,
}
})
<!-- v-if与v-show的区别
1.都是用来控制隐藏与显示
2.v-if是通过dom操作实现隐藏 v-show是通过css方式隐藏
3.频繁切换用v-show -->
列表渲染
v-for
<!-- 遍历数字 -->
<p v-for="item in 10">{{item}}</p>
<!-- 遍历对象 -->
<p v-for="item in obj">{{item}}</p>
<p v-for="(item,index) in obj">{{index}}:{{item}}</p>//item当前向 index索引
<!-- 遍历字符串 -->
<p v-for="item in str" :key="item">{{item}}</p>
new Vue({
el: '#box',
data: {
str: '学好前端',
obj: {
tel: 18239607956,
qq: 2523925028,
wx: 123456789,
name: 'baize'
}
}
})
<!-- v-bind:key指令 vue在渲染列表的时候更优化,v-bind:key的值必须是唯一的
不建议用随机或index -->
事件
监听事件
我们可以使用 v-on 指令 (通常缩写为 @ 符号) 来监听 DOM 事件,并在触发事件时执行一些 JavaScript。
<h1>{{counter}}</h1>
<button @click="counter++">{{counter}}</button>
<button v-on:click="counter--">{{counter}}</button>
new Vue({
data() {
return { counter: 1 }
}
})
许多事件处理逻辑会更为复杂,所以直接把 JavaScript 代码写在 v-on 指令中是不可行的。因此 v-on 还可以接收一个需要调用的方法名称。
<button @click="sayNum(1)">{{num}}</button>
<!-- (1)实际参数 (实参)-->
new Vue({
el: '#box',
data(){
return{
num:1
}
},
methods:{
// sayNum:function(){
sayNum(n){// 简写:
this.num+=n;// (n)形式参数(形参)
alert(this.num);
}
}
})
//this指向new Vue创建的实例
// vue data 采用函数返回形式
//vue 实例直接数据隔离相互不影响
事件的特殊参数($event )
<div id="box">
<!-- 默认不写括号也会传入事件$event -->
<!-- 写括号$event,固定写法,代表事件对象 -->
<h1 @click="sayNum($event,1)">事件特殊参数</h1>
<button type="button" @click="sayNum($event,3)">{{num}}</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script>
new Vue({
el: '#box',
data(){
return{
num:1
}
},
methods:{
// sayNum:function(){
sayNum(e,n){// 简写:
// e代表事件对象
// e.target被点击的元素 ,innerText文本内容
alert(e.target.innerText);
this.num+=n
}
}
})
</script>
事件修饰符
概括
.stop 阻止事件冒泡
.prevent 阻止默认事件
.capture 捕获
.self 自身元素触发
.once 执行一次
.passive 滚动立即触发,不等待滚动完成(移动端性能提升)
实例:
<div id="box">
<h1>表白</h1>
<!-- .stop 阻止事件冒泡 -->
<div class="parent" @click="doHd">
<!-- .once 执行一次 -->
<button @click.once="say">表白</button>
<!-- .prevent 阻止默认事件 -->
<a href="http://baidu.com" @click.prevent.stop="doit">百度</a></div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script>
new Vue({
el: '#box',
methods: {
// say:function(){
say() { // 简写:
alert("表白");
},
doit() {
alert("百度!")
},
doHd(){
alert('999')
}
}
})
// .capture 捕获
// .self 自身元素触发
// .passive 滚动立即触发,不等待滚动完成(移动端性能提升)
按键修饰符
监听键盘事件时,我们经常需要检查特定的按键。可以使用按键修饰符
概述
Vue 为最常用的键提供了别名
.enter 回车
.tab 制表
.delete “删除”和“退格”键
.esc 取消
.space空格
.up 上
.down 下
.left 左
.right 右
系统修饰键
按下相应按键时才触发鼠标或键盘事件的监听器。
概述
.enter 回车
.ctrl
.alt
.shift
.meta (⌘或Windows 徽标键 ⊞)
.exact 精确
鼠标按钮修饰符
这些修饰符会限制处理函数仅响应特定的鼠标按钮。
概述
.left
.right
.middle
表单绑定
文本与多行文本
<div id="box">
<h1>表单绑定</h1>
<input type="text" v-model="msg"/>
<p>{{msg}}</p>
<textarea rows="" cols="" v-model="text"></textarea>
<p>{{text}}</p>
<p>{{str}}</p>
<input type="text" v-model="str"/><br>
<!-- v-model="str" 是:value="str" @input="str=$event.target.value" 简写-->
<input type="text" :value="str" @input="str=$event.target.value">
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script>
new Vue({
el: '#box',
data(){
return{
msg:"",
text:"",
str:"one two three"
}
}
})
</script>
复选框checkbox 单选框radio 选择框 select
<div id="box">
//checkbox
<h1>单个checkbox</h1>
<input type="checkbox" v-model="select">{{select}}
<h1>多个checkbox</h1>
<p>{{fav}}</p>
<input type="checkbox" value="唱歌" name="fav" v-model="fav" />唱歌<br>
<input type="checkbox" value="跳舞" name="fav" v-model="fav" />跳舞<br>
<input type="checkbox" value="看书" name="fav" v-model="fav" />看书<br>
<input type="checkbox" value="游泳" name="fav" v-model="fav" />游泳<br>
//radio
<h1>radio-{{sex}}</h1>性别:
<input type="radio" name="sex" v-model="sex" value="1">男
<input type="radio" name="sex" v-model="sex" value="2">女
<input type="radio" name="sex" v-model="sex" value="3">保密<br>
//select
<h1>select -{{sel}}</h1>
<p>小张的文凭</p>
<select name="" id="" v-model="sel">
<option value="胎教">胎教</option>
<option value="学前班">学前班</option>
<option value="小学">小学</option>
<option value="初中">初中</option>
</select>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script>
new Vue({
el: '#box',
data() {
return {
fav: [],
select: true,
sex: 1,
sel: '小学'
}
}
})
</script>
表单修饰符
.lazy
你可以添加 lazy 修饰符,从而转为在 change 事件之后进行同步
<!-- 在“change”时而非“input”时更新 -->
<input type="text" v-model.lazy="str">
<p>{{str}}</p>
new Vue({
el: '#box',
data() {
return {
num: 1,
str: '国庆快乐'
}
}
})
.number
如果想自动将用户的输入值转为数值类型,可以给 v-model 添加 number 修饰符:
<input type="text" v-model.number="num">
<p>{{10+num}}</p>
new Vue({
el: '#box',
data() {
return {
num: 1,
str: '国庆快乐'
}
}
})
.trim
过滤首尾空白
<input v-model.trim="msg" />
new Vue({
el: '#box',
data() {
return {
num: 1,
msg: ' 国庆快乐 '
}
}
})
计算 computed
对于任何包含响应式数据的复杂逻辑,你都应该使用计算属性
(从现有数据计算出新的数据)
实例
<div id="box">
<input type="text" v-model.number="n1">
<input type="text" v-model.number="n2">
<p>{{n3}}</p>
<p>{{str}}</p>
<input type="text" v-model="str">
<p>{{rstr}}</p>
</div>
new Vue({
el: '#box',
computed: {
//从现有的n1与n2计算出n3
"n3": function() {
return this.n1 + this.n2;
},
//从现有的str计算出rstr
rstr() {
return this.str.split("").reverse().join('');
}
},
data() {
return {
n1: 1,
n2: 2,
str: "明天开始放假"
}
}
})
watch监听
虽然计算属性在大多数情况下更合适,但有时也需要一个自定义的侦听器,当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的
1.
<div id="box">
<h1>watch监听</h1>
<button @click="num++">{{num}}</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script>
new Vue({
el: '#box',
data() {
return {
num: 5
}
},
watch: {
"num": {
handler(nval, oval) {
// ovaL和nval都是最新的值
console.log('数据num', oval, "变", nval)
}
}
}
})
</script>
2.引用数据类型需要添加处理器handler与deep
<div id="box">
<h1>watch监听</h1>
<input type="text" v-model="obj.pre">
<select name="" id="" v-model="obj.type">
<option value="+">+</option>
<option value="-">-</option>
<option value="*">*</option>
<option value="/">/</option>
</select>
<input type="text" name="" id="" v-model="obj.next">
=
{{obj.result}}
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script>
new Vue({
el: '#box',
data() {
return {
obj: {
pre: 1,
next: 1,
type: "+",
result: 2
}
}
},
watch: {
"obj": {
//引用类型数据监听需要添加deep选项
// oval和nval都是最新的值
handler(nval, oval) {
// console.Log("数据发生变化" , nvaL , ovaL);
//只要obj发生变化重新计算result的值
this.obj.result = eval(`(${this.obj.pre})${this.obj.type}(${this.obj.next})`);
},
deep: true,
}
}
})
</script>
Class 与Style
class的绑定
操作元素的 class 列表和内联样式 因为它们都是 attribute
Vue.js 做了专门的增强。表达式结果的类型除了字符串之外,还可以是对象或数组。
<style>
.active {
background-color: #FF7700;
color: #fff;
}
.big {
font-size: 24px;
padding: 8px;
}
.bold {
font-weight: 900;
}
</style>
<div id="app">
<!-- 字符串方式 -->
<button @click="flag=!flag" v-bind:class="flag?'active':''">开关</button>
<!-- 对象方式 -->
<button @click="flag=!flag" :class="{'active':flag,'big':isBig}">开关</button>
<!-- 数组方式 -->
<p :class="classList">这是行测试文本</p>
<!-- class绑定为一个对象,如果值为真则该键名作为class绑定元素上 -->
</div>
<!--上面的语法表示 active 这个 class 存在与否将取决于flag值,flag为true表示类存在,反之则不存在 -->
<script>
new Vue({
el: "#app",
data() {
return {
flag: true,
isBig: false,
classList: ['bold', 'big', 'active']
}
},
})
</script>
style的绑定
对象语法:
CSS 属性名可以用驼峰式 (camelCase) 或短横线分隔 (kebab-case,记得用引号括起来) 来命名
<div :style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
数组语法
<div :style="[baseStyles, overridingStyles]"></div>
<div id="app">
<!-- color 选择颜色 range范围值0-100 -->
<input type="color" v-model="color" />
<input type="range" min="1" max="200" v-model="height" />
<!-- height随着滑块改变大小传值给下方行高 -->
<p :style="{'fontSize':'48px','backgroundColor':color,'lineHeight':height+'px'}">样式的绑定</p>
</div>
<script>
new Vue({
el: "#app",
data() {
return {
color: "#ff7700",
height: 80
}
},
})
</script>
组件和动画
组件components(重点)
this的指向:vue实例本身的属性和方法,那么this指向就是vue实例本身,比如methods对象,computed对象,watch对象里的方法
全局组件
它们在注册之后可以用在任何新创建的 Vue 根实例 (new Vue
) 的模板中
Vue.component 来创建组件:
Vue.component("btn",{
template:`<button @click="n++">{{n}}</button>`,
data(){return {n:1}}
})
使用:
<div id="app">
<btn></btn>
</div>
局部组件(常用,重点)
(全局注册是不够理想的。它会被包含在你最终的构建结果中。这造成了用户下载的 JavaScript 的无谓的增加。)
var step = {
template:`<div>
<button @click="n--">-</button>{{n}}<button @click="n++">+</button>
</div>`,
data(){return {n:1}}
}
new Vue({
el:"#app",
components:{step}
})
<step></step>
<step></step>
</div>
props传递参数(父组件向子组件传参数(父传子))
通常你希望每个 prop 都有指定的值类型,比如
(String 、 Number 、 Boolean 、 Array 、 Object 、 Date 、 Function 、 Symbol )
<step :num="10"></step>
<step :num="5"></step>
props:{
"num":{type:Number,default:1}
},
data(){return {
n:this.num
}}
对象与数组的默认值必须是函数的返回值
自定义事件(v-model)
自定义的组件(2.2.0+ 新增)
v-model 双向绑定原理
本质是一中语法糖写法。它负责监听用户的输入事件以更新数据
input 中type="text”中的原理
绑定一个value属性 和一个input事件
v-model = :value + @input
.sync修饰符
.sync修饰符可以实现子组件与父组件的双向绑定,并且可以实现子组件同步修改父组件的值。
一般情况下父子组件之间传参通过props(父组件传子组件)$emit(子组件传父组件)
这里可以使用.sync(本质语法糖)简化代码
插槽
和 HTML 元素一样,我们经常需要向一个组件传递内容,我们使用 <slot> 作为我们想要插入内容的占位符
父组件:
<step>
这是嵌套内容
</step>
子组件:
var step={
template:`<div>
<h1>组件的标题</h1>
<slot></slot>
</div>`}
运行结果:
组件的标题
这是嵌套内容
具名插槽
父组件:
<step>
<template v-slot:pre>
<span slot="pre">¥</span>
</template>
<template v-slot:next>
<span slot="next">元</span>
</template>
</step>
子组件:
const step = {
template:`<div>
<slot name="pre"></slot>
100
<slot name="next"></slot></div>`,
}
运行结果:¥100元
作用域插槽
有时让插槽内容能够访问子组件中才有的数据是很有用的。
当一个组件被用来渲染一个项目数组时,这是一个常见的情况,我们希望能够自定义每个项目的渲染方式。
父组件:
<step>
<template v-slot:default="scope">
<i class="fas fa-check">{{scope.index}}</i>
<span class="green">{{ scope.item }}</span>
</template>
</step>
子组件:
const step = {
template: `<ul>
<li v-for="( item, index ) in list">
<slot :item="item" :index="index"></slot>
</li>
</ul>`,
data() { return {
list: ["vue", 'react', 'angular']}
}}
运行结果:
- 0 vue
- 1 react
- 2 angular
动画
Vue 提供了内置的过渡封装组件,该组件用于包裹要实现过渡效果的组件。
组件进入和离开 DOM 的钩子 使用内置的 <transition> 组件
<div id="app">
<button @click="flag=!flag">切换</button> <br>
<transition name="fade">
<img src="./images/sun.jpeg" alt="" width="120" v-if="flag">
</transition>
</div>
new Vue({
el: '#app',
data() { return { flag: true } }
})
动画-过渡
在进入/离开的过渡中,会有 6 个 class 切换。
v-enter-active 进入开始 v-enter-to 进入结束 v-enter-active进入整个状态
v-leave-active 离开开始 v-leave-to 离开结束 v-leave-active离开整个状态
动画-关键帧
@keyframes fadeIn{
from{opacity: 0;}
to{ opacity: 1;}
}
@keyframes fadeOut {
0%{ opacity: 1;}
100%{ opacity: 0;}
}
.fade-enter-active{ animation: fadeIn ease 1s;}
.fade-leave-active{ animation: fadeOut ease 1s;}
动画-引入
直接引入插件
animate动画库:https://www.jq22.com/yanshi819
<link rel="stylesheet" href="./css/animate.css">
<transition name="fade" enter-active-class="animated slideInDown" leave-active-class="slideOutDown animated">
<img src="./images/sun.jpeg" alt="" width="120" v-if="flag">
</transition>