vue基本概述
Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。
Vue.js是一套构建用户界面的渐进式框架,采用自底向上增量开发的设计。Vue的核心库关注于视图(html),不仅易上手,还便于与第三方库或项目整合。
渐进式:一步一步,不是将所有的东西都学完才能使用。
自底向上设计:一种设计程序的过程和方法,就是先编写出基础程序段,然后在逐步扩大规范、补充和升级某些 功能,实际上是一种自底向上构造程序的过程。
Vue.js的核心是允许采用简洁式模板语法来声明的将数据渲染进DOM的系统
在使用数据之前需要先进性声明才可以使用
为什么要学习Vue?
简单,前端三大框架(Vue,React,angler)中是对小白最友好的框架
另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。
Vue和Jquery有什么区别?
数据驱动试图
- jquery到vue转变是一个思想的转变,是将jquery直接操作dom的思想转变到操作数据上去。
- jQuery是使用选择器选取DOM对象,对其进行赋值、取值、事件绑定等操作,其实和原生的HTML的区别只在于可以更方便的选取和操作DOM对象
- Vue则是通过Vue对象将数据和View完全分离开来了。对数据进行操作不再需要引用相应的DOM对象,可以说数据和View是分离的,他们通过Vue对象这个vm实现相互的绑定。这就是传说中的MVVM
什么时候学习Vue?
先把前端三件套熟悉(HTML,CSS,JavaScript)
Vue基本语法
官方文档
插值表达式
使用{{ }}进行渲染data:{}里面的变量
也可以是函数,不过在data里面的方法,在插值表达式中需要补充大括号
例如
HTML
<div id="app">
<div>{{ msg }}</div>
<div>{{ getInfo() }}</div>
</div>

在插值表达式中,支持运算符,以及一些方法
vue指令:
v-text
渲染文本,和插值表达式类似
HTML
<div></div>
<div>{{ msg }}</div>
也是支持运算符的
HTML
<div></div>
v-html
渲染标签,如果字符串是含标签的特殊字符,那么vue会将它渲染成标签
如果是v-text或者是使用插值表达式,则会原样输出

注意:
v-html一般是用来渲染信任的文本,例如文章的详情内容等,最好不要用在用户提交的地方
容易造成XSS攻击
v-bind
可以给标签动态添加内容,也可以给动态的修改标签属性
不过在属性上的操作稍微和操作内容不太一样,我们使用v-bind指令
例如我想动态修改img标签的src属性,希望它去读取data里面的值
但是我们不能在属性中使用插值表达式

这样写src直接将我的内容原样输出了,所以我们需要使用v-bind,全称为动态属性
那么我可以这么做
HTML
<img alt="">

