文章目录
1、Vue.js是什么?
一位华裔前Google
工程师(尤雨溪)开发的前端js库
作用:动态构建用户界面
特点:①遵循MVVM
模式
②编码简洁,体积小,运行效率高,移动
/PC
端开发
③它本身只关注UI
,可以轻松引入vue
插件和其他第三方库开发项目
与其他框架的关联
①借鉴angular
的模板和数据绑定技术
②借鉴react
的组件化和虚拟DOM
技术
vue包含一系列的扩展插件(库)
vue-cli | vue脚手架 |
---|---|
vue-resource(axios) | ajax请求 |
vue-router | 路由 |
vuex | 状态管理 |
vue-lazyload | 图片懒加载 |
vue-scroller | 页面滑动相关 |
mint-ui | 基于vue的组件库(移动端) |
element-ui | 基于vue的组件库(PC端) |
2、Vue.js基本使用
1)引入vue.js
<script type="text/javascript" src="../js/vue.js"></script>
2)创建Vue
实例对象(vm
),指定选项(配置)对象
el:指定dom
标签容器的选择器
data:指定初始化状态数据的对象/函数(返回一个对象)
<script type="text/javascript">
//创建Vue实例
const vm = new Vue({
//配置对象
el: '#app',
data: {
//数据(Model)
username: ''
}
})
</script>
3)在页面模板中使用{{}}
或vue
指令
//双向数据绑定 : v-model
//显示数据 : {{xxx}}
<input type="text" v-model="username">
<p>Hello {{username}}</p>
3、Vue对象的选项
①el
指定dom
标签容器的选择器,Vue
就会管理对应的标签及其子标签(默认为文件名的小写)
②components
映射组件标签
<template>
<div id="app">
<!--3、使用组件标签-->
<HelloWorld/>
</div>
</template>
<script>
//1.引入组件
import HelloWorld from './components/HelloWorld.vue'
export default {
//2.映射组件标签
components: {
HelloWorld
}
}
</script>
③data
对象或函数类型
指定初始化状态属性数据的对象,vm
也会自动拥有data
中的属性,页面中可以直接访问
数据代理:由vm
对象来代理对data
中所有属性的操作(读/写)
④methods
包含多个方法的对象
供页面中的事件指令来绑定回调,回调函数默认有event
参数,但也可以指令自己的参数
所有的方法由vue
对象来调用,访问data
中属性直接使用this.xxx
⑤computed
在computed
属性对象中定义计算属性的方法
计算属性高级:
通过getter/setter
实现对属性数据的显示和监视
计算属性存在缓存, 多次读取只执行一次getter
计算
<div id="demo" id="app">
姓: <input type="text" placeholder="First Name" v-model="firstName"><br>
名: <input type="text" placeholder="Last Name" v-model="lastName"><br>
<!--fullName1是根据fistName和lastName计算产生-->
姓名1(单向): <input type="text" placeholder="Full Name1" v-model="fullName1"><br>
姓名3(双向): <input type="text" placeholder="Full Name3" v-model="fullName3"><br>
</div>
<script type="text/javascript" src="../js/vue.js"></script>
<script type="text/javascript">
const vm = new Vue({
el: '#demo',
data: {
firstName: 'A',
lastName: 'B',
},
//计算属性,什么时候执行:初始化显示/相关的data属性数据发生改变
//计算并返回当前属性的值
computed: {
//什么时候执行:初始化显示/相关的data属性数据发生变化
fullName1() {//计算属性中的一个方法,方法的返回值作为属性值
return this.firstName + ' ' + this.lastName;
},
fullName3: {
//回调函数:1、你定义的 2、你没有调用 3、最终执行了
//当需要读取当前属性值时回调,根据相关的数据计算并返回当前属性的值
get() {
return this.firstName + ' ' + this.lastName;
},
//回调函数,监视当前属性值的变化,当属性值发生改变时回调,更新相关的属性数据
set(value) {//value就是fullName3的最新属性值
const names = value.split(' ');
this.firstName = names[0];
this.lastName = names[1];
}
}
}
});
</script>
⑥watch
包含多个属性监视的对象,分为一般监视和深度监视
xxx:function(value){ xxx:{ deep:true, handler:fun(value) } }
另一种添加监视方式:vm.$watch('xxx',function(value){})
<div id="demo" id="app">
姓: <input type="text" placeholder="First Name" v-model="firstName"><br>
名: <input type="text" placeholder="Last Name" v-model="lastName"><br>
姓名2(单向): <input type="text" placeholder="Full Name2" v-model="fullName2"><br>
</div>
<script type="text/javascript" src="../js/vue.js"></script>
<script type="text/javascript">
const vm = new Vue({
el: '#demo',
data: {
firstName: 'A',
lastName: 'B',
fullName2: 'A B'
},
watch: {//配置监视
//监听firstName
firstName: function (value) {
console.log(this);//vm对象
this.fullName2 = value + ' ' + this.lastName;
}
}
});
//监视lastName
vm.$watch('lastName', function (value) {
this.fullName2 = this.firstName + ' ' + value;
})
</script>
4、过渡动画
vue
动画的理解
操作css
的trasition
或animation
vue
会给目标元素添加/移除特定的class
- 基本过渡动画的编码
1). 在目标元素外包裹
2). 定义class
样式- 指定过渡样式:
transition
- 指定隐藏时的样式:
opacity
/其它
- 指定过渡样式:
- 过渡的类名
xxx-enter-active
: 指定显示的transition
xxx-leave-active
: 指定隐藏的transition
xxx-enter
,.xxx-leave-to
: 指定隐藏时的样式
代码示例:
<style type="text/css">
.fade-enter-active, .fade-leave-active {
transition: opacity 1s;
}
.fade-enter, .fade-leave-to {
opacity: 0;
}
</style>
<div id="demo1">
<button @click="show=!show">
Toggle1
</button>
<transition name="fade">
<p v-if="show">Hello</p>
</transition>
</div>
<script type="text/javascript">
new Vue({
el: '#demo1',
data: {
show: true
}
})
</script>
5、生命周期
①vue
生命周期分析
-
初始化显示
beforeCreate()
created()
beforeMount()
mounted()
-
更新状态:
this.xxx = value
beforeUpdate()
updated()
-
销毁
vue
实例:vm.$destroy()
beforeDestory()
destoryed()
②主要的生命周期函数:
created()
/mounted()
:启动异步任务(启动定时器,发送ajax请求,绑定监听)
beforeDestory()
:做一些收尾工作
6、自定义过滤器
①理解
对需要显示的数据进行格式化后再显示
②编码
1). 定义过滤器
Vue.filter(filterName, function(value[,arg1,arg2,...]){
// 进行一定的数据处理
return newValue
})
2). 使用过滤器
<div>{{myData | filterName}}</div>
<div>{{myData | filterName(arg)}}</div>
具体示例代码
<div id="test">
<p>原生:{{date}}</p>
<p>完整版:{{date | dateString}}</p>
<p>年月日:{{date | dateString('YYYY-MM-DD')}}</p>
<p>时分秒:{{date | dateString('HH:mm:ss')}}</p>
</div>
<script type="text/javascript" src="../js/vue.js"></script>
<script type="text/javascript" src="https://cdn.bootcss.com/moment.js/2.24.0/moment.min.js"></script>
<script>
Vue.filter('dateString', function (value, format) {
//如果没有format没有值则使用后面给定的格式
return moment(value).format(format || "YYYY-MM-DD HH:mm:ss")
})
new Vue({
el: '#test',
data: {
date: new Date()
}
})
</script>
7、Vue内置指令
指令 | 属性 |
---|---|
v-text/v-html | 指定标签体;v-html会将value作为html标签来解析 |
v-if &v-else v-show |
显示/隐藏元素 v-if:如果value为true,当前标签会输出在页面中 v-else:与v-if一起使用,如果value为false,将当前标签输出到页面中 v-show:就会在标签中添加display样式, 如果vlaue为true, display=block, 否则是none |
v-for | 遍历 遍历数组:v-for="(persons,index) in persons" 遍历对象:v-for=“value in person” |
v-on | 绑定事件监听 v-on:事件名,可以缩写为:@事件名 监听具体的按键:@keyup.keyCode @keyup.enter 停止时间的冒泡和阻止时间的默认行为:@click.stop @click.prevent 隐含对象:$event |
v-bind | 强制绑定解析表达式 html标签属性是不支持表达式的,就可以使用v-bind 可以缩写为: :id='name’ 代码示例: :style="{color:colorValue}" |
v-model | 双向数据绑定,自动收集用户输入数据 |
ref: | 标识某个标签 ref='xxx’ 读取得到标签对象:this.$refs.xxx |
v-cloak | 防止页面加载时出现 vuejs 的变量名 |
示例代码:
<div id="example">
<p v-text="msg" ref="message"></p>
<p v-html="msg"></p>
<p v-for="(item,index) in arr">{{item}}</p>
<p v-cloak v-for="(item2,index) in obj">{{item2}}</p>
<button @click="showMsg">显示Msg</button>
</div>
<script type="text/javascript" src="../js/vue.js"></script>
<script type="text/javascript">
new Vue({
el: '#example',
data: {
msg: "<b>Hello VUE</b>",
arr: [111, 2222],
obj: {'name1': 1, 'name2': 2}
},
methods: {
showMsg() {
alert(this.$refs.message.textContent);
}
}
})
</script>
8、自定义指令
1). 注册全局指令
Vue.directive('my-directive', function(el, binding){
el.innerHTML = binding.value.toUpperCase()
})
2). 注册局部指令
directives : {
'my-directive' : function(el, binding) {
el.innerHTML = binding.value.toUpperCase()
}
}
3). 使用指令:v-xxx
具体示例代码
<div id="test">
<p v-upper-text="msg"></p>
<p v-lower-text="msg"></p>
</div>
<script type="text/javascript" src="../js/vue.js"></script>
<script type="text/javascript">
// 注册一个全局指令(不同的vue的id下均可以使用)
// el: 指令所在的标签对象
// binding: 包含指令相关数据的容器对象
Vue.directive('upper-text', function (el, binding) {
el.innerHTML = binding.value.toUpperCase();
})
new Vue({
el: '#test',
data: {
msg: "<b>Where</b> Amazing Happens!"
},
//定义局部指令(只能在指定的id下可以使用)
directives: {
'lower-text': {
bind(el, binding) {
el.textContent = binding.value.toLowerCase();
}
}
}
})
</script>
9、表单的输入绑定
<div id="demo">
<form action="/xxx" @submit.prevent="submitForm">
<span>用户名: </span>
<input type="text" v-model="user.username"><br>
<span>密码: </span>
<input type="password" v-model="user.pwd"><br>
<span>性别: </span>
<input type="radio" id="female" value="女" v-model="user.sex">
<label for="female">女</label>
<input type="radio" id="male" value="男" v-model="user.sex">
<label for="male">男</label><br>
<span>爱好: </span>
<input type="checkbox" id="basket" value="basket" v-model="user.likes">
<label for="basket">篮球</label>
<input type="checkbox" id="foot" value="foot" v-model="user.likes">
<label for="foot">足球</label>
<input type="checkbox" id="pingpang" value="pingpang" v-model="user.likes">
<label for="pingpang">乒乓</label><br>
<span>城市: </span>
<select v-model="user.cityId">
<option value="">未选择</option>
<option :value="p.id" v-for="(p,index) in user.allCity">{{p.name}}</option>
</select><br>
<span>介绍: </span>
<textarea rows="10" v-model="user.desc"></textarea><br><br>
<input type="submit" value="注册">
</form>
</div>
<script type="text/javascript" src="../js/vue.js"></script>
<script type="text/javascript">
new Vue({
el: '#demo',
data: {
user: {
username: "",
pwd: "",
sex: "女",
likes: ['foot'],
cityId: '',
allCity: [{id: 1, name: 'BJ'}, {id: 2, name: 'SH'}, {id: 3, name: 'SZ'}],
desc: ''
}
},
methods: {
submitForm() {
}
}
})
</script>
10、自定义插件的使用
插件通常用来为 Vue
添加全局功能。插件的功能范围没有严格的限制——一般有下面几种:
- 添加全局方法或者属性。如:
vue-custom-element
- 添加全局资源:指令/过滤器/过渡等。如
vue-touch
- 通过全局混入来添加一些组件选项。如
vue-router
- 添加
Vue
实例方法,通过把它们添加到Vue.prototype
上实现。 - 一个库,提供自己的
API
,同时提供上面提到的一个或多个功能。如vue-router
代码示例:vue-myPlugin.js
(function (window) {
const MyPlugin = {}
MyPlugin.install = function (Vue, options) {
// 1. 添加全局方法或属性
Vue.myGlobalMethod = function () {
console.log('Vue函数对象的myGlobalMethod()')
}
// 2. 添加全局资源
Vue.directive('my-directive',function (el, binding) {
el.textContent = 'my-directive----'+binding.value
})
// 3. 添加实例方法
Vue.prototype.$myMethod = function () {
console.log('vm $myMethod()')
}
}
window.MyPlugin = MyPlugin
})(window)
使用
<div id="test">
<p v-my-directive="msg"></p>
</div>
<script type="text/javascript" src="../js/vue.js"></script>
<script type="text/javascript" src="vue-myPlugin.js"></script>
<script type="text/javascript">
// 声明使用插件(安装插件: 调用插件的install())
Vue.use(MyPlugin) // 内部会调用插件对象的install()
const vm = new Vue({
el: '#test',
data: {
msg: 'HaHa'
}
})
Vue.myGlobalMethod()
vm.$myMethod()
</script>
11、vue脚手架
用来创建vue
项目的工具包
创建项目:
npm install -g vue-cli
(第一次安装vue-cli
)
vue init webpack 项目名
开发环境运行:
cd 项目名
->npm install
->npm run dev
生产环境打包发布:
npm run build
(即生成打包好的文件dist
)
安装测试服务器测试
npm install -g serve
serve dist
访问所给的链接即可
使用tomcat
服务器
将打包好的dist
文件夹放入到webapps
下,tomcat
默认端口为8080
,访问http://localhost:8080/dist
即可。
12、eslint
用于做项目编码规范检查的工具
基本原理:定义了很多规则, 检查项目的代码一旦发现违背了某个规则就输出相应的提示信息
有相应的配置, 可定制检查。
关闭编码时候的检查:webstorm:setting
->搜索ESLint
-<关闭Enable
13、组件化编程
①vue文件的组成
<template>
<div></div>
<template/>
<script>
//配置Vue对象
exprot default{
//指定属性名和属性值的类型
props:[]/{},
//这里只能用函数的方式
data(){
return{
arr:[1,2,3],
obj:{name:value}
}
},
computed: {},
methods: {},
watch: {},
filters: {},
directives: {},
components: {}
}
</script>
<style>
<style/>
②组件化编码的基本流程
-
拆分界面,抽取组件
-
编写静态组件
-
编写动态组件
初始化数据,动态显示初始化界面,实现与用户交互功能
③组件间通信
1)props
父子组件间通信的基本方式
属性值的2大类型:
一般:父组件->子组件
函数:子组件->父组件
隔层组件间传递:必须逐层传递
兄弟组件间:必须借助父组件
代码示例:
父组件:
<template>
<div :title='text'></div>
</template>
<script>
export default{
data(){
return{
text:"Hello Child"
}
}
}
</script>
子组件:
<template>
<p>{{title}}</p>
</template>
<script>
export default{
props:{
title:String
}
}
</script>
2)vue的自定义事件
该方式用的较少
此方式只用于子组件向父组件发送消息(数据),不适合隔层组件和兄弟组件间的通信
子组件:this.$emit('addTodo', todo)
父组件:
方式一:通过v-on
<TodoHeader @addTodo="addTodo"/>
方式二:通过$on
<TodoHeader ref="header"/>
this.$refs.header.$on('delete_todo', function (todo) {
this.deleteTodo(todo)
})
3)pubsub第三方库
适合于任何关系的组件间通信
安装:npm install --save pubsub-js
发布消息:PubSub.publish('deleteTodo', this.index)
订阅消息:
PubSub.subscribe('deleteTodo', (msg, index) => {
this.deleteTodo(index)
})
4)slot
此方式用于父组件向子组件传递标签数据
5)vuex(推荐)
多组件共享状态(数据的管理),组件间的关系也没有限制
功能比pubsub
强大,更适用于vue
项目,后面将详细讲解。
14、Ajax
vue-resource
:vue
插件,多用于vue1.x
axios
:第三方库,多用于vue2.x
①vue-resource的使用
//引入模块
import VueResource from 'vue-resource'
//使用插件
Vue.use(VueResource)
//通过vue/组件对象发送ajax请求
this.$http.get('/someUrl').then((response)=>{
//success callback
console.log(response.data)
},(response)=>{
//error callback
console.log(response.statusText) //错误信息
}
)
②axios的使用
//引入模块
import axios from 'axios'
//发送ajax请求
axios.get(url).then(response=>{
//得到返回结果数据
console.log(response.data)
}).catch(error=>{
console.log(error.message)
})
15、vue-router
vue
用来实现SPA
漏油的插件,使用vue-router
的方法如下:
①创建路由器
[router/index.js]
import Vue from 'vue'
import VueRouter from 'vue-router'
import About from '../components/About.vue'
import Detail from '../components/Detail.vue'
Vue.use(VueRouter)
exprot default new VueRouter({
routes:[
{
//一般路由
path:'/about',
component:About,
//嵌套路由
children:[{
path:'/about/detail',
component:Detail
}]
},
{
//自动跳转路由
path:'/',
redirect:'/about'
}
]
})
②注册路由器
[main.js]
import router from './router'
new Vue({
router
})
③使用路由组件标签
<router-link to="/xxx">Go to XXX</router-link>
<router-view></router-view>
向路由组件传递数据
params: <router-link to="/home/news/abc/123">
props: <router-view msg='abc'>
缓存路由组件
<keep-alive>
<router-view></router-view>
</keep-alive>
路由的编程式导航
this.$router.push(path): 相当于点击路由链接(可以返回到当前路由界面)
this.$router.replace(path): 用新路由替换当前路由(不可以返回到当前路由界面)
this.$router.back(): 请求(返回)上一个记录路由
16、vuex
对应用中组件的状态进行集中式的管理(读/写)
①状态自管理应用
state
:驱动应用的数据源
view
:以声明方式将state映射到视图
actions
: 响应在view
上的用户输入导致的状态变化(包含n个更新状态的方法)
②多组件共享状态的问题
多个视图依赖于同一状态,来自不同视图的行为需要变更同一状态
以前的解决办法
将数据以及操作数据的行为都定义在父组件
将数据以及操作数据的行为传递给需要的各个子组件(有可能需要多级传递)
vuex
就是用来解决这个问题的,vuex
结构图如下
③vuex的核心概念
1.state
vuex
管理的状态对象,它应该是唯一的
2.mutations
包含多个直接更新state
的方法(回调函数)的对象
谁来触发: action
中的commit('mutation名称')
只能包含同步的代码, 不能写异步代码
3.actions
包含多个事件回调函数的对象
通过执行: commit()
来触发mutation
的调用, 间接更新state
谁来触发: 组件中: $store.dispatch('action名称')
可以包含异步代码(定时器, ajax)
4.getters
包含多个计算属性(get
)的对象
谁来读取: 组件中: $store.getters.xxx
5.modules
包含多个module
一个module
是一个store
的配置对象
与一个组件(包含有共享数据)对应
④项目中Vuex的具体使用
下载: npm install vuex --save
[state.js]
export default {
articles: []
}
[actions]
import {SAVE_ARTICLE} from './mutation-type'
import axios from 'axios'
export default {
reqArticles ({commit}) {
//异步请求的具体代码只能在action.js中
axios.get('http://47.106.166.70:8100/get/all/articles').then(response => {
const articles = response.data
commit(SAVE_ARTICLE, {articles})
console.log("success")
}).catch(error => {
console.log(error.message)
})
}
}
[mutations.js]
import {SAVE_ARTICLE,GO_HOME,GO_INDEX} from './mutation-type'
export default {
[SAVE_ARTICLE](state,{articles}){
state.articles=articles
}
}
[index.js]
//向外暴露store对象
Vue.use(Vuex)
export default new Vuex.Store({
state,mutations,actions,getters
})
[main.js]
//映射store
import store from './store'
new Vue({
store
})
[组件中如何使用]
第一种(推荐):
import {mapGetters, mapActions} from 'vuex'
methods: {
//映射action中的方法
...mapActions(['goHome']),
goToHome () {
//this.$router为传递的对象
this.goHome(this.$router)
}
}
第二种:至二级使用$store对象
mounted () {
this.$store.dispatch('reqArticles')
}
注:
store对象
1.所有用vuex管理的组件中都多了一个属性$store, 它就是一个store对象
2.属性:
state: 注册的state对象
getters: 注册的getters对象
3.方法:
dispatch(actionName, data): 分发action
17.ElementUI的简单使用
下载并导入:npm i element-ui -S
[mian.js]
import 'element-ui/lib/theme-chalk/index.css';
import Element from 'element-ui';
Vue.use(Element, { size: 'small', zIndex: 3000 });
[.vue页面中]
<template>
<el-button type="primary" @click="handleClick">主要按钮</el-button>
</template>
<script>
export default {
methods: {
handleClick () {
this.$message('这是一条消息提示');
}
}
}
</script>