本文目录:
- 1.安装
- 2.使用vue
- 3.创建vue实例
- 4.事件处理
- 5.基础指令
- 6.样式绑定
- 7.表单输入
- 8.什么是组件?
- 9.将组件分离出来-单文件组件
- 10.组件生命周期钩子函数
1.安装
首先创建一个项目目录,我这里创建一个vue-demo的目录,这个名字可以自定义,但是不要命名为vue 这样会冲突
我这里使用命令来创建,如果对命令不熟悉,可以直接在webstorm中创建
mkdir vue-demo
然后进入到vue-demo目录,如果使用webstorm创建的话就直接在webstrom中打开teminal,这样是默认进入vue-demo的
cd vue-demo
接下来初始化项目
npm init -y
最后使用npm 安装vue
npm install vue@2.5.16 --save
因为是小白嘛,为了防止意外bug的出现,安装的时候我们使用@锁定版本。
2.使用vue
vue是一个渐进式的框架,so,我们可以直接在页面中使用script引用vue的核心js文件,没错,不需要任何配置,就是这么简单!
<script src="node_modules/vue/dist/vue.js"></script>
3.创建vue实例
通过new Vue函数创建出一个新的Vue实例vm
let vm = new Vue()
可以在创建Vue实例的时候传入相应的选项
let vm = new Vue({
el: '#app' //id名为app的元素作为应用的根节点
})
console.log(vm.$el) //这里打印出相应的根节点
符号开头的,用来和用户自定义的属性区分开
初始化时传入的data属性,用来存放相关数据,并且这些数据是响应式的
let vm = new Vue({
el: '#app',
data: {
message: 'hello,nodeing',
username: 'xiaoqiang'
}
});
console.log(vm.$data.message) //hello,nodeing
console.log(vm.$data.username) //xiaoqiang
强调一点,vm代理了data的数据对象,效果如下
console.log(vm.$data.message === vm.message)//true
需要注意的是,只有初始化的时候,在选项data中存在的属性才是响应式的
例如,初始化的时候是这样的:
let vm = new Vue({
el: '#app',
data: {
message: 'hello,nodeing',
username: 'xiaoqiang'
}
});
其中,data里面并没有password属性,我们在浏览器中增加password属性,是看不到变化的。
4.事件处理
监听事件
使用v-on:事件名称 = '事件处理函数'的形式来监听事件,事件处理函数要写在methods后面的对象中
<div id="app">
<button v-on:click="say">按钮</button>
</div>
<script src="node_modules/vue/dist/vue.js"></script>
<script>
new Vue({
el:'#app',
data: {
message:'hello,world'
},
methods:{
say(){
alert(this.message)
}
}
})
</script>
</body>
</html>
如果事件处理函数需要传参数的话,可以写成这样:
<button v-on:click="say('hello')">按钮</button>
//实例中的写法是这样的
methods:{
say(msg){
alert(msg)
}
}
事件修饰符
事件修饰符是帮助我们去处理事件相关细节的,例如,防止事件冒泡、阻止系统默认行为等,以前我们需要使用event.stopPropagation()、event.preventDefault()去实现,在vue中有更简洁的使用方式,.stop、.prevent就可以搞定,这样在方法中就只需要关注业务逻辑,不需要去关注事件细节了
1 .stop修饰符,阻止事件冒泡
<div id="app">
<div id="box" v-on:click="out">
<div id="box-inner" v-on:click.stop="inner"></div>
</div>
</div>
2 .prevent 阻止默认行为
<a href="http://baidu.com" v-on:click.prevent>百度一下</a>
3 .capture 阻止事件捕获
<div id="app">
<div id="box" v-on:click.capture="out">
<div id="box-inner" v-on:click="inner"></div>
</div>
</div>
4 .self 事件源是自身的时候才触发
<div id="box" v-on:click.self="out">
<div id="box-inner" v-on:click="inner"></div>
</div>
5 .once 事件只触发一次
<div id="app">
<div id="box" v-on:click="out">
<div id="box-inner" v-on:click.once="inner"></div>
</div>
</div>
按键修饰符
- 1 .enter 回车键
- 2 .tab tab键盘
- 3 .delete (捕获“删除”和“退格”键)
- 4 .esc esc键
- 5 .space 空格
- 6 .up
- 7 .down
- 8 .left
- 9 .right
使用方法和事件修饰符一样:
<input type="text" v-on:keyup.enter="fn">
系统修饰符
- .ctrl
- .alt
- .shift
- .meta windows系统对应的是徽标键
使用方法也和事件修饰符一样:
<input type="button" value="点击" v-on:click.shift="fn">
5.基础指令
什么是指令
指令 (Directives) 是带有 v- 前缀的特殊特性,指令特性的值预期是单个 JavaScript 表达式,指令的职责是,当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM
指令,可以理解为一种特殊的属性,以v-开头
<p v-if="flag">hello nodeing</p>
上面代码中v-if就是一个指令,用来处理条件判断,根据表达式的值的真假条件渲染元素
常用的指令
1.v-text和v-html
v-text可以将数据文本渲染到标签中,需要注意的是,渲染出来的内容只是文本,并不会解析html标签
<p v-text="message"></p>
v-text的功能和下面这种形式一样
<p>{{message}}</p>
注意:v-text和{{}}还是有一点差异的,那就是当vue的实例还没有创建出来的时候,{{}}模板语法会显示为文本,所以总体v-text体验感更加的好
但是v-text会覆盖元素中原本的内容,插值表达式{{ }}只会替换自己的这个占位符,不会把整个元素内容替换。
v-html和v-text的区别是v-html渲染出来的内容,html标签是会被解析的,把上面代码中的v-text改写成v-html试试
<p v-text="message"></p>
<p >{{message}}</p>
<p v-html="message"></p>
v-text和v-html的区别和jQuery中的text()、html()的区别是类似的
2.v-show
v-show可以根据表达式的值切换css的display属性,决定内容是否显示,需要注意的是,v-show只是单纯的切换css的display属性,内容始终都会被创建出来的,和if条件渲染不同,if条件渲染是会销毁内容的
<p v-show="flag">{{message}}</p>
3.v-if、v-else、v-else-if
这几个指令和js语言中的if else类似
<p v-if="num >= 90">非常优秀: {{num}}</p>
<p v-else-if="num>=80">良好:{{num}}</p>
<p v-else-if="num>=70">中等:{{num}}</p>
<p v-else-if="num>=60">及格:{{num}}</p>
<p v-else>不及格:{{num}}</p>
4.v-for
v-for指令用来做循环渲染,需要使用item in items这种特殊的语法,items表示一个数据源数组,item表示每一个被循环出来的项
注意1: v-for是可以打印出数组元素的下标的,需要写成下面这样,第二个参数index就表示下标
<ul v-for="(item, index) in arr">
<li>{{item}}-{{index}}</li>
</ul>
注意2: 对象也是可以被循环的,使用方法和上面一样
<div v-for="(value, key) in object">
{{ key }}: {{ value }}
</div>
<!-- 支持第三个参数 索引 -->
<div v-for="(value, key, index) in object">
{{ index }}. {{ key }}: {{ value }}
</div>
注意3: 可以控制循环次数
<ul v-for="n in 10">
<li>{{n}}</li>
</ul>
注意4: 数组更新检测,要让数组更新后页面也跟着渲染,那么必须使用vue包含的一组观察数组的变异方法,例如,添加一个数据 必须使用push方法,如果使用this.arr[6] = 7 这种方法是不会触发页面更新的
let vm = new Vue({
el: '#app',
data: {
arr: [1, 2, 3, 4, 5, 6],
},
methods: {
fn() {
// this.arr[6] = 7; 使用这种方法添加元素,页面不会更新
this.arr.push(7)
console.log(this.arr)
}
}
});
同理,对数组的其他操作,也需要用相关方法,具体如下:
- push() //往数组最后添加一个元素,返回值是变化后的新数组
- pop() //删除数组最后的一个元素,返回值是删除掉的元素值
- shift() //删除数组的第一个元素
- unshift() //往数组的最前面添加一个元素
- splice() //第一个参数表示数组从下标几开始删除,第二参数代表删除几个元素,如果只写一个0,则默认为删除全部,从第三个参数开始,表示添加的元素
- sort() //排序,参数中需要传入排序规则(函数),如果不传,默认是字符编码进行排序。
升序:this.arr.sort((a,b)=>{return a>b})
降序:this.arr.sort((a,b)=>{return a<b}) - reverse() 反转,能够反转数组的顺序
上面这些方法执行后会改变原来数组,这些我们称为变异方法,还有一些方法执行后总是会返回一个新的数组,并不会改变原来数组,这些我们成为非变异方法,对于非变异方法,通常需要用返回的这个新数组,去替换原来的数组,例如:用concat() 连接数组,需要用新数组替换原来的数组,说白了就是要把执行concat后返回的新数组赋值给原来的数组,这样才会触发页面更新
this.arr = this.arr.concat([9,9,9]);
注意5: 对象的更新也需要使用具体的方法,如果直接在对象上添加或删除属性,将不会触犯页面更新,比如this.obj.num = 30
这样直接添加会生效,但是不会触发页面更新,应该使用this.$set(this.obj,'num', 30);
5.v-on
v-on用来添加事件,前面我们已经用过很多次了,这个指令可以简写,我们绑定事件可以写成下面这样:
绑定一个点击事件:<button @click=‘fn’>点击</button>
绑定一个鼠标移入事件:<div @mouseover='fn2'>hello</div>
6.v-bind
v-bind用来绑定属性
绑定一个href属性:<a v-bind:href="'http://www.baidu.com'">百度一下</a>
可以简写成下面的形式
<a :href="'http://www.baidu.com'">百度一下</a>
7.v-model
v-model可以在表单控件或者组件上创建双向绑定
<input type="text" v-model="val" >
8.v-pre
跳过这个元素和它的子元素的编译过程。可以用来显示原始 Mustache 标签。跳过大量没有指令的节点会加快编译。通俗的说,加了这个指令,元素和它的子元素将不会被编译
<span v-pre>{{ message }}</span>
9.v-cloak
隐藏未编译的Mustache语法标签,直到实例准备完毕<p v-cloak>{{message}}</p>
需要配合css
[v-cloak]{
display: none;
}
注意:当需要隐藏的内容比较多的时候,使用v-cloak,如果内容很少的情况,使用v-text
10.v-once
只渲染元素和组件一次。随后的重新渲染,元素/组件及其所有的子节点将被视为静态内容并跳过。这可以用于优化更新性能。
6.样式绑定
绑定class样式
1.绑定单个class
<div :class="classBox"></div>
2.绑定多个样式
<div :class="[classBox,classBox2,classBox3]"></div>
上面这种方式称为数组语法,数组中的元素也可以使用三元表达式来计算:
<div v-bind:class="[isActive ? activeClass : '', errorClass]"></div>
3.可以根据值来确定是否显示某个样式
<div :class="[{box:isActive},classBox2, classBox3]"></div>
当isActive为true的时候,动态添加box样式,否则此样式不会附加在元素上。
4.可以通过判定来实现样式的选择性使用
<div v-bind:class="{ active: type === 'small', 'text-danger': type === 'big' }"></div>
当 :class 的表达式过长或逻辑复杂时,我们可以通过计算属性来绑定,比如在某个标签中绑定了demoClass变量,将这个变量定义在computed中
computed: {
customClasses: function () {
return {
display: !this.isHidden,
'bigger-text': !this.isHidden && this.isBigger
}
}
}
绑定style样式
1.把所有样式写到一个对象中
<div :style="{width:'100px',height:'100px',backgroundColor:'red'}"></div>
动态绑定样式也可以不写在对象中,像下面这样不会报错,但是不推荐。
<div :style="width:100px;height:100px;background-color:red"></div>
注意:上面代码中需要注意的是对象写法中的css中background-color,需要去掉‘-’,然后把color首字母大写,类似的还有fontSize、marginLeft等
2.可以把样式写到data中的一个对象上,然后渲染到标签上
<div :style="styleObj"></div>
data: {
styleObj: {
width:'100px',
height:'100px',
backgroundColor:'green'
}
}
上面这种写法比较清晰,推荐把样式写到data里面。
3.可以同时设置多个sytleObj
<div id="app">
<button @click="fn">点击</button>
<div :style="[styleObj, styleObj2, styleObj3]">hello, nodeing</div>
</div>
<script src="node_modules/vue/dist/vue.js"></script>
<script>
let vm = new Vue({
el: '#app',
data: {
styleObj: {
width:'100px',
height:'100px',
backgroundColor:'green'
},
styleObj2: {
fontSize: '20px'
},
styleObj3: {
color: 'red'
}
}
});
</script>
4.可以动态绑定具体的属性值
<div class="zoom_dialog" :style="{top:selftop+'px'}">
props: {
topPosition:{
type:Number,
default:1
}
}
computed: {
selftop(){
return (this.topPosition-1)*325+100
}
}
案例:循环渲染li,点击li实现动态class变化
①先在data里增加一个变量,用来储存当前点击的元素
data() {
return {
activeClass: -1, // 0为默认选择第一个,-1为不选择
};
},
②在template里面的代码,切记在@click方法里面要传index,
<li :class="activeClass == index ? 'active':''" v-for="(itme,index) in itmeList" :key="index" @click="getItme(index)">{{itme.text}}</li>
③点击事件:改变data里面activeClass的值
getItme(index) {
this.activeClass = index; // 把当前点击元素的index,赋值给activeClass
},
④在style中写上 .active 样式
.active {
/* background: #eee; */
color: #1e82d2;
font-weight: bolder;
}
另外补充一个快速实现静态数据的tab切换的方法
<body>
<div id="app">
<ul class="tab-tilte">
<li @click="cur=0" :class="{active:cur==0}">标题一</li>
<li @click="cur=1" :class="{active:cur==1}">标题二</li>
<li @click="cur=2" :class="{active:cur==2}">标题三</li>
<li @click="cur=3" :class="{active:cur==3}">标题四</li>
</ul>
<div class="tab-content">
<div v-show="cur==0">内容一</div>
<div v-show="cur==1">内容二</div>
<div v-show="cur==2">内容三</div>
<div v-show="cur==3">内容四</div>
</div>
</div>
<script src="./js/vue.js" type="text/javascript"></script>
<script type="text/javascript">
var app = new Vue({
el: "#app",
data: {
cur:0 //默认选中第一个tab
}
});
</script>
</body>
7.表单输入
基础用法
1.文本
<input type="text" v-model="message" value="hahaha">
注意:此时,如果再设置value是不能生效的,如果有默认值,最好在vue实例中初始化
2.单选框
<input type="radio" v-model="picked" value="男" >
<input type="radio" v-model="picked" value="女" >
<p>选择:{{picked}}</p>
这样写的话,只要单选框被选择了,则自动会把value值赋给v-model双向绑定的数据。
3.复选框
<input type="checkbox" v-model="picked" value="vue" >
<input type="checkbox" v-model="picked" value="react" >
<input type="checkbox" v-model="picked" value="angular" >
<p>选择:{{picked}}</p>
复选框中我们选中哪个,vue就会自动把对应的复选框中的value值丢到v-model绑定的变量的数组中。
4.下拉选择框
<select v-model="selected">
<option disabled value="">请选择</option>
<option value="北京">北京</option>
<option value="上海">上海</option>
<option value="天津">天津</option>
</select>
<span>Selected: {{ selected }}</span>
被选择的value值会被动态的赋值给v-model绑定的值。
修饰符
1.number 把默认为字符串类型的数字转化为number
比如下面的input,本来获取到的值默认是字符串类型的,通过.number修饰符,message值会被自动转换成数字类型。
<input type="text" v-model.number="message">
2.trim 去除首尾的空格
<input type="text" v-model.trim="message">
8.什么是组件?
理解组件
前端组件化开发是目前非常流行的方式,什么是前端组件化开发呢?就是将页面的某一部分独立出来,将这一部分的数据、视图、以及一些控制逻辑封装到一个组件内部,暴露一些开箱即用的函数或者属性供外部组件调用。这种组织代码的开发方式我们称为组件化开发。通俗的说,我们需要把一个页面拆分成若干的小单元,每个小单元就是一个小组件。
组件开发的最大好处就是可以复用代码。
在vue中,所有的 Vue 组件同时也都是 Vue 的实例,所以可接受相同的选项对象 (除了一些根级特有的选项) 并提供相同的生命周期钩子。Vue组件带有一个名字,在根实例中,组件被定义为元素使用,下面我们来定义一个button计数器组件
// 定义一个名为 button-counter 的新组件
Vue.component('button-counter', {
data: function () {
return {
count: 0
}
},
template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>'
})
组件是可复用的 Vue 实例,且带有一个名字:在这个例子中是 <button-counter>。我们可以在一个通过 new Vue 创建的 Vue 根实例中,把这个组件作为自定义元素来使用:
<div id="components-demo">
<button-counter></button-counter>
</div>
new Vue({ el: '#components-demo' })
data必须是一个函数
当我们定义这个 <button-counter>
组件时,你可能会发现它的 data
并不是像这样直接提供一个对象:
data: {
count: 0
}
取而代之的是,一个组件的 data 选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝:
data: function () {
return {
count: 0
}
}
9.将组件分离出来-单文件组件
在上面vue组件的学习的时候,我们使用 Vue.component 来定义全局组件,紧接着用 new Vue({ el: '#container '}) 在每个页面内指定一个容器元素,这种方式在小规模项目中可以运行的很好,但在复杂的项目中就会有很多缺点,因此,我们需要学习并使用单文件组件。
什么是单文件组件?
通俗的说单文件组件就是每个文件就是一个组件,把不同的组件放到不同的文件中去,这种文件以.vue
结尾
单文件组件结构
<template>
<div class="page">
{{message}}我是首页
</div>
</template>
<script type="text/ecmascript-6">
export default {
data () {
return {
message: 'hello, '
}
},
}
</script>
<style scoped>
//scoped可以让css只能在组件内部生效
</style>
实战演练
需求:使用单文件组件完成下图页面
在用vue-cli创建的项目文件夹中的src目录下写代码
1.在src目录下的components目录下新建MyHeader.vue文件,添加下面内容
<template>
<div class="page">
{{ title }}
</div>
</template>
<script type="text/ecmascript-6">
export default {
data () {
return {
title: '这是网页头部'
}
}
}
</script>
<style>
</style>
2.重复上一步,分别添加MyContent.vue文件和MyFooter文件
MyContent.vue
<template>
<div class="page">
{{message}}
</div>
</template>
<script type="text/ecmascript-6">
export default {
data () {
return {
message: '这里是主体内容'
}
}
}
</script>
<style scoped>
</style>
MyFooter
<template>
<div class="page">
{{message}}
</div>
</template>
<script type="text/ecmascript-6">
export default {
data () {
return {
message: '这里是底部内容'
}
}
}
</script>
<style scoped>
</style>
3.在src/App.vue文件中添加内容
<template>
<div class="page">
<router-view></router-view>
<my-header></my-header>
<my-content></my-content>
<my-footer></my-footer>
</div>
</template>
<script type="text/ecmascript-6">
import MyHeader from '@/components/MyHeader'
import MyContent from '@/components/MyContent'
import MyFooter from '@/components/MyFooter'
export default {
data () {
return {
name: 111
}
},
components: {
MyHeader,
MyContent,
MyFooter
}
}
</script>
<style scoped>
</style>
@:build文件夹中webpack.base.config.js中的function resolve(dir){ ... }规定好的一个路径,还有一个使用规定了该路径的使用形式是符号@
4.运行查看效果
在终端里面执行命令
npm start
10.组件生命周期钩子函数
__1.beforecreate : __
完成实例初始化,初始化非响应式变量
this指向创建的实例;
可以在这加个loading事件;
data computed watch methods上的方法和数据均不能访问
2.created
实例创建完成
完成数据(data props computed)的初始化 导入依赖项。
可访问data computed watch methods上的方法和数据
未挂载DOM,不能访问ref为空数组
可在这结束loading,还可以做一些初始化,实现函数自执行,
可以对data数据进行操作,可进行一些ajax请求,请求不易过多,避免白屏时间太长。
若在此阶段进行的 DOM 操作一定要放在 Vue.nextTick() 的回调函数中
3.berofeMount
有了el,编译了template|/outerHTML
能找到对应的template,并编译成render函数
此时页面并没有内容
4.mounted
完成创建vm.ref
可在这发起后端请求,拿回数据,配合路由钩子做一些事情;
可对DOM 进行操作
5.beforeUpdate
数据更新之前
可在更新前访问现有的DOM,如手动移除添加的事件监听器;
6.updated :
完成虚拟DOM的重新渲染和打补丁;
组件DOM 已完成更新;
可执行依赖的dom 操作
注意:不要在此函数中操作数据,会陷入死循环的。
7.activated:
在使用vue-router时有时需要使用<keep-alive></keep-alive>来缓存组件状态,这个时候created钩子就不会被重复调用了,
如果我们的子组件需要在每次加载的时候进行某些操作,可以使用activated钩子触发
__8.deactivated __
keep-alive 组件被移除时使用
keep-alive 是 Vue 内置的一个组件,可以使被包含的组件保留状态,避免重新渲染.
__9.beforeDestroy: __
在执行app.$destroy()之前
可做一些删除提示,如:你确认删除XX吗?
可用于销毁定时器,解绑全局时间 销毁插件对象
10.destroyed :
当前组件已被删除,销毁监听事件 组件 事件 子实例也被销毁
这时组件已经没有了,无法操作里面的任何东西了。
11. errorCaptured
当捕获一个来自子孙组件的错误时被调用。此钩子会收到三个参数:错误对象、发生错误的组件实例以及一个包含错误来源信息的字符串。此钩子可以返回 false 以阻止该错误继续向上传播。