当然,v-bind: 可以简写为 :
HTML
<img alt="">
v-bind不仅可以用于HTML存在的属性,还可以应用在自定义属性上
例如
HTML
<p></p>
实际结果:
<p id="p_01"></p>
在vue所有的指令中,都是支持表达式的
例如:
JavaScript
<div class="name">
{{ a.length === 0 ? '没有数据' : a }}
-{{ a.split('.')[1] }}
</div>
什么是表达式?
JavaScript
// 这是语句
var a = 1;
// 这是表达式
a.length === 0 ? '没有数据' : a
条件渲染
v-if和v-else的普通使用
v-if中的布尔值为true,则渲染这个div
如果if不成立,则渲染else中的代码块
HTML
<div id="app">
<div>{{ num }}</div>
<div id="if">
<div>大于0.9的概率</div>
<div>v-if不满足显示我</div>
</div>
</div>
v-else-if多条件语句
HTML
<div id="v-else-if">
<div>大于0.9的概率</div>
<div>大于0.6的概率</div>
<div>大于0.4的概率</div>
<div>大于0.2的概率</div>
<div>所有条件都不成立</div>
</div>
v-if="flag",为true的时候显示
为false的时候消失
JavaScript
<div id="app">
<div class="name">
{{ name }}
</div>
<div>
if没匹配到就显示我
</div>
</div>
v-show与v-if的区别
- v-if如果是false,不会渲染
- v-show如果是false,不会显示
style="display: none;"
体会一下v-if和v-show
HTML
一个是看不见,但是我存在,只是我隐藏了 v-show
一个是看不见,因为我本来就没被渲染 v-if
列表渲染
主要分为遍历列表和遍历对象
遍历列表
JavaScript
lis: [
'张三',
'王伟',
'张伟',
'王五',
]
此时的item就是每个元素
HTML
<ul>
<li>
{{ item }}
</li>
</ul>
key要唯一!!!
如果需要遍历出每个元素的索引
则在遍历的时候指定index
HTML
<ul>
<li>
{{ index }} -- {{ item }}
</li>
</ul>
遍历对象
JavaScript
obj:{
name: '张三',
age: 21,
addr: '北京市',
}
一个参数,就是遍历对象的值
二个参数,值和键
三个参数,值,键,索引
HTML
<ul>
<li>
对象的值:{{ item }}
</li>
</ul>
<ul>
<li>
对象的值:{{ item }}
对象的键:{{ key }}
</li>
</ul>
<ul>
<li>
对象的值:{{ item }}
对象的键:{{ key }}
变量的索引:{{ index }}
</li>
</ul>
Vue事件
v-on:或者@
HTML
<div id="app">
<div>
{{ num }}
</div>
<div>
<button>点我 +</button>
<button>点我 -1</button>
</div>
</div>
事件所执行的方法是要被定义在methods里面
JavaScript
methods: {
add() {
this.num ++
}
}
参数问题
可以通过传参进行参数传递
HTML
<button>点我 +</button>
...
add(number) {
this.num += number
}
// 此时的add函数就能接收到传递进来的参数值
默认参数
默认参数就是触发当前事件的事件对象
JavaScript
<button id="add" class="add_cls">点我 +</button>
一定是v-on:click="add",只写一个函数名,
而不是v-on:click="add()",这样获取不到事件对象
JavaScript
// 获取触发当前事件的标签
add(event) {
// 触发当前事件的事件对象
console.log(event)
// 获取标签
console.log(event.target)
// 获取id,class
console.log(event.target.id)
console.log(event.target.className)
}
如果有参数,想接收事件对象
使用$event进行传递
JavaScript
<button id="add" class="add_cls">点我 +</button>
...
add(number, event) {
this.num += number
// 触发当前事件的事件对象
console.log(event)
// 获取标签
console.log(event.target)
// 获取id,class
console.log(event.target.id)
console.log(event.target.className)
}
图片轮播案例
HTML
<title>图片轮播</title>
<div id="app">
<div>
<img alt="">
</div>
<div>
<button>上一张</button>
<button>下一张</button>
</div>
</div>
事件修饰符
在事件处理程序中调用 event.preventDefault() 或 event.stopPropagation() 是非常常见的需求。尽管我们可以在方法中轻松实现这点,但更好的方式是:方法只有纯粹的数据逻辑,而不是去处理 DOM 事件细节。
为了解决这个问题,Vue.js 为 v-on 提供了事件修饰符。之前提过,修饰符是由点开头的指令后缀来表示的。
HTML
<a></a>
<form></form>
<a></a>
<form></form>
<div>...</div>
<div>...</div>
<a href="http://www.fengfengzhidao.com">枫枫知道</a>
事件冒泡
HTML
<div class="parent">
<div class="center">
<div class="child">
</div>
</div>
</div>
点击里元素,执行顺序

点击中间的元素

