2、Vue 开发基础(一)
2.1、Vue 实例
在 Vue 项目中,每个 Vue 应用都是通过 Vue 构造器创建新的 Vue 实例开始的。
2.1.1、创建 Vue 实例
<script>
new Vue({
el: '#root',
data: {
name: '潘嘉龙'
}
})
</script>
Vue 实例配置选项
选项 | 说明 |
---|---|
data | Vue 实例数据对象 |
methods | 定义 Vue 实例中方法 |
components | 定义子组件 |
computed | 计算属性 |
filters | 过滤器 |
el | 唯一根标签 |
watch | 监听数据变化 |
2.1.2、el 唯一根标签
在创建 Vue 实例时,el 表示唯一根标签,class 或 id 选择器可用来将页面结构与 Vue 实例对象 vm 中的 el 绑定。
<div id='root'>
{{name}}
</div>
<script>
new Vue({
el: '#root', // 通过 el 与 div 元素绑定
data: {
name: '潘嘉龙'
}
})
</script>
2.1.3、data 初始数据
Vue 实例的数据对象为 data,Vue 会将 data 的属性转换为 getters、setter,从而让 data 的属性能够响应数据变化。
<div id='root'>
{{name}}
</div>
<script>
var vm = new Vue({
el: '#root', // 通过 el 与 div 元素绑定
data: {
name: '潘嘉龙'
}
})
console.log(vm.$data.name);
console.log(vm.name);
Vue 实例创建之后,可以通过 vm. d a t a 访 问 原 始 数 据 对 象 。 V u e 实 例 也 代 理 了 d a t a 对 象 上 所 有 的 属 性 , 因 此 访 问 v m . d a t a 相 当 于 访 问 v m . data 访问原始数据对象。Vue 实例也代理了 data 对象上所有的属性,因此访问 vm.data 相当于访问 vm. data访问原始数据对象。Vue实例也代理了data对象上所有的属性,因此访问vm.data相当于访问vm.data.name
2.1.4、methods 定义方法
methods 属性用来定义方法,通过 Vue 实例可以直接访问这些方法。
在定义的方法中,this 指向 Vue 实例本身。
定义在 methods 属性中的方法可以作为页面中的事件处理方法使用,当事件触发后,执行相应的事件处理方法。
<div id='root'>
<!-- 为 button 按钮绑定 click 事件 -->
<button @click="showInfo">请单击</button>
<p>{{msg}}</p>
</div>
<script>
new Vue({
el: '#root',
data: {
name: '潘嘉龙',
msg : ''
},
methods: {
// 定义事件处理方法 showInfo
showInfo(){
this.msg = "触发单击事件"
}
}
})
</script>
2.1.5、computed 计算属性
Vue 提供了一种更通用的方式来观察和响应 Vue 实例上的数据变动,当有一些数据需要随着其他数据变动而变动时,就需要使用 computed 计算属性。
html
<div id='root'>
<p>总价格:{{totalPrice}}</p>
<p>单价:{{price}}</p>
<p>数量:{{num}}</p>
<div>
<button @click="num == 0 ? 0 : num--">减少数量</button>
<button @click="num++">增加数量</button>
</div>
</div>
js
new Vue({
el: '#root',
data: {
name: '潘嘉龙',
price: 20,
num: 0
},
computed:{
// 总价格 totalPrice
totalPrice(){
return this.price * this.num
}
}
})
2.1.6、状态监听
Vue 中的事件处理方法是根据用户所需自行定义的,它可以通过单击事件、键盘事件等触发条件来触发,但不能自动监听当前 Vue 对象的状态变化。
html
<div id='root'>
<!-- input 中的 v-model 用于在表单控件元素上创建双向数据绑定 -->
<input type="text" v-model="cityName" name="" id="">
</div>
js
new Vue({
el: '#root',
data: {
cityName: '潘嘉龙'
},
// 使用 watch 监听 cityName 变化
watch:{
cityName(newName, oldName){
console.log(newNamem, oldName);
}
}
})
2.1.7、filters 过滤器
在前端页面开发中,通过数据绑定可以将 data 数据绑定到页面中,页面中的数据经过逻辑层处理后展示最终的结果。
数据的变化除了在 Vue 逻辑层进行操作外,还可以通过过滤器来实现。
过滤器有两种使用方式。
2.1.7.1、在插值表达式中使用过滤器
通过 “{{data}}” 语法,可以将 data 中的数据插入页面中,该语法就是插值表达式。
在插值表达式中还可以使用过滤器来对数据进行处理,语法为 “{{data | filter}}”
<div id='root'>
<div>{{message | toUpcase}}</div>
</div>
<script>
new Vue({
el: '#root',
data: {
name: '潘嘉龙',
message: 'helloworld'
},
filters:{
// 将 helloworld 转换为 HELLOWORLD
toUpcase(value){
return value ? value.toUpperCase() :''
}
}
})
</script>
2.1.7.2、在 v-bind 属性绑定中使用过滤器
v-bind 用于属性绑定,如 “v-bind:id=‘data’” 表示绑定 id 属性,值为 data。在 data后面可以加过滤器,语法为 “data | filter”。
<div id='root'>
<div v-bind:id="dataId | formatId">helloworld</div>
</div>
<script>
new Vue({
el: '#root',
data: {
name: '潘嘉龙',
dataId: 'dff1'
},
filters: {
formatId(value){
// 字符串处理
return value ? value.charAt(1) + value.indexOf('d') : ''
}
}
})
</script>
2.2、Vue 数据绑定
Vue 中的数据绑定功能极大地提高了开发效率。
2.2.1、绑定样式
Vue 提供了样式绑定功能,可以通过绑定内联样式和绑定样式类这两种方式来实现。
2.2.1.1、绑定内联样式
在 Vue 实例中定义的初始数据 data,可以通过 v-bind 将样式数据绑定给 DOM 元素。
<div id='root'>
<!-- 绑定样式属性值 -->
<div v-bind:style="{backgroundColor: pink,width:width, height:height}">
<!-- 绑定样式对象 -->
<div v-bind:style="myDiv"></div>
</div>
</div>
<script>
new Vue({
el: '#root',
data: {
name: '潘嘉龙',
myDiv:{backgroundColor: 'red',width: '100px', height: '100px'},
pink: 'pink',
width: '100%',
height: '200px'
}
})
</script>
2.2.1.2、绑定样式类
样式类即以类名定义元素的样式。
html
<div id='root'>
<div v-bind:class="{box}">我是box
<div v-bind:class="{inner}">我是inner1</div>
<div v-bind:class="{inner}">我是inner2</div>
</div>
</div>
<script>
new Vue({
el: '#root',
data: {
name: '潘嘉龙',
box: 'box',
inner : 'inner'
}
})
</script>
css
.box{
background-color: pink;
width: 100%;
height: 200px;
}
.inner{
background-color:red;
width: 100px;
height: 50px;
border: 2px solid white;
}
2.2.2、内置指令
Vue 为开发者提供了内置指令,通过内置指令就可以用简洁的代码实现复杂的功能。
常用的内置指令
指令 | 说明 |
---|---|
v-model | 双向数据绑定 |
v-no | 监听事件 |
v-html | 单向数据绑定 |
v-text | 插入文本内容 |
v-html | 插入包含HTML饿内容 |
v-for | 列表渲染 |
v-if | 条件渲染 |
v-show | 显示隐藏 |
Vue 的内置指令书写规则以 v 开头,后缀用来区分指令的功能,且通过短横线连接。
指令必须写在 DOM 元素上。
内置指令还可以使用简写方式,v-on:click 简写为 @click,v-bind:class 简写为 :class。
2.2.2.1、v-model
v-model 主要实现数据双向绑定通常用在表单元素上,例如 input、textarea、select等。
<div id='root'>
<input type="text" v-model="msg" name="" id="">
</div>
<script>
new Vue({
el: '#root',
data: {
msg: '潘嘉龙'
}
})
</script>
2.2.2.2、v-text
v-text 是在 DOM 元素内部插入文本内容。
<div id='root'>
<p v-text="msg"></p>
</div>
<script>
new Vue({
el: '#root',
data: {
msg: '潘嘉龙'
}
})
</script>
2.2.2.3、v-html
v-html 是在 DOM 元素内容插入 HTML 标签内容。
<div id='root'>
<div v-html='name'></div>
</div>
<script>
new Vue({
el: '#root',
data: {
name: '<h1>我是v-html</h1>'
}
})
</script>
2.2.2.4、v-bind
v-bind 可以实现单向数据绑定
<div id='root'>
<input type="text" v-bind:value="msg" name="" id="">
</div>
<script>
new Vue({
el: '#root',
data: {
msg: '潘嘉龙',
}
})
</script>
2.2.2.5、v-on
v-no 是事件监听指令,直接与事件类型配合使用。
<div id='root'>
<p>{{msg}}</p>
<button v-on:click='showInfo'>请单击</button>
</div>
<script>
new Vue({
el: '#root',
data: {
msg: '潘嘉龙'
},
methods: {
showInfo(){
this.msg = '我是v-on指令'
}
}
})
</script>
2.2.2.6、v-for
v-for 可以实现页面列表渲染,常用来循环数组。
<div id='root'>
<div v-for='(item, key) in list' data-id='key'>
索引是:{{key}},元素内容是:{{item}}
</div>
</div>
<script>
new Vue({
el: '#root',
data: {
name: '潘嘉龙',
list: [1,2,3]
}
})
</script>
2.2.2.7、v-if 和 v-show
v-if 用来控制元素显示或隐藏,属性为布尔值。
v-show 可以实现与 v-if 同样的效果,但是 v-show 是操作元素的 display 属性,而 v-if 会对元素进行删除和重新创建,所以 v-if 在性能上不如 v-show。
<div id='root'>
<div v-if='isShow' style="background-color:#ccc;">我是 v-if</div>
<button @click='isShow = !isShow'>显示 / 隐藏</button>
</div>
<script>
new Vue({
el: '#root',
data: {
name: '潘嘉龙',
isShow: true
}
})
</script>
2.3、Vue 事件
在前端开发中,开发人员经常需要为元素绑定事件,为此,Vue 提供了非常灵活的事件绑定机制。
2.3.1、事件监听
在 Vue 中可以使用内置指令 v-on 监听 DOM 事件,并在触发时运行一些 Javascript 代码,或绑定事件处理方法。
2.3.1.1、在触发事件时执行 JavaScript 代码
<div id='root'>
<button v-on:click='count += Math.random()'>随机数</button>
<p>自动生成的随机数是 {{count}}</p>
</div>
<script>
new Vue({
el: '#root',
data: {
name: '潘嘉龙',
count: 0
}
})
</script>
2.3.1.2、使用按键修饰符监听按键
在监听键盘事件时,经常需要检查常见的键值。
<div id='root'>
<input type="text" v-on:keyup.enter="submit" name="" id="">
</div>
<script>
new Vue({
el: '#root',
data: {
name: '潘嘉龙'
},
methods: {
submit(){
console.log("表单提交");
}
}
})
</script>
2.3.2、事件修饰符
事件修饰符是自定义事件行为,配合 v-on 指令来使用,用 “.” 符号连接。
常用事件修饰符
修饰符 | 说明 |
---|---|
.stop | 阻止事件冒泡 |
.prevent | 阻止默认事件行为 |
.capture | 事件捕获 |
.self | 将事件绑定到自身,只要自身才能触发 |
.once | 事件只触发一次 |
2.3.2.1、.stop 阻止事件冒泡
默认的事件传递方式是冒泡,所以同一事件类型会在元素内部和外部触发,有可能会造成事件的错误触发,所以就需要使用 .stop 修饰符阻止事件冒泡行为。
<div id='root'>
<div v-on:click='doParent'>
<button v-on:click='doThis'>事件冒泡</button>
<button v-on:click.stop='doThis'>阻止事件冒泡</button>
</div>
</div>
<script>
new Vue({
el: '#root',
data: {
name: '潘嘉龙'
},
methods: {
doParent(){
console.log('我是父元素单击事件');
},
doThis(){
console.log('我是被单击元素事件');
}
}
})
</script>
2.3.2.2、.prevent 阻止默认事件行为
HTML 标签具有自身特性,例如, 标签被单击时会自动跳转。
在实际开发中,如果标签的默认行为与事件发生冲突,此时可以使用 .prevent 修饰符来阻止 标签的默认行为。
<div id='root'>
<a href="https://www.baidu.com" v-on:click.prevent>阻止默认行为</a>
<a href="https://www.baidu.com">不阻止默认行为</a>
</div>
<script>
new Vue({
el: '#root',
data: {
name: '潘嘉龙'
}
})
</script>
2.3.2.3、.capture 事件捕获
事件捕获的执行顺序是由外部结构向内部结构执行,与事件冒泡的顺序相反。
<div id='root'>
<div v-on:click.capture='doParent'>
<button v-on:click='doThis'>事件捕获</button>
</div>
</div>
<script>
new Vue({
el: '#root',
data: {
name: '潘嘉龙'
},
methods: {
doParent(){
console.log('我是父元素的单击事件');
},
doThis(){
console.log('我是当前元素的单击事件');
}
},
})
</script>
2.3.2.4、.self 自身触发
事件修饰符 .self 用来实现只要 DOM 元素本身会触发事件。
<div id='root'>
<div v-on:click.self='doParent' class="Odiv1">a
<div class="Odiv2" v-on:click='doThis'>b</div>
</div>
<div v-on:click='doParent' class="Odiv1">c
<div class="Odiv2" v-on:click.self='doThis'>d</div>
</div>
</div>
<script>
new Vue({
el: '#root',
data: {
name: '潘嘉龙'
},
methods: {
doParent(){
console.log('我是父元素的单击事件');
},
doThis(){
console.log('我是当前元素的单击事件');
}
},
})
</script>
2.3.2.5、.once 只触发一次
事件修饰符 .once 用于阻止事件多次触发,只触发一次。
<div id='root'>
<button v-on:click='doThis'>只执行一次</button>
</div>
<script>
new Vue({
el: '#root',
data: {
name: '潘嘉龙'
},
methods: {
doThis(){
console.log('我是当前元素的单击事件且只执行一次');
}
},
})
</script>
注意
事件修饰符可以控制事件安装一定规则触发,在使用修饰符时,书写的顺序很重要。
例如,v-on:click.prevent.self 会阻止所有的单击,而 v-on:click.self.prevent 只会阻止对元素本身的单击。
2.4、Vue 组件
Vue 可以进行组件化开发,组件是 Vue 的基本结构单元,开发过程中使用起来非常方便灵活,只需要按照 Vue 规范定义组件,将组件渲染到页面即可。
2.4.1、什么是组件
在 Vue 中,组件是构成页面中独立结构单元,能够减少重复代码的编写,提高开发效率,降低代码之间的耦合程度,使项目更易维护和管理。
组件主要以页面结构的形式存在,不同组件也具有基本交互功能,根据业务逻辑实现复杂的项目功能。
<div id='root'>
<my-component></my-component>
<my-component></my-component>
<my-component></my-component>
</div>
<script>
Vue.component('my-component', {
data () {
return {
count: 0
}
},
template: '<button v-on:click="count++">被单击 {{count}}</button>'
})
new Vue({
el: '#root',
data: {
name: '潘嘉龙'
}
})
</script>
2.4.2、局部注册组件
可以通过 Vue 实例的 components 属性来实现。
<div id='root'>
<my-component></my-component>
</div>
<script>
var com1 = {
template: '<p>我是 vm 实例中的局部组件</p>'
}
new Vue({
el: '#root',
data: {
name: '潘嘉龙'
},
components: { myComponent: com1}
})
</script>
2.4.3、template 模板
模板代码是可以写在 HTML 结构中,这样就有利于在编辑器中显示代码提示和高亮显示,不仅改善了开发体验,也提高了开发效率。
Vue 提高了 标签来定义结构的模板,可以在该标签中书写 HTML 代码,然后通过 id 值绑定到组件内的 template 属性上。
<div id='root'>
<p>{{title}}</p>
<my-component></my-component>
</div>
<template id="tmp1">
<p>{{title}}</p>
</template>
<script>
Vue.component("my-component",{
template:'#tmp1',
data () {
return {
title: '我是组件内的 title'
}
}
})
new Vue({
el: '#root',
data: {
name: '潘嘉龙',
title: '我是 vm 实例的 title'
}
})
</script>
注意
在全局注册组件时,组件接收的配置选项,与创建 Vue 实例的配置选项基本相同,都可以使用 methods 来定义方法。
组件内部具有自己的独立作用域,不能直接被外部访问。
2.4.4、组件之间的数据传递
在 Vue 中,组件实例具有局部作用域,组件之间的数据传递需要借助一些工具(如 props 属性)来实现父组件向子组件传递数据信息。
在 Vue 中,数据传递主要通过 props 属性和 $emit 方式来实现。
2.4.4.1、props 传值
props 即道具,用来接受父组件定义的数据,其值为数组,数组中是父组件传递的数据信息。
<div id='root'>
<my-parent name="title"></my-parent>
</div>
<script>
Vue.component('my-parent', {
props:['name'],
template: '<div>我是父组件 {{name}}</div>',
})
new Vue({
el: '#root',
data: {
name: '潘嘉龙'
}
})
</script>
注意
props 是以从上到下的单向数据流传递,且父级组件的 props 更新会向下流动到子组件中,但是反过来不行。
2.4.4.2、$emit 传值
$emit 能够将子组件中的值传递到父组件中去。
$emit 可以触发父组件中定义的事件,子组件的数据信息通过传递参数的方式完成。
<div id='root'>
<parent></parent>
</div>
<template id="child">
<div>
<button @click='click'>Send</button>
<input type="text" v-model='message' name="" id="">
</div>
</template>
<script>
// child 组件
Vue.component('child', {
template: '#child',
data() {
return {
message: '子组件的消息'
}
},
methods: {
click() {
this.$emit('childFn', this.message)
}
}
})
Vue.component('parent', {
template: '<div><child @childFn="transContent"></child>子组件传来的值:{{message}}</div>',
data() {
return {
message: ''
}
},
methods: {
transContent(payload) {
this.message = payload
}
}
})
new Vue({
el: '#root',
data: {
name: '潘嘉龙',
},
})
</script>
2.5、生命周期
Vue 实例为生命周期提供了回调函数,用来在特定的情况下触发,贯穿了 Vue 实例化的整个过程,这个用户在不同阶段添加自己的代码提供了机会。
每个 Vue 实例在被创建时都要经过一系列的初始化过程,如初始数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。
2.5.1、钩子函数
钩子函数用来描述 Vue 实例从创建到销毁的整个生命周期。
生命周期的钩子函数
钩子 | 说明 |
---|---|
beforeCreate | 创建实例对象之前执行 |
created | 创建实例对象之后执行 |
beforeMount | 页面挂载成功之前执行 |
mounted | 页面挂载成功之后执行 |
beforeUpdate | 组件更新之前执行 |
updated | 组件更新之后执行 |
beforeDestroy | 实例销毁之前执行 |
destroyed | 实例销毁之后执行 |
2.5.2、实例创建
beforeCreate 和 created 钩子函数的使用。
<div id='root'>
{{msg}}
</div>
<script>
new Vue({
el: '#root',
data: {
msg: '潘嘉龙'
},
beforeCreate() {
console.log('实例创建之前');
console.log(this.$data.msg);
},
created () {
console.log('实例创建之后');
console.log(this.$data.msg);
}
})
</script>
2.5.3、页面挂载
Vue 实例创建后,如果挂载点 el 存在,就好进行页面挂载。
<div id='root'>
{{msg}}
</div>
<script>
new Vue({
el: '#root',
data: {
msg: '潘嘉龙'
},
beforeMount () {
console.log('挂载之前');
console.log(this.$el.innerHTML); // 通过 this.$el 获取 el 的 DOM 元素
},
mounted () {
console.log('挂载之后');
console.log(this.$el.innerHTML);
}
})
</script>
2.5.4、数据更新
Vue 实例挂载完成后,当数据发生变化时,会执行 beforeUpdate 和 updated 钩子函数。
<div id='root'>
<div v-if='isShow' ref="self">test</div>
<button @click='isShow=!isShow'>更新</button>
</div>
<script>
new Vue({
el: '#root',
data: {
isShow: true
},
beforeUpdate () {
console.log('更新之前');
console.log(this.$refs.self);
},
updated () {
console.log('更新之后');
console.log(this.$refs.self);
}
})
</script>
2.5.5、实例销毁
生命周期的最后阶段是实例的销毁,会执行 beforeDestroy 和 dstroyed 钩子函数。
<div id='root'>
<div ref='self'>test</div>
</div>
<script>
var vm = new Vue({
el: '#root',
data: {
msg: '潘嘉龙'
},
beforeDestroy() {
console.log('销毁之前');
console.log(this.$refs.self);
console.log(this.msg);
console.log(vm);
},
destroyed() {
console.log('销毁之后');
console.log(this.$refs.self);
console.log(this.msg);
console.log(vm);
},
})
</script>
传统方式编写应用
存在的问题:
1、依赖关系混乱,不好维护
2、代码复用率不高
组件的定义——实现应用中局部功能代码和资源的集合