Vue简介
Vue 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。
Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。
Vue还提供了 MVVM 数据绑定和一个可组合的组件系统,具有简单、灵活的 API,其目标是通过尽可能简单的 API 实现响应式的数据绑定和可组合的视图组件。
另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。
vue的主要特点
- 轻量级的框架
- 双向数据绑定
- 指令
- 组件化
- 客户端路由
- 状态管理
安装
cdn引入
## 最新版
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
## 指定版本
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14"></script>
官网提供的链接有时候会无法使用,可以换一个cdn,这是我在staticfile找的cdn,传送门,
https://cdn.staticfile.org/vue/2.6.0/vue.js
搜索框输入vue,然后选择版本,将对应的链接添加到我们的script标签中即可
npm
# 最新版
npm install vue
注:本教程使用cdn引入
Vue实例
每一个vue的应用都是通过new创建一个新的Vue实例开始的
new Vue({
//选项
})
下面创建第一个vue程序
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>第一个Vue程序</title>
<script src="https://cdn.staticfile.org/vue/0.10.0/vue.js"></script>
</head>
<body>
<div id="app">{{test}}</div>
<script type="text/javascript">
new Vue({
el: '#app',
data:{
test:'hello vue'
}
})
</script>
</body>
</html>
Vue.js 的核心是一个允许采用简洁的模板语法来声明式地将数据渲染进 DOM 的系统
在上面的实例中,我们通过id名app将Vue实例挂载到一个div上,然后通过文本插值的方式将数据进行插入,当然你也可以使用class,只需要将标签赋予一个类名,然后将el属性改为“.className”即可,不过这种方法一般不建议。
数据和方法
当一个Vue的实例被创建时,data对象的所有属性均被加入到Vue的响应式系统中,当属性值改变时,视图也随之相应为更新的值。
从第一个实例我们可以看到,data就是我们所说的数据对象,这里直接上官方文档
// 我们的数据对象
var data = { a: 1 }
// 该对象被加入到一个 Vue 实例中
var vm = new Vue({
data: data
})
// 获得这个实例上的 property
// 返回源数据中对应的字段
vm.a == data.a // => true
// 设置 property 也会影响到原始数据
vm.a = 2
data.a // => 2
// ……反之亦然
data.a = 3
vm.a // => 3
在vue中,我们除了使用data定义数据对象,还能用methods定义方法基本语法为
new Vue({
methods: {
functionName: function(){},
// 还可以简写为
functionName(){}
}
})
那么如何使用Vue实例中的数据和方法,看如下示例
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>数据与方法</title>
<script src="https://cdn.staticfile.org/vue/2.6.0/vue.js"></script>
</head>
<body>
<div id="app">
<p>{{test}}</p>
<p>{{!test?getValue():"123"}}</p>
<button v-on:click="setValue()">{{buttonName()}}</button>
</div>
<div>{{test}}</div>
<script type="text/javascript">
new Vue({
el: '#app',
data:{
test:'hello vue'
},
methods: {
buttonName(){
return "按钮"
},
getValue(){
return this.test
},
setValue(){
this.test = "hi Vue"
}
}
})
</script>
</script>
</body>
</html>
我们通过双大括号“{{}}”在标签上进行文本插值,但是除了简单的property键值,我们还可以使用函数或者表达式,例如在本例中第二个p标签使用了三元表达式,按钮处使用了一个方法,返回了“按钮”作为button的名称。
常用指令
在vue中,指令是指带有 v- 前缀的特殊属性,预期值是单个JavaScript表达式,首先得分清楚什么是表达式,什么是语句。
表达式是 值、变量以及运算符的组合,例如算数表达式,赋值表达式,逻辑表达式、还有三元表达式
x + 1 //算数表达式
x = 0 //赋值表达式
x > 1 //逻辑表达式
x===0?true:false //三元表达式
在 HTML 中,JavaScript 语句是由 web 浏览器“执行”的“指令“。由值、运算符、表达式、关键词和注释组成。举几个例子吧
let x = 1;
for(i in x){}
console.log(x)
这种便是语句。
然后介绍一下常用的指令
-
v-bind:这个指令用于接收参数,并响应式的更新html属性,例如
<!--这是常规写法--> <a href="https://blog.zhaojiuyi.top"></a> <!--这是使用参数绑定的写法--> <a v-bind:href="url"></a> new Vue({ data: { url: 'https://blog.zhaojiuyi.top' } })
-
v-on:这个指令用于监听DOM事件,例如点击事件
<button v-on:click="functionName()">我是一个按钮</button> <!--这里的functionName()则是我们写在methods里面的方法-->
-
v-for:这个指令用于列表渲染,可以通过for循环的方式将列表里面的所有元素渲染到网页,其语法为 v-for=“item in items”,其中items是数组名,item是被迭代的数组元素,示例
<div id="app"> <li v-for="item in test">{{item}}</li> </div> <script type="text/javascript"> new Vue({ el: '#app', data:{ test: [1,2,3,4,5,6] } }) </script>
除了被迭代的元素,v-for还支持第二个参数——索引,语法为
v-for=”(item,index)in items“
当Vue更新被渲染的元素列表时,我们需要每个节点一个key,以便Vue跟踪每个节点的身份,实现重用和重新排列现有元素。注:这个key应该是唯一的
<!--参照这种写法--> <div v-for="(item,index)in items" :key="index"> {{item}} </div>
-
v-show:根据传入参数的真假判断是否展示元素
<div v-show="true">测试文字</div> <!--当v-show为true时元素显示,为false时不显示--> <div v-show="isShow" id="test">测试文字</div> <script> new Vue({ el: "#test" data: { isShow: false } }) </script>
除了传入布尔值,还可以传入数字,例如1为true,0为false,除此之外,还可以传入一个变量,当变量为null,undefined或0时 ,v-show为false。
-
v-html:在前面我们了解到了如何使用双大括号进行数据绑定,然而双大括号会把数据解释为普通文本,当我们想要输出一段html代码时,便可以使用v-html
<div id="app"> <div>{{msg}}</div> <div v-html="msg"></div> </div> <script type="text/javascript"> new Vue({ el: '#app', data:{ msg: `<span style="color: red;">这是一段html代码</span>` } }) </script>
-
v-if,v-else,v-else-if:v-if和v-show都能用来进行条件渲染,区别在于,v-show只是控制了元素的display,元素在html加载时已经被渲染,只是进行简单的css样式切换;而v-if只在条件为真时才开始渲染元素,是真正的条件渲染,v-else和v-else-if就参照我们写其他语言时的if-else即可,v-else和v-else-if必须跟在v-if之后。注:v-else和v-else-if不是必须的,根据自己业务需求来使用
<div v-if=""></div> <div v-else-if=""></div> <div v-else=""></div>
其中v-bind和v-on两个指令由于使用频繁,所以提供了缩写v-on缩写为@,v-bind缩写为:
<a v-bind:href="url">...</a> <a v-on:click="doSomething">...</a> <!-- 缩写 --> <a :href="url">...</a> <a @click="doSomething">...</a>
计算属性
通过Vue的模板语法,我们能轻松的进行插值和运算,但是模版内的表达式虽然便利,但是过于复杂的逻辑会让模板过重且难以维护。vue提供了计算属性 computed,以便我们处理复杂的逻辑。
基础例子
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>计算属性</title>
<script src="https://cdn.staticfile.org/vue/2.6.0/vue.js"></script>
</head>
<body>
<div id="app">
<div>{{testComputed}}</div>
<!-- 结果为654321 -->
</div>
<script type="text/javascript">
new Vue({
el: '#app',
data:{
test: [1,2,3,4,5,6]
},
computed:{
testComputed(){
return this.test.reverse().join('')
}
}
})
</script>
</script>
</body>
</html>
到这里你可能会发现,使用computed和methods得到的结果是一致的。不过计算属性不同的是它基于响应式依赖进行缓存,也就是说只有在该计算属性的依赖发生改变时,计算属性才会重新求值。
从上面的例子,当我们多次访问testComputed时,计算属性会立即返回之前计算的结果,而不会再次进行计算,只有当test发生改变时,计算属性才会重新进行计算。相比使用methods,每次使用都会完整执行一次计算。
监听器
在实际业务场景中,我们常常有一些数据需要随着其他数据的变动而做出改变,vue提供了一种监听属性 watch 。监听属性适合用在异步或开销较大的操作。
下面是一个简单的示例
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>监听器</title>
<script src="https://cdn.staticfile.org/vue/2.6.0/vue.js"></script>
</head>
<body>
<div id="app">
<button @click="add()">testWatch+1</button>
</div>
<script type="text/javascript">
new Vue({
el: '#app',
data:{
testWatch: 0,
},
watch:{
testWatch:function(newValue,oldValue){
console.log(newValue,oldValue)
}
},
methods:{
add(){
this.testWatch++
}
}
})
</script>
</script>
</body>
</html>
点击按钮,可以看到打印的newValue和oldValue。
组件基础
个人认为,组件化是vue的重点也是特色所在,通过组件化,我们能够通过编写独立或可复用的组件完成一个大型的单页面应用,同时,组件化的页面更容易维护。
组件定义
基本语法为 Vue.component(tagName, options) ,其中tagName为组件名称,类比我们用的div,span,p等,options是一个对象。
全局注册组件
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>组件基础</title>
<script src="https://cdn.staticfile.org/vue/2.6.0/vue.js"></script>
</head>
<body>
<div id="app">
<first-component></first-component>
</div>
<script type="text/javascript">
Vue.component('first-component',{ //全局注册组件
data(){
return {
text: "我的第一个组件"
}
},
template: `<h1>{{text}}</h1>`
})
new Vue({
el: '#app' // 创建一个根实例
})
</script>
</script>
</body>
</html>
局部注册组件
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>组件基础</title>
<script src="https://cdn.staticfile.org/vue/2.6.0/vue.js"></script>
</head>
<body>
<div id="app">
<first-component></first-component>
</div>
<script type="text/javascript">
let component = {
data(){
return {
text: "我的第一个组件"
}
},
template: `<h1>{{text}}</h1>`
}
new Vue({
el: '#app', // 创建一个根实例
components:{
'first-component': component
}
})
</script>
</script>
</body>
</html>
需要注意的是,不论是全局注册组件还是局部注册组件,都应该创建一个Vue的根实例,同时在vue2,template之下只能有一个标签,否则会编译错误,可以使用一个div包裹在最外侧。
<!--错误的写法-->
<template>
<div></div>
<div></div>
</template>
<!--正确的写法-->
<template>
<div>
<div></div>
<div></div>
</div>
</template>
在组件中,data不再是一个对象,而是一个函数,每个组件实例可以维护一份被返回对象的独立的拷贝,也就是每个组件都能独立维护自己的data,提高了组件复用性。
组件复用
你可以将组件进行任意次数的复用
<div id="app">
<first-component></first-component>
<first-component></first-component>
<first-component></first-component>
</div>
正如上面所说,每个组件都会独立维护自己的data,这是因为每使用一次组件,就会重新创建一个新的实例。
组件传参
父组件向子组件传参
prop是子组件用来接收父组件传递数据的一个自定义属性。
<div id="app">
<child text="hello"></child>
</div>
<script type="text/javascript">
let component = {
props: ['text'],
template: `<h1>{{text}}</h1>`
}
new Vue({
el: '#app', // 创建一个根实例
components:{
'child': component
}
})
</script>
这个例子中注册了一个名为child的组件,父组件#father使用child子组件的text属性进行传值,然后子组件通过使用props中的text显示数据,和data使用方法基本一致。
props验证
为了让代码更加规范,我们通常需要给每个prop指定值的类型,此时我们可以以对象的形式列出prop,以键值对的形式指定prop名称和类型
Vue.component('prop',{
props: {
propA: String, //基础类型
propB: [String,Number], // 多个类型
propC: { //必填
type: String,
requires: true
},
propD: { //默认值
type: Number,
default: 10
},
propE: { //带默认值的对象
type: Object,
default: function(){ //对象或数组的默认值应该从工厂函数获取
return {text: 'hi'}
}
}
}
})
子组件向父组件传参
除了父组件向子组件传参,常常还会有子组件向父组件传参,在vue中提供了自定义事件,即我们可以通过v-on绑定自定义的事件,子组件通过$emit触发事件以达到传参的目的。
先上示例
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>组件传参</title>
<script src="https://cdn.staticfile.org/vue/2.6.0/vue.js"></script>
</head>
<body>
<div id="father">
<div>{{title}}</div>
<child @eventname="getValue"></child>
</div>
<script type="text/javascript">
let component = {
template: `<button @click="transfer()">参数传递</button>`,
methods: {
transfer(){
this.$emit("eventname","我是传递的参数")
}
}
}
new Vue({
el: '#father', // 创建一个根实例
data: {
title: '现在没有参数传递'
},
methods:{
getValue(e){
this.title = e
}
},
components:{
'child': component
}
})
</script>
</script>
</body>
</html>
在这个例子中,首先注册了一个局部组件,并在组件中写了一个按钮,通过点击按钮触发子组件内部事件eventname,同时传递参数;然后再看父组件,使用@(v-on的简写)监听子组件内部事件eventname,事件触发的同时触发getValue方法,需要注意的是,这里我们只写方法名,也就是不加括号,然后接收到参数后赋值给title。
插槽
自定义的组件作为一个标签被我们所使用,有时候我们需要在标签中添加数据或插入其他内容,这时候便会用到插槽。
<div id="father">
<child>我是插入插槽的内容</child>
</div>
<script type="text/javascript">
let component = {
template: `<div>letf<slot></slot>right</div>`
}
new Vue({
el: '#father', // 创建一个根实例
components:{
'child': component
}
})
</script>
这是一个插槽的写法
然后就是多个插槽,只需要给每个插槽命名,然后通过v-slot标签指定插槽即可,如果不指定则为default。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>插槽</title>
<script src="https://cdn.staticfile.org/vue/2.6.0/vue.js"></script>
</head>
<body>
<div id="father">
<child>
<template v-slot:top>我是插入top插槽的内容</template>
<template v-slot:bottom>我是插入bottom插槽的内容</template>
</child>
</div>
<script type="text/javascript">
let component = {
template: `<main><div>letf<slot name="top"></slot>right</div>
<div>letf<slot name="bottom"></slot>right</div></main>`
}
new Vue({
el: '#father', // 创建一个根实例
components:{
'child': component
}
})
</script>
</script>
</body>
</html>
注意 v-slot
只能添加在 <template>
上
当被提供的内容只有默认插槽时,组件的标签才可以被当作插槽的模板来使用。这样我们就可以把 v-slot
直接用在组件上:
<child v-slot:default="slotProps">
{{ slotProps.user.firstName }}
</child>
生命周期
每个Vue实例都会经过数据监听、模板编译、挂载、dom更新、销毁等过程。下图为官网提供的生命周期图例,可以在不断学习和使用中慢慢理解。
VueCLI
VueCLI简介
VueCLI是官方提供的一个脚手架,能够快速搭建起一个单页面应用(SPA)。
官网对于VueCLI的介绍
Vue CLI 是一个基于 Vue.js 进行快速开发的完整系统,提供:
-
通过 @vue/cli 实现的交互式的项目脚手架。
-
通过 @vue/cli + @vue/cli-service-global 实现的零配置原型开发。
-
一个运行时依赖 (@vue/cli-service),该依赖:
-
可升级;
-
基于 webpack 构建,并带有合理的默认配置;
-
可以通过项目内的配置文件进行配置;
-
可以通过插件进行扩展。
-
-
一个丰富的官方插件集合,集成了前端生态中最好的工具。
-
一套完全图形化的创建和管理 Vue.js 项目的用户界面。
Vue CLI 致力于将 Vue 生态中的工具基础标准化。它确保了各种构建工具能够基于智能的默认配置即可平稳衔接,这样你可以专注在撰写应用上,而不必花好几天去纠结配置的问题。与此同时,它也为每个工具提供了调整配置的灵活性,无需 eject。
使用VueCLI搭建Vue.js项目
由于安装脚手架需要使用到npm,在搭建项目之前需要确保安装node.js,这里就不做阐述了。
确保环境问题后,在控制台全局安装
npm install -g vue-cli //此方法安装的是2.x版本
npm install -g @vue/cli 此方法安装的是最新版
首先创建一个文件夹,然后从控制台进入该文件夹
例如我在d盘新建了一个firstvue
执行命令vue init webpack myfirstproject
其中myfirstproject是项目名称,可以根据自己的喜好,webpeck表示以webpack为模板生成项目。
接下来会让我们确认自己的项目名称,项目描述,作者,是否使用vue-router
,ESLint
等,可根据自己的需求进行修改,需要注意的是vue-router是构建单页面应用的关键,所以还是得选上,我这里直接一路回车了,然后就等待下载完成。
此时项目已经下载完成了,cd进入项目目录,运行npm run dev
,如果报错可能是未能加载项目所需的依赖,也就是node_modules里面的内容,这时候运行npm install
下载依赖,完成后重新运行即可。
浏览器地址栏输入该地址,看到如下界面,一个使用脚手架搭建的Vue.js项目就搭建完成了