被父元素包裹的元素,点击事件发送后会逐级将事件向上传递
HTML
<p>阻止事件冒泡</p>
<div class="parent">
<div class="center">
<div class="child">
</div>
</div>
</div>
添加stop事件修饰符之后,点击里元素,会阻止事件继续向上传播
键盘事件
HTML
@keydown 键盘按下
@keyup 键盘回弹
按下回车触发
支持组合键
HTML
<input type="text">
<input type="text">
> 使用修饰符时,顺序很重要;相应的代码会以同样的顺序产生。因此,用 v-on:click.prevent.self 会阻止所有的点击,而 v-on:click.self.prevent 只会阻止对元素自身的点击。
2.1.4新增
HTML
<a></a>
按键修饰符
最常见的可能就是在一个输入框中,判断用户是否按下了回车键
HTML
<input>
一些必要的按键名称
HTML
.enter
.tab
.delete (捕获“删除”和“退格”键)
.esc
.space
.up
.down
.left
.right
组合按键
HTML
<input>
<div>Do something</div>
计算属性
- 调用的时候不用加括号(只是一个属性)
- 可以监听属性变化,属性变化,计算属性重新执行
- 并且有缓存(多个计算属性,只执行一次)
和methods的区别
属性变化,methods方法全部重新获取
HTML
<title>计算属性</title>
<div id="app">
<div>{{ name }}</div>
<div>{{ name.split('').reverse().join('') }}</div>
<div>{{ name.length === 5 ? '五言绝句' : '七言绝句' }}</div>
<div>五言绝句</div>
<div>七言绝句</div>
<div>错了</div>
<div>{{ getName }}</div>
<div>{{ getName }}</div>
<div>{{ getName }}</div>
<div>{{ getName }}</div>
<div>{{ getName }}</div>
<div>{{ getName }}</div>
<div>{{ getName }}</div>
<div>{{ get_data_name() }}</div>
<div>{{ get_data_name() }}</div>
<div>{{ get_data_name() }}</div>
<div>{{ get_data_name() }}</div>
<div>{{ get_data_name() }}</div>
<button>
点我
</button>
<span>{{ num }}</span>
<button>计算属性</button>
</div>
computed与watch,methods的区别
methods:可以放入函数,并且没有缓存
watch:
监听,当数据发送变化时,才会触发
可以得到现在的值和过去的值
还可以监听路由变化
和属性同名
自定义过滤器
创建一个过滤器
JavaScript
// 自定义过滤器
filters:{
// 截取最后一个字符
getLastChar(item){
return item.substr(item.length-1,1)
}
}
使用过滤器
HTML
<li>
{{item.name|getLastChar }} -- {{ item.addr }}
</li>
时间过滤器

