一、概念
Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。
二、快速入门
1.起步
引入JS
<!-- 1.开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- 2.生产环境版本,优化了尺寸和速度 -->
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<!-- 3.npm安装vue组件-->
$ npm install vue
2.插件引入
VSCode 安装 Vue 2 Snippets
Vue语法提示
3.基本语法
3.1 声明式渲染
<script>
//vue声明式渲染
let vm = new Vue({
el:"#app", //绑定元素
data:{ //封装数据
name:"zhangsan",
num:0
},
methods:{ //封装方法
}
});
</script>
<div id="app">
{{ message }}
</div>
3.2 双向绑定
数据模型变化,视图变化,反之,视图变化,数据模型也变化
数据改变时,动态渲染视图。
<body>
<div id="app">
<input type="text" v-model="num">
<h1>I`m {{name}},当前输入的数字是 {{num}}</h1>
</div>
</body>
<script>
let vm = new Vue({
el:"#app",
data:{
name:"zhangsan",
num:0
}
});
</script>
3.3 条件与循环
v-if
用于控制一个元素是否显示。true–显示 false–隐藏
v-if
是让该标签完全消失
<div id="app-3">
<p v-if="seen">现在你看到我了</p>
</div>
<script>
var app3 = new Vue({
el: '#app-3',
data: {
seen: true
}
})
</script>
v-if
和 v-else-if
的结合使用
<div id="app4">
<button @click="random=Math.random()">点我生成随机数</button>
<span>{{random}}</span>
<h1 v-if="random>=0.75">>= 0.75</h1>
<h1 v-else-if="random>=0.5">>= 0.5</h1>
<h1 v-else-if="random>=0.2">>= 0.2</h1>
<h1 v-else-if="random<0.2"><= 0.2</h1>
</div>
<script>
let vm4 = new Vue({
el:"#app4",
data:{
random:1
}
});
</script>
v-show
用于控制一个元素是否显示,和 v-if
不同的是, v-show
是通过样式display:none
来控制显隐的。
v-for
绑定数组的数据来渲染一个项目列表
vue会 “复制” 加了 v-for
标签的元素标签,复制的个数为数组的长度,然后一一对应渲染数组的值
PS:建议每次遍历时都加上 唯一标识 :key="当前对象的唯一标识值,如ID等等"
可以提高vue渲染效率
<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>
带索引和对象信息的 v-for
,并使用v-if
来过滤遍历结果
<div id="app3">
<ul>
<li v-for="(user,index) in users" v-if="user.gender == 'g'">
当前索引:{{index}} <br>
当前对象信息:{{user.name}}/{{user.gender}}/{{user.age}} <br>
对象信息: <span v-for="(v,k,i) in user">属性名:{{k}} : 属性值:{{v}} : 索引值:{{i}}} | </span> <br>
<hr/>
</li>
</ul>
</div>
<script>
let vm3 = new Vue({
el:"#app3",
data:{
users:[
{name:'a1',gender:'m',age:21},
{name:'a2',gender:'g',age:22},
{name:'a3',gender:'g',age:23},
{name:'a4',gender:'m',age:24}
]
}
});
</script>
3.4 处理用户输入
v-model
用于把Vue.data中的值与dom对象(输入框、单选、多选)中的值(Value) 进行绑定(不是属性)
<body>
<div id="app">
<input type="text" v-model="num">
<h1>当前输入的数字是 {{num}}</h1>
</div>
</body>
<script>
let vm = new Vue({
el:"#app",
data:{
num:0
}
});
</script>
v-bind:属性名
可以简写为 :
如何属性的值如果包含 -
就需要用引号括起来
<div id="app2">
<a v-bind:href="link">gogogogo</a>
<span v-bind:class="{active:isActive,'text-danger':hasError}">Hello</span>
</div>
<script>
let vm2 = new Vue({
el:"#app2",
data:{
link:"https://www.baidu.com",
isActive:true,
hasError:true
}
});
</script>
v-on
可以简写为 @
例如 @:click
添加一个事件监听器,click
表示点击事件
通过它调用在 Vue 实例中定义的方法,v-on
指令的值为要调用的方法名
事件冒泡:如果子元素和父元素都绑定了点击事件,那么点击子元素后会依次执行子元素的事件和父元素的事件,默认开启
阻止事件冒泡:@chick.stop="xxx"
默认行为:HTML的有些标签有默认执行的动作。如:a标签会执行跳转动作。
修改默认行为:@click.prevent.stop="xxx"
可以执行自定义的方法、操作,如果值为空就是不执行任何操作
按键修饰: 按键盘上某个特定的键触发的操作。
绑定按键操作:@keyup.up="xxx"
给上方向键绑定事件。up
是vue抽取的常用按键的别名
vue抽取常用按键的别名:.enter
.tab
.delete(删除和退格)
.esc
.space
.up
.down
.left
.right
其余按键按照.键码
的方式进行绑定
绑定组合键操作:@click.ctrl="xxx"
按住ctrl后点击触发事件
@keyup.alt.up="xxx"
按住alt 和 上方向键触发事件
<div id="app-5">
<p>{{ message }}</p>
<button v-on:click="reverseMessage">反转消息</button>
</div>
<script>
var app5 = new Vue({
el: '#app-5',
data: {
message: 'Hello Vue.js!'
},
methods: {
reverseMessage: function () {
this.message = this.message.split('').reverse().join('')
}
}
})
</script>
v-html
绑定变量,并用HTML语法解析后展示
<div id="app1">
<span v-html="msg">
</span>
</div>
<script>
let vm = new Vue({
el:"#app1",
data:{
msg:"<h1>Hello</h1>"
}
});
</script>
差值表达式 {{}}
格式:{{表达式}}
说明:
- 支持JS语法,可以调用JS内置函数(函数必须有返回值)
- 表达式必须有返回的结果。没有结果的表达式不允许使用,如:
let a = 1 + 1
- 可以直接获取Vue实例中定义的
data
或methods
<h1>当前输入的数字是 {{num}}</h1>
3.5 构建组件化模板
组件相当于自定义一个标签模板,这个标签模板有着自己的内容和逻辑
// 定义名为 todo-item 的新组件
Vue.component('todo-item', {
// todo-item 组件现在接受一个 "prop",类似于一个自定义 attribute参数。
// 这个 prop 名为 todo。
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: '随便其它什么人吃的东西' }
]
}
})
<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>
3.6 计算器computed
当值发生变化时自动执行
<div id="app5">
<ul>
<li>book1 价格:{{xyjprice}} <input type="number" v-model="xyjnum"></li>
<li>book2 价格:{{shzprice}} <input type="number" v-model="shznum"></li>
<li>总价: {{totalPrice}}</li>
</ul>
</div>
<script>
new Vue({
el:"#app5",
data:{
xyjprice:7,
shzprice:8,
xyjnum:0,
shznum:0
},
computed: {
totalPrice(){
return this.xyjnum*this.xyjprice + this.shznum*this.shzprice
}
},
})
</script>
3.7 监听器watch
监听器
格式:要监听的变量: function(newVal,oldVal){}
方法默认的参数为被监听变量的新值和旧值
<div id="app5">
<ul>
<li>book1 价格:{{xyjprice}} <input type="number" v-model="xyjnum"></li>
<li>book2 价格:{{shzprice}} <input type="number" v-model="shznum"></li>
<li>总价: {{totalPrice}}</li>
{{msg}}
</ul>
</div>
<script>
new Vue({
el:"#app5",
data:{
xyjprice:7,
shzprice:8,
xyjnum:0,
shznum:0,
msg:""
},
computed: {
totalPrice(){
return this.xyjnum*this.xyjprice + this.shznum*this.shzprice
}
},
watch: {
xyjnum: function(newVal,oldVal){
if(newVal > 3){
this.msg = "西游记--库存不足"
this.xyjnum = 3
}
}
},
})
</script>
3.8 过滤器 filters
局部过滤器
<div id="app6">
<ul>
<li v-for="item in userList">
{{item.gender | genderFilter}}
</li>
</ul>
</div>
<script>
new Vue({
el:"#app6",
data:{
userList:[
{id:1,name:"a1",gender:1},
{id:2,name:"a2",gender:0},
{id:3,name:"a3",gender:1}
]
},
filters:{
genderFilter(val){
if(val == 1){
return '女';
}else{
return '男';
}
}
}
})
</script>
全局过滤器
<div id="app6">
<ul>
<li v-for="item in userList">
{{item.gender | gFilter}}
</li>
</ul>
</div>
<script>
Vue.filter("gFilter",function(val){
if(val == 1){
return '女';
}else{
return '男';
}
})
new Vue({
el:"#app6",
data:{
userList:[
{id:1,name:"a1",gender:1},
{id:2,name:"a2",gender:0},
{id:3,name:"a3",gender:1}
]
}
})
</script>
4.组件化
注意:
- 组件名不能包含大写字母
- 不管哪儿种方式声明的组件,都只能在被vue对象绑定的元素中使用
全局组件与局部组件实例
<div id="app7">
<all></all>
<button-count></button-count>
</div>
<script>
// 全局组件
Vue.component("all",{
template:`<button @click="count++">我被点击了{{count}} 次</button>`,
data() {
return {
count:0
}
}
});
// 局部声明一个组件
const buttonCounter = {
template:`<button @click="count++">我被点击了{{count}} 次</button>`,
data() {
return {
count:0
}
}
}
new Vue({
el:"#app7",
data:{
count:1
},
components:{
'button-count':buttonCounter
}
})
</script>
5.生命周期
每个vue实例在创建时都要经过一系列的初始化过程:
- 初始化–事件&生命周期
- 初始化–注入&校验
- 挂载模板
- 被修改时,虚拟DOM重新渲染并应用更新
- 销毁实例,解除绑定、销毁子组件和监听器等等
Vue在生命周期中的每个状态都设置了钩子函数(监听函数,类似AOP服务增强)
当Vue处于不同的生命周期时,对应的钩子函数就会被触发调用
生命周期图示
图中涉及:
beforeCreate
:初始化注入之前
此时数据模型未加载,方法未加载,模板未加载created
:初始化注入之后
此时数据模型已加载,方法已加载,模板已加载,模板未渲染beforeMount
:挂载模板之前
模板未渲染(表达式还没解析)mounted
:挂载模板之后
模板已渲染beforeUpdate
:修改之前
数据模型已更新,模板未更新(模板未重新渲染)updated
:修改之后
数据模型已更新,模板已更新(模板已重新渲染)beforeDestroy
:销毁之前destroyed
:销毁完毕
6.模块化开发
6.1 环境准备
#windows命令窗口下全局安装
# 安装webpack
npm install webpack -g
# 安装vue命令行脚手架
npm install -g @vue/cli-init
6.2 初始化vue项目
# 在vue的工作空间执行
# vue脚手架使用webpack模板初始化一个项目
vue init webpack 项目名
# 选择初始化项目的各种参数...
# 启动项目
cd 项目名目录
npm run dev
6.3 开发流程
6.3.1 编写vue组件
.vue
的构成:
- 写vue模板
- 写vue实例,JS
- 调试样式
<template>
<div id="app">
<img src="./assets/logo.png">
<router-view/>
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
6.3.2 配置路由
配置跳转规则
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'HelloWorld',
component: HelloWorld
}
]
})
import Vue from 'vue'
import App from './App'
import router from './router'
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
components: { App },
template: '<App/>'
})
6.4 整合Element-UI
6.4.1 安装
npm i element-ui
安装完成后 package.json 里会有相关信息
"dependencies": {
"element-ui": "^2.14.0",
"vue": "^2.5.2",
"vue-router": "^3.0.1"
}
6.4.2 导入
在main.js中导入Element-UI
// 导入插件
import ElementUI from 'element-ui'
//导入样式
import 'element-ui/lib/theme-chalk/index.css'
//设置vue使用element-ui
Vue.use(ElementUI)
6.4.3 使用Element-UI 标签
具体参考 Element-UI文档
<el-table :data="tableData">
<el-table-column prop="date" label="日期" width="140">
</el-table-column>
<el-table-column prop="name" label="姓名" width="120">
</el-table-column>
<el-table-column prop="address" label="地址"> </el-table-column>
</el-table>
6.4.4 抽取组件
<!--用此标签标识组件部分-->
<router-view></router-view>