vue入门学习(更新中)
一、Vue的安装及导入
此处引用一个大佬写的博客,内容非常详细,包括vue2.x以及vue3.x版本
Vue的三种安装方式
二、Vue的基本介绍
2.1、Vue的生命周期以及相关钩子函数
(1)什么是钩子函数?
钩子函数是在vue实例化后就已经定义完成的函数。
<script type="text/javascript">
var app = new Vue({
el:"#app",
// created就是一个钩子函数,在页面创建后执行
created() {
console.log("created...");
}
});
</script>
(2)什么是生命周期?
Vue的生命周期指的是Vue从被实例化到销毁的过程,且可以根据过程中执行的钩子函数将其拆解程四个部分:创建前/后,渲染(挂载)前/后,更新前/后,销毁前/后。
2.2、数据双向绑定
原理:
(1)什么是数据双向绑定?
首先先介绍一下数据单向绑定,数据单向绑定是指将Model绑定到View上,实现当Model更新时,做到View的更新,但是这种方式在View发生更新时,是无法去改变Model的值的。数据双向绑定将Model和View互相结合,做到了互相影响。
(2)如何做到数据双向绑定?(vue2.x)
Vue采用了数据劫持结合订阅者-发布者模式的方式以实现双向绑定。
针对一个js对象,利用Object.defineProperty方法进行数据劫持,重写属性的set和get方法。并且vue中的实例将引用到的数据作为一个依赖收集起来,当某一个属性发生变化即触发set函数时,通过依赖通知实例调用get方法重新渲染界面。
(3)vue双向绑定和js的单向数据流是否冲突?
三、Vue基本语法
3.1、循环语法v-for
3.1.1、遍历数组
基本用法:
<div id='app'>
<ul>
<li v-for="item in movies" :key="item"></li>
</ul>
</div>
<script type="text/javascript">
var app = new Vue({
el:"#app",
// created就是一个钩子函数,在页面创建后执行
data(){
return {
movies: [
"星际战警",
"复仇者联盟",
"流浪地球"
],
}
}
});
</script>
3.1.2、遍历对象
基本用法:
<div id='app'>
<ul>
<li v-for="(value,key,index) in movies" :key="item"></li>
</ul>
</div>
<script type="text/javascript">
var app = new Vue({
el:"#app",
// created就是一个钩子函数,在页面创建后执行
data(){
return {
movies: {
name: 'test',
height: '180',
age: 18,
}
}
}
});
</script>
3.1.3、key属性
什么是Key属性?Key属性的作用是什么?
Key属性是Vue中用于标识元素的一个属性。其通常和v-for共同使用,将v-for循环生成的元素进行唯一标识,并且在Vue的diff算法中,也涉及到了Key值。
如果在元素中使用v-for去进行循环遍历,那么最好添加key属性。这是Vue的特性决定的,Vue将元素的复用性当做其特性之一。
在下列例子中,如果不添加key属性,那么当两个模板切换时,Vue会对input元素进行复用,并且不会清空input中已经输入的内容。
<div id='app'>
<template v-if="showUsername">
<label>UserName</label>
<input placeholder="input the username"></input>
</template>
<template v-else>
<label>Email</label>
<input placeholder="input the email"></input>
</template>
</div>
<script type="text/javascript">
var app = new Vue({
el:"#app",
data(){
return {
msg: 'welcome to Vue',
showUsername: true,
}
}
});
</script>
3.2、Mustache
Mustache语法,即双大括号语法。我们可以通过该语法,将data或者computed中的属性,快速填充到html中
<div id='app'>
<p>{{ firstName}}-{{lastName}}</p>
</div>
<script type="text/javascript">
var app = new Vue({
el:"#app",
// created就是一个钩子函数,在页面创建后执行
data(){
return {
firstName: 'Kobe',
lastName: 'Bryant',
}
}
});
</script>
3.3、v-text
效果与Mustache语法类似,接收的值大多为string类型
基本用法:
<div id='app'>
<p v-text="title"></p>
</div>
<script type="text/javascript">
var app = new Vue({
el:"#app",
// created就是一个钩子函数,在页面创建后执行
data(){
return {
title: 'welcome to Vue',
}
}
});
</script>
3.4、v-html
v-html与v-text和Mustache语法类似,但v-html可以解析html元素
<div id='app'>
<p v-html="title"></p> // 等于<p><b>welcome to Vue</b></p>
</div>
<script type="text/javascript">
var app = new Vue({
el:"#app",
// created就是一个钩子函数,在页面创建后执行
data(){
return {
title: '<b>welcome to Vue</b>',
}
}
});
</script>
3.5、v-cloak
上述的mustache语法,在网速较慢的情况下,可能会出现闪烁问题,即显示Musache语法本身。使用v-cloak可以在mustache语法编译之前,将其样式设置为display:none
基础用法:
<div id='app'>
<p v-cloak>{{title}}</p>
</div>
<script type="text/javascript">
var app = new Vue({
el:"#app",
// created就是一个钩子函数,在页面创建后执行
data(){
return {
title: 'welcome to Vue',
}
}
});
</script>
<style>
[v-cloak]{
display: none !important
}
</style>
3.6、v-pre
v-pre用于跳过该元素和其子元素的编译过程,用于显示原本的Mustache语法
基本用法:
<div id='app'>
<p>{{title}}</p> // welcome to Vue
<p v-pre>{{title}}</p> // {{title}}
</div>
<script type="text/javascript">
var app = new Vue({
el:"#app",
// created就是一个钩子函数,在页面创建后执行
data(){
return {
title: 'welcome to Vue',
}
}
});
</script>
3.7、v-once
某些情况下,我们可能希望某个元素不会随着数据的变化而发生变化,那么v-once就可以达到效果。
基础用法:
<div id='app'>
<div v-once>{{title}}</div>
</div>
<script type="text/javascript">
var app = new Vue({
el:"#app",
// created就是一个钩子函数,在页面创建后执行
data(){
return {
title: 'hello world'
}
}
});
</script>
3.8、v-bind
3.8.1、v-bind基础
v-bind,顾名思义,就是绑定的意思。基础用法中,将data中的msg和title属性绑定。
基础用法:
<div id='app'>
<span v-bind:title="msg">hello</span>
</div>
<script type="text/javascript">
var app = new Vue({
el:"#app",
data(){
return {
msg: 'welcome to Vue',
}
}
});
</script>
3.8.2、v-bind语法糖
v-bind的语法糖即“:”
基本用法:
// 与结果与8.1基本用法一致
<div id='app'>
<span :title="msg">hello</span>
</div>
<script type="text/javascript">
var app = new Vue({
el:"#app",
data(){
return {
msg: 'welcome to Vue',
}
}
});
</script>
3.8.3、v-bind绑定class
在写代码时,我们经常会遇到一种情况,我们需要根据某个属性动态给某个元素添加样式。比如:
点击标签后,字体为红色
未被点击的标签,字体为黑色
绑定class可以使用两种数据类型,对应两种语法
对象语法
数组语法
3.8.4、对象语法
<div id='app'>
<span :title="msg" :class="{'active':isActive}">hello</span>
</div>
<script type="text/javascript">
var app = new Vue({
el:"#app",
data(){
return {
msg: 'welcome to Vue',
isActive: false,
}
}
});
</script>
<style>
.active{
color:red;
}
</style>
3.8.5、数组语法
<div id='app'>
<span :title="msg" :class="['active']">hello</span>
// 可以和普通的类同时存在,此时title拥有title/active两个类属性
<span :class="['active']" class="title">title</span>
</div>
<script type="text/javascript">
var app = new Vue({
el:"#app",
data(){
return {
msg: 'welcome to Vue',
}
}
});
</script>
<style>
.active{
color:red;
}
</style>
3.8.6、v-bind绑定style
使用v-bind动态绑定style样式跟绑定class类似,同样有对象语法和数组语法
注意点:样式的属性名需要使用驼峰进行命名,如果使用横杆,需要使用引号包裹成字符串
<div id='app'>
// 数组语法
<span :title="msg" :style="[s1,s2]">hello</span>
// 对象语法
<span :style="{color: 'red', fontSize: '16px'}">title</span>
</div>
<script type="text/javascript">
var app = new Vue({
el:"#app",
data(){
return {
msg: 'welcome to Vue',
s1: { color: 'red'},
s2: { fontSize: '16px'},
}
}
});
</script>
<style>
.active{
color:red;
}
</style>
3.8.6、应用案例
v-bind结合v-on实现列表点击后,字体变红:
<div id='app'>
<ul>
<li
v-for="(movie, index) in movies"
@click="itemClick(movie,index)"
:class="{'clicked':index===selectedIndex}"
>{{movie}}</li>
</ul>
</div>
<script type="text/javascript">
var app = new Vue({
el:"#app",
// created就是一个钩子函数,在页面创建后执行
data(){
return {
movies: ["星际战警", "",""],
selectedIndex: 0,
}
},
methods: {
itemClick(movie,index){
this.selectdeIndex = index;
}
},
});
</script>
<style>
.clicked{
color: red
}
</style>
3.9、v-on
v-on可以用于监听Dom元素事件,并且将方法绑定到事件上。
<div id='app'>
<button v-on:click="count += 1">Add 1</button>
// 语法糖
<button @click="count += 1">Add 1</button>
<span>button has been clicked {{count}} times</span>
</div>
<script type="text/javascript">
var app = new Vue({
el:"#app",
data(){
return {
count: 0,
}
}
});
</script>
3.10、条件渲染
3.10.1、v-if
可以通过判断v-if中的值,来控制元素是否渲染,同时可以搭配v-else以及v-else-if使用
<div id='app'>
<span :title="msg" v-if="hidden">hello</span>
<span v-else> sorry, some errors hadden</span>
</div>
<script type="text/javascript">
var app = new Vue({
el:"#app",
data(){
return {
msg: 'welcome to Vue',
hidden: true,
}
}
});
</script>
3.10.2、v-show
v-show同样根据传入的值来判断元素的显隐,但即使是隐藏,该元素也已经被渲染出来,v-show是通过设置display:none将其隐藏。
<div id='app'>
<span :title="msg" v-show="hidden">hello</span>
</div>
<script type="text/javascript">
var app = new Vue({
el:"#app",
data(){
return {
msg: 'welcome to Vue',
hidden: false,
}
}
});
</script>
3.10.3、区别
v-if是真正的条件渲染,且它是惰性的。如果在页面初始化时,条件为false,那么该元素不会被进行渲
染。并且,在条件进行变化时,该元素会进行反复的销毁和创建。
v-show的判断,只是对其display样式的调整,无论条件如何,都会在页面初始化时进行元素的渲染。
如果在页面中,该元素判断条件不会进行相对频繁的切换,那么可以使用v-if去控制,反之推荐使用v-show。v-if相对于v-show,它拥有较低的初始化渲染开销,但是在后续渲染开销中较大。
3.11、数据双向绑定(v-model)
3.11.1、基础用法
v-model是Vue中用于数据双向绑定的工具,可以做到在数据变化时,页面同时变化或者在页面变化时,数据同时变化。
v-model一般用于绑定输入框(input)多行文本域(textarea)单选框(radio)复选框(CheckBox)以及下拉选择列表(select)
input:绑定字符串
textarea:绑定字符串
radio:绑定字符串
CheckBox:只有一个复选框,绑定布尔类型,多个复选框时绑定数组
Select:单选时,绑定字符串,多选时绑定数组
<div id='app'>
// 文本框
<input v-model="input"></input>
<label>{{input}}</label>
// 多行文本
<input type='textarea' v-model="textarea"></input>
<label>{{textarea}}</label>
// 单选框
<input type='radio' value="单选" v-model="radio"></input>
<label>{{radio}}</label>
// 单个复选框
<input type='checkbox' v-model="singleCheckBox"></input>
<label>{{singleCheckBox}}</label>
// 多个复选框
<input type='checkbox' value="one" v-model="singleCheckBox"></input>
<input type='checkbox' value="two" v-model="singleCheckBox"></input>
<input type='checkbox' value="three" v-model="singleCheckBox"></input>
<label>{{singleCheckBox}}</label>
</div>
<script type="text/javascript">
var app = new Vue({
el:"#app",
data(){
return {
textarea: '',
input: '',
singleCheckBox: false,
multipleCheckBox: [],
radio: ''
}
}
});
</script>
3.11.2、进阶用法(初学可以忽略)
v-model实际上,是v-bind:value和@input两个语法组合的语法糖,那么就理应可以应用于自定义组件上。
如果想要在自定义组件中使用v-model,需要在子组件的props中定义value用于接收父组件传入的值,并且在value的值发生变化时,提交input事件。
父组件:
<template>
<div>
<custom-obj v-model="customData"></custom-obj>
</div>
</template>
<script>
import customObj from './customObj'
export defautl {
components: {
customObj,
}
data(){
customData: 'test',
}
}
</script>
子组件:
<template>
<div>
<span>父组件输入:</span>
<input :value="value" @input="valueChange"></input>
</div>
</template>
<script>
export defautl {
name: 'customObj',
props: {
value: {
type: String,
default: '',
}
},
methods: {
valueChange(e){
this.$emit("input",e.target.value)
}
}
}
</script>
3.12、基础路由跳转
3.12.1、标签跳转(router-link)
<template>
<div>
<router-link :to="{path: '/home'}">
跳转首页
</router-link>
// 要使用name跳转,需要在路由中配置name属性
<router-link :to="{name: 'home'}">
跳转首页
</router-link>
</div>
</template>
<script>
export defautl {
methods: {
}
}
</script>
3.12.2、this.$router.push
<template>
<div>
<button @click="gotoHome">跳转首页</button>
</div>
</template>
<script>
export defautl {
methods: {
gotoHome(){
this.$router.push("/home")
// 多个参数
// this.$router.push({path: 'home',params: {id: '1'}, query: {queryId: '2'}})
}
}
}
</script>
3.12.3、this.$router.replace
与push不同的是,push会向history栈中添加一个新的路由记录,但是replace会将当前路由在栈中进行替换。这就导致了,使用push的路由,可以使用回退按钮返回,但replace不行。
<template>
<div>
<button @click="gotoHome">跳转首页</button>
</div>
</template>
<script>
export defautl {
methods: {
gotoHome(){
this.$router.replace("/home")
// 多个参数
// this.$router.replace({path: 'home',params: {id: '1'}, query: {queryId: '2'}})
}
}
}
</script>
四、Vue其他方法
4.1、计算属性(computed)
什么是计算属性?
计算属性就跟它的名字一样,他是可以经过计算的属性。以方法名作为属性,在方法内部进行简单的逻辑运算后,将结果作为属性值返回并且作为缓存存储,不需要进行重复计算,并且在依赖属性发生变化时,计算属性也会同时进行更新。
示例:
<div id='app'>
<label>{{message}}</label>
<label>{{reserveMessage}}</label>
</div>
<script type="text/javascript">
var app = new Vue({
el:"#app",
data(){
return {
message: 'hello',
}
},
computed: {
reserveMessage(){
// 当message发生变化时,返回值也会更新
return this.message.split("").reserve().join()
}
}
});
</script>
4.2、监听(watch)
watch可以用于监听组件中属性的变化,并且执行回调函数。
<div id='app'>
<label>{{message}}</label>
<label>{{reserveMessage}}</label>
</div>
<script type="text/javascript">
var app = new Vue({
el:"#app",
data(){
return {
message: 'hello',
}
},
watch: {
message: {
deep: true,
immediate: true,
handler(newValue, oldValue){
console.log("newValue:",newValue)
}
}
}
});
</script>
4.3、混入(mixins)
当项目中有抽离出来的公共部分的js代码,并且需要在某一个组件中引入时,就可以使用mixins进行混入。
混入后的代码,其所有属性及方法等,效果与直接写入组件中相同,但如果存在方法名或者属性重复,那么以组件中已存在的为优先。
// minxins混入文件
export default{
name: 'testMinxins',
data(){
return {
testInfo: 'mixins'
}
}
}
<div id='app'>
<label>{{message}}</label>
<label>{{reserveMessage}}</label>
</div>
<script type="text/javascript">
import testMinxins from './testMixins'
var app = new Vue({
el:"#app",
data(){
return {
}
},
mixins: [testMinxins]
});
// 效果与混入相同
var app = new Vue({
el:"#app",
data(){
return {
testInfo: 'mixins'
}
},
});
</script>
五、Vue组件
5.1、组件基础用法
组件的作用,在于将不同的界面进行拆分开发,同时能够进行公共组件的开发,提高代码的可复用性。但是在使用组件时,开发者需要先在父组件中进行引入并且注册。
组件的基础用法:
<div id='app'>
<child-btn></child-btn>
</div>
<script type="text/javascript">
const childBtn= {
//定义组件的模版
template:`<button @click='num++'>你点击了{{num}}次</button>`,
//定义组件中使用到的数据属性
data(){
return {
num:0
}
}
};
// 效果与混入相同
var app = new Vue({
el:"#app",
// 组件注册
components: {
childBtn
}
});
</script>
5.2、父组件给子组件传值
由于父组件和子组件,严格来说是属于两个组件,那么这两个组件之间的数据就是不共通的,即子组件无法直接使用父组件的数据。那么当子组件需要使用父组件的数据时,就需要父组件进行数据传入。
子组件使用props中的属性值进行接收,并且指定属性的类型以及默认值。父组件通过在标签内添加属性值进行传值
<div id='app'>
<movie-intro :movieName='movieName' :score="score"></movie-intro>
</div>
<script type="text/javascript">
const movieIntro= {
//定义组件的模版
template:`<p>{{movieName}}--{{score}}</p>`,
//定义组件中使用到的数据属性
data(){
return {
num:0
}
},
props: {
movieName: '',
score: {
type: Number,
default: 0
},
}
};
// 效果与混入相同
var app = new Vue({
el:"#app",
// 组件注册
components: {
movieIntro
},
data(){
return {
movieName: 'titanic',
score: 9.8,
}
}
});
</script>
5.3、子组件给父组件传值
在项目的开发中,绝大多数人都会遇到子组件需要修改父组件数据的情况,但是Vue是不允许子组件直接修改父组件的数据,所以子组件就需要通过提交事件($emit)的方法,去修改父组件的数据。
<div id='app'>
<movie-intro :movieName='movieName' :score="score" @scoreAdd="scoreAdd"></movie-intro>
</div>
<script type="text/javascript">
const movieIntro= {
//定义组件的模版
template:`<p>{{movieName}}--{{score}}</p>
<button @click="scoreAdd">得分+1</button>`,
//定义组件中使用到的数据属性
data(){
return {
num:0
}
},
props: {
movieName: '',
score: {
type: Number,
default: 0
},
},
methods: {
scoreAdd(){
// 当绑定时使用了.sync修饰符时,可以使用update:xxx进行数据更新
// this.$emit("update:score", score + 1)
this.$emit("scoreAdd", score + 1)
}
}
};
// 效果与混入相同
var app = new Vue({
el:"#app",
// 组件注册
components: {
movieIntro
},
data(){
return {
movieName: 'titanic',
score: 9.8,
}
},
methods: {
scoreAdd(score){
this.score = score
}
}
});
</script>
5.4、其他传值方法
已经写过一篇Vue的传值方法,所以这里就不作赘述了,需要了解的可以直接链接跳转。
六、axios
6.1、概述
简单来说,axios是一个基于primose的http库,可以在浏览器以及node.js中直接运行,作为异步请求的载体。
6.2、方法
6.2.1、axios.create(常用)
该方法一般常用于项目中进行初始化的常规配置。
用法:
const request = axios.create({
baseURL: '',
withCredentials: true,
timeout: 30000,
})
// 定义接口时
export function getPage(data,params){
return request({
url: '/api/getPage', // 接口地址 baseURL + url即为完整地址
method: 'post', // get/delete/put均可
data,
params,
responseType: 'json' // 默认为json,如果是二进制流,可以设置blob
})
}
6.2.2、axios.post(get/delete/put)
直接使用axios,不经过通用配置。
用法:
axios.post(
url,
data,
params
).then(res => {
console.log(res)
}.catch((err) => {
console.log(err)
}