HTML
<div id="app">
<div>
当前时间:{{ now|get_date }}
</div>
<ul>
<li>
id:{{ item.id }} 时间:{{ item.date|get_date }}
</li>
</ul>
<div>
时间过滤
</div>
<ul>
<li>
id:{{ item.id }} 时间:{{ item.date|time_to_filter }}
</li>
</ul>
</div>
参数问题
自定义过滤器也是可以接受参数,它的书写语法是
JavaScript
<li>
id:{{ item.id }} 时间:{{ item.date|time_to_filter('a', 'b') }}
</li>
...
filters: {
...
time_to_filter(date_str, a, b) {
// date_str -> '自身的值'
// a -> 'a'
// b -> 'b'
return date_str
}
}
过滤器方法的第一个参数就是调用者本身的值,第二个参数之后就是调用的实参
并且支持链式过滤器
HTML
<div>{{now|get_now|get_now1}}</div>
全局方法
需要将属性和方法挂载到Vue.prototype上
JavaScript
Vue.prototype.$com = "全局变量"
let global_method = ()=>{
return "全局方法"
}
function add(){
return "全局 add 方法"
}
Vue.prototype.$global_method = global_method
Vue.prototype.$add = add
使用
HTML
<div>
{{ $global_method() }}
</div>
<div>
{{ $add() }}
</div>
全局过滤器
JavaScript
// 全局过滤器
let global_filter = (item) => {
return item + '--global'
}
// 注册全局过滤器 (过滤器名称,方法)
Vue.filter('global_filter', global_filter)
使用全局过滤器
HTML
<div>
{{ $com|global_filter }}
</div>
局部组件
HTML
<title>局部组件</title>
<div id="app">
</div>
全局组件
HTML
<title>局部组件</title>
<div id="app">
</div>
组件通信
父传子
父传子:通过props来进行通信
HTML
1. 在自组件中声明props接收在父组件挂载的属性
2. 可以在自组件的template在任意使用
3, 在父组件绑定自定义的属性
props传入一个对象
JavaScript
props: ['title', 'likes', 'isPublished', 'commentIds', 'author']
props: {
title: String,
likes: Number,
isPublished: Boolean,
commentIds: Array,
author: Object,
callback: Function,
contactsPromise: Promise // or any other constructor
}
props: {
data: {
type: String, // 类型
required: true, // 必填项
default: '张三' // 如果没传值,那么这个默认值就是它
}
}
HTML
<div id="app">
</div>
created与mounted
JavaScript
created(){
console.log(this.data, 1)
},
mounted(){
console.log(this.data, 2)
}
子传父
HTML
1. 在父组件中,自组件上绑定自定义事件
2. 在自组件中,触发原生的事件,在事件函数通过this.$emit触发自定义的事件
父组件
JavaScript
components: {
comment1
},
methods: {
eff(data) {
// data 是子组件传递的数据
console.log('父组件被调用了', data)
}
}
子组件
JavaScript
let comment1 = {
template: `
<div>
<ul>
<li>兰州拉面</li>
<li>哈尔滨啤酒</li>
<li>四川担担面</li>
<button>点我触发父组件方法</button>
</ul>
</div>`,
methods: {
add() {
this.$emit('eff', {name: '子组件传来的数据'})
}
}
}
平行组件
HTML
<title>平行组件</title>
<style>
body {
margin: 0;
}
#app {
display: flex;
}
#app > div {
width: 50%;
height: 200px;
display: flex;
justify-content: center;
align-items: center;
}
#gouwuc {
background-color: #3a8ee6;
}
#get {
background-color: #b3d9d9;
}
</style>
<div id="app">
</div>
多次嵌套取值
HTML
1. provide 提供变量 函数(){return {} },
2. inject 接收变量 inject: [],
匿名插槽
JavaScript
let base_layout = {
data() {
return {}
},
template: `
<div>
<header>
我是页头
</header>
</div>`
}
new Vue({
el: '#app',
components: {
base_layout
}
})
在模板中把想要替换的东西放在``标签中,这就是一个占位符
HTML
实际的内容
这样就会将标签中的内容去代替slot中的内容
如果slot都没有名字,那么如果有多个slot,就会全部进行替换
具名插槽
如果你的模板中需要有多个地方被替换
那么匿名插槽就不太合适了,我们给每个插槽都起一个别名
JavaScript
let base_layout = {
data() {
return {}
},
template: `
<div>
<header>
我是页头
</header>
<main>
我是内容
</main>
<footer>
我是页脚
</footer>
</div>`
}
这样我们在进行替换的时候,指明要替换哪个slot就OK了
HTML
<template>
头部
</template>
<template>
身体
</template>
<template>
尾部
</template>
注意v-slot的写法
HTML
v-slot:header
v-slot: 可以简写为 #
HTML
<template>
<div>
哈哈哈哈
</div>
</template>
<template>
身体
</template>
<template>
尾部
</template>
> 我们在替换的时候,是可以写任意标签的,也就是说,在替换的时候,你也可以将组件写入插槽中
HTML
<template>
<div>
哈哈哈哈
</div>
</template>
<template>
身体
</template>
<template>
尾部
</template>
作用域插槽
JavaScript
let base_layout = {
data() {
return {
user: {
name: '枫枫',
xin: '知道'
}
}
},
template: `
<div>
<main>
{{ user.xin }}
</main>
</div>`
}
在子组件中,我在插槽里面显示的是user的xin,如果我想让它显示user的name应该怎么做呢
如果我们直接在父组件调用的时候这样写
HTML
{{ user.name }}
这是错误的写法,因为我们的user是被定义再自组件中的,在父组件中就无法使用这个user,所以就会报错啦
那么我们就应该将这个user对象传递给父组件
在子组件中
HTML
{{ user.xin }}
通过动态属性的方式将user传递给父组件
在父组件中
HTML
<template>
{{ slotProps.user.name }}
</template>
接收传递来的user即可
slotProps可以是你自己定义的名字,它里面存储的是这样的
HTML
{ "user": { "name": "枫枫", "xin": "知道" } }
所以我们将slotProps中的user中的name传递给子组件,就可以做到数据动态替换
如果你的组件中,有且只有一个默认插槽,那么在替换的时候,是可以这么做的
HTML
{{ slotProps }}
但是,如果出现了具名插槽,这样会导致作用域混乱
我们应该这样使用
JavaScript
let base_1 = {
data(){
return {
user: {
name: '枫枫知道',
age: 21
}
}
},
template: `
<div>
<header>
我的名字是 {{ user.name }},年龄是{{ user.age }}
</header>
</div>`
}
HTML
<template>张子枫</template>
<template>{{ slotBase }}</template>
动态组件
> ``元素是vue 里面的一个内置组件。
在里面使用 v-bind: is,可以实现动态组件的效果。
自定义指令
前面使用的v-if, v-show,以及v-for这些都是Vue为我们提供的内置指令
当然,我们也可以自己自定义一个指令
局部自定义指令
JavaScript
directives: {
focus: {
// 指令的定义
// 使用这个指令就会聚焦在输入框中
inserted: function (el) {
el.focus()
}
}
}
使用
HTML
<input type="text">
在focus中有几个钩子函数,需要了解
bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。