一、Vue核心知识
1.1.Vue的基本简介
学习一门技术首先登陆其官网,中文网址,英文网址,vue
是一款渐进式JavaScript框架,作用是为了动态构建用户界面,该框架遵循MVVM模式,编码简洁,体积小,运行效率高;他借鉴了angular的模板
和数据绑定技术
,借鉴了react的组件化
和虚拟DOM技术
,当然,该技术也存在一个Vue全家桶,例如vue脚手架:vue-cli
,ajax请求:vue-resource
,路由:vue-router
,状态管理:vuex
,图片懒加载:vue-lazyload
,移动端UI组件库:min-ui
,PC端组件库:element-ui
,页面滑动:vue-scroller
等等插件;
1.2.Vue的基本使用
1 | <div id="app"> |
vue的HelloWord编码说明
- 使用vue首先引入Vue.js,然后创建Vue对象,其中el表示指定的
根element选择器
,data是指初始化数据,双向数据绑定使用v-model
,显示数据使用语法:{[xxx]}
; - vue的MVVM的体现就是:
model
代表模型,上述代码就是数据对象(data),view
代表视图,就是vue中的模板页面,viewModel
代表是视图模型(vue实例);
1.3.模板语法
所谓的模板就是动态的Html页面,包含了一些JS语法代码,在Vue中使用双大括号表达式
和指令
(以v-开头的自定义标签属性);
双大括号表达式
语法是:{xxx}
,作用就是向页面输出数据,可以调用对象的方法,例如{msg.toUpperCase()}
;
指令:强制数据绑定
1 | <body> |
上述代码中的img标签的src属性不会获取到data中定义的imgSrc属性的值,这个时候就需要使用指令强制数据绑定,功能就是指定变化的属性值
,完整写法是:v-bind:src='imgSrc'
,一般采用简洁写法::src='imgSrc'
;正确写法如下:
1 | <img :src="imgSrc" alt=""> |
指令:绑定事件监听
1 | <body> |
绑定事件监听指令的作用就是绑定指定事件名的回调函数,完整写法:v-on:click='xxx'
或者v-on:click='xxx(参数)'
再或者v-on:click.enter='xxx'
,简洁写法就是:@click='xxx'
,使用@
符号;
1.4.计算属性和监视
计算属性
在computed属性对象中定义计算属性的方法,在页面中使用{方法名}
来显示计算的结果;
1 | <body> |
计算属性的get和set
使用计算属性实现上述的双向绑定,代码如下:
1 | <body> |
注意:计算属性存在缓存,多次读取只执行一次getter计算;
监视
通过vm对象的$watch()方法或者watch配置
来监视某一个属性的值是否发生变化,当属性发生变化时,通过执行回调函数来执行相关的功能,下面的代码是使用计算属性完成的同一个功能,
1 | <body> |
1.5.class和style绑定
在某些页面中,某些元素的样式是动态发生变化的,class和style绑定就是用来实现动态改变样式效果的技术,其中class绑定中,表达式可以是字符串,可以是对象,也可以是数组,实例如下:
1 | <head> |
1.6.条件渲染
在vue中条件渲染使用v-if
、v-else
和v-show
指令,二者不同的地方在于v-if
是不会生成不应该显示的元素,v-show
是通过css控制隐藏不应该显示的节点元素,是在页面生成的,当需要频繁的切换时,使用v-show
比较好,当条件不成立时,v-is
的所有子节点也不会被解析;
1 | <body> |
1.7.列表渲染
列表的渲染使用的是v-for
指令,可以渲染数组和对象,注意的是遍历的时候指定唯一的index或者key,另外在做数组的删除和更新操作时使用数组的变异方法
,有关vue的数组变异方法可以参考官方API;
1 | <body> |
列表渲染-列表过滤和排序
1 | <body> |
1.8.事件处理
在vue中绑定监听使用@xxx='fun'
,其中点击函数和传参数和不传参数,默认事件的形参是event
,当需要传参的同时需要默认event时候,使用隐含属性对象@xxx = fun(123,$event)
;事件有两个修饰符:.prevent
:阻止事件的默认事件的默认行为和.stop
:停止事件冒泡;按键修饰符使用keyup.keyCode = fun()
:keycode是键盘输入对应的ketcode值,可以使用名称,但是存在一部风没有;
1 | <body> |
1.9.表单输入绑定
表单的数据绑定使用v-model
指令,具体相关编码如下:
1 | <body> |
1.10.Vue的生命周期
常用的生命周期方法:create()/mounted()
:常用于发送Ajax请求启动定时器等异步任务,beforeDestory()
:常用于做一些收尾工作,例如关闭定时器;
1 | <body> |
说明:
beforeCreate、created、beforeMount、mounted
初始化方法只执行一次,beforeUpdate、updated
执行多次,beforeDestroy、destroyed
死亡方法,也执行一次;
1.11.过渡和动画
在vue中动画就是操作css的trasition或者animation属性,vue会给目标元素添加和移除指定的class,只不过要遵循一定的命名规则,
1 | <title>动画和过渡</title> |
1.12.过滤器
在vue中允许自定义过滤器,所谓过滤器就是:对要显示的数据进行特定格式化后在显示,例如时间格式化等
,注意的是:并没有改变原本的数据,只是产生新的对应数据
;
1 | <body> |
1.13.内置指令和自定义指令
常用的内置指令
- v:text : 更新元素的 textContent
- v-html : 更新元素的 innerHTML
- v-if : 如果为 true, 当前标签才会输出到页面
- v-else: 如果为 false, 当前标签才会输出到页面
- v-show : 通过控制 display 样式来控制显示/隐藏
- v-for : 遍历数组/对象
- v-on : 绑定事件监听, 一般简写为@
- v-bind : 强制绑定解析表达式, 可以省略 v-bind
- v-model : 双向数据绑定
- ref : 指定唯一标识, vue 对象通过$els 属性访问这个元素对象
- v-cloak : 防止闪现出现
{[xxx]}
, 与 css 配合: [v-cloak] { display: none }
1 | <title>内置指令</title> |
说明:
v-cloak
指令是为了页面加载数据缓慢时候显示{[xxx]}
标签而出了一个指令,与CSS搭配使用
自定义指令
注册全局指令,方法如下:
1 | Vue.directive('my-directive', function(el, binding){ |
注册局部指令,方法如下:
1 | directives : { |
1 | <body> |
1.14.核心知识总结
- Vue是前端开发库,用于构建用户界面,遵循MVVM模式,编码简洁,体积小,效率高,包含了一些列插件库;
- 基本使用:引入vue.js,创建vue实例对象,其中el代表dom标签选择器,data代表初始化数据对象;
el
:指定dom标签容器的选择器,一般写一个根标签;data
:对象或者函数类型,指定初始化状态属性数据的对象,页面中可以使用{[xxx]}
直接访问methods
:包含多个方法的对象,供页面中的事件指令来回调,回调函数默认有$event
参数,也可以指定自己的参数,在方法中,访问data中的属性直接使用this.xxx
;computed
:计算属性,包含多个方法的对象,对状态属性进行计算处理后返回给页面一个新的数据,使用get和set方法实现属性的计算读取,同时监视数据的变化;watch
:监视,包含多个属性监视的对象,xxx.function(value){}
,可以传入两个参数,代表新值和改变前的值,也可以使用vm.$watch('xxx', function(value){})
的方式添加监听;- vue中的过渡和动画,实质就是vue操作css的transition/animation属性;
- 生命周期:常用的钩子函数是
created() / mounted()
: 启动异步任务(启动定时器,发送ajax请求, 绑定监听)和beforeDestroy()
: 做一些收尾的工作例如清除定时器等; - 自定义过滤器:使用的是
Vue.filter(filterName,function(value){})
,在页面使用方法:{[myData | filterName(arg)]}
,参数可传可不传; - vue内置指令:
v-for遍历
、@绑定事件
、v-model数据双向绑定
、ref标识标签
; - 自定义指令:使用
Vue.directive
注册全局指令,使用directives
注册局部指令;
注意:数据在哪个组件,更新数据的行为(方法)就应该定义在那个组件中
二、Vue组件化编码方式
2.1.使用vue-cli创建模板项目
vue-cli是vue官方提供的脚手架工具,首先确认安装了node和npm,最好安装一个cnpm,使用方法如下:
- npm install -g vue-cli
- vue init webpack vue_demo 其中 vue_demo是项目名
- cd vue_demo
- npm install或者npm run dev
项目结构说明
- build : webpack 相关的配置文件夹(基本不需要修改)
- dev-server.js : 通过 express 启动后台服务器
- config: webpack 相关的配置文件夹(基本不需要修改)
- index.js: 指定的后台服务的端口号和静态资源文件夹
- src : 源码文件夹
- components: vue 组件及其相关资源文件夹
- App.vue: 应用根主组件
- main.js: 应用入口 js
- static: 静态资源文件夹
- .babelrc: babel 的配置文件
- .eslintignore: eslint 检查忽略的配置
- .eslintrc.js: eslint 检查的配置
- .gitignore: git 版本管制忽略的配置
- index.html: 主页面文件
- package.json: 应用包配置文件
- README.md: 应用描述说明的 readme 文件
简单的使用Vue模板项目
首先,我们编写了一个HelloWord的组件,
1 | <template> |
然后,我们在App.vue中使用我们自己定义的组件
1 | <template> |
我们知道使用Webpack打包后会生成一个js文件,也就是入口文件main.js
1 | import Vue from 'vue' |
2.2.项目打包发布方式
打包命令:npm run build
使用静态服务器:安装命令:npm install -g serve
,发布命令:serve dist
,然后直接访问就可以了
使用动态web服务器(Tomcat):修改webpack.prod.conf.js,加入output: {publicPath: '/xxx/' //打包文件夹的名称}
,然后重新打包,将dis文件夹的名称改为项目名称,放在tomcat的webapp目录下,访问即可;
2.3.组件的定义
在vue中,我们知道一个vue文件包含三部分,分别为模版页面、JS模块对象和CSS样式,组件的定义就是写一个vue文件,只是这一个文件单独的完成某一项功能,例如,下拉树,下拉多选等,这就是一个组件;当我们页面需要使用组件的时候就引入相关的组件,使用方法如下:
1.引入组件
1 | import HelloWorld from './components/HelloWord' |
2.将引入的组件映射为标签
1 | export default { |
3.使用组件标签
1 | <HelloWorld/> |
说明:使用标签时:1.和组件映射一模一样写,2.大写变小写,并用-连接,例如:
<hello-world>
2.4.组件的通信
在组件的通信中,我们需要的明确的是数据是某一个组件的数据,还是某一些组件的数据
,也就是明确组件通信的基本原则,不要在子组件中直接修改父组件的状态数据
和数据在那个组件上,更新数据的行为(函数定义)就在那个组件上
;例如:一个页面的评价,包含的添加组件和遍历显示组件,那么数据因该定义在这两个组件的父组件上,因为添加组件是向数据中插入一条数据,遍历组件是将数据遍历显示;
组件的通信方式
在vue中组件之间的通信方式有五种,分别为props、vue的自定义事件、消息的订阅与发布、slot和vuex
,
组件通信:props
1.将父组件的数据传递到子组件中
1 | <List :comments="comments"/> |
2.在子组件中申明props,申明的方式有三种
1 | export default { |
1 | export default { |
1 | export default{ |
同理,组件之间方法的通信也是如下如下所示:
1.父组件定义方法
1 | methods:{ |
2.将方法传递到子组件中,注意使用的是冒号
1 | <Add :addComment="addComment"/> |
3.子组件中使用props申明
1 | props: { |
4.子组件直接通过this使用
1 | this.addComment(comment); |
使用props的优点和缺点
- 使用props这种组件通信方式只适合父组件向子组件传递数据;
- 传递到子组件的标签属性都会称为子组件对象的属性,可以直接在组件中使用;
- 如果需要向非直接子后代的组件传递数据需要多层逐层传递;
- 兄弟组件之间也不能直接使用props通信,需要借助父组件才行;
题外话:不同事件的区别
前提:当一个大div包裹一个小的div时候,
onmouseover
:从外部进入大div时候,触发,从小div进入大div时候,触发onmouseenter
:从外部进入大div时候,触发onmouseleave
:从大div进入到外部时候,触发onmouseout
:从大div进入小div时候,触发
组件通信:自定义事件
官方文件中的自定义事件可以参考,自定义事件,简单的一下
1.父组件中绑定通信的函数,props使用的是冒号,这里不是了
1 | <TodoHeader @addTodo="addTodo"/> |
2.子组件中也不再使用props申明了
1 | this.$emit('addTodo',todo) |
说明:$emit函数的参数一个是绑定的事件函数名,一个就是数据,执行这个函数需要传递的参数;
当然,官方还介绍另外一种自定义事件通信,只是我觉得有些麻烦,这里也一并简单说一下
1.给需要绑定的组件中指定ref属性
1 | <TodoHeader ref="header"/> |
2.因为事件是在加载的时候就因该被绑定,所以在mounted中执行异步代码
1 | mounted(){ |
3.子组件中同样的使用方法
1 | this.$emit('addTodo',todo) |
说明:这种方式也只是适合直接父子组件之间传递函数,在隔代组件活着兄弟组件之间不合适;
组件通信:pubsub消息订阅与发布
使用pubsub.js进行消息的订阅与发布,需要我们下载和引入pubsub.js
1 | npm install --save pubsub-js |
这个时候,我们如果要A–B–C之间传递函数,就可以不再使用props逐层传递和声明了;
和前面的对比:绑定事件监听就是订阅消息,触发事件就是发布消息;
1.父组件引入pubsub.js
1 | import PubSub from 'pubsub-js' |
2.父组件中订阅消息
1 | mounted(){ |
3.孙子组件同理引入pubsub.js,同时发布消息
1 | PubSub.publish('deleteTodo',index) |
说明:使用pubsub进行组件之间的通信,可以不关系组件之间的关系,例如兄弟组件都可以使用;
组件通信:slot
简单说,我们平时看的APP的顶部导航就是反复的使用,但是每一个页面的内容和样式又不一样,这个时候就可以使用slot,父组件向子组件传递标签数据
;
1.首先在子组件中定义插头,定义了三个插头
1 | <template> |
2.在父组件中向子组件传递标签数据
1 | <TodoFooter> |
说明:传递的标签数据是在父组件渲染的,所以子组件的计算属性都要放在父组件中,子组件不需要写;
三、Vue请求方式vue-ajax
在vue中,可以使用vue-ressource和axios来发送异步AJAX请求,其中vue-ressource在vue1.x中使用广泛,但在vue2.x之后官方推荐使用axios请求库
3.1.axios的使用
1.下载axios
1 | npm install axios --save |
2.组件中引入
1 | import axios from 'axios' |
3.组件初始化时候调用
1 | mounted(){ |
四、Vue组件库
常用的vue组件库,在移动端使用Mint UI
,其官方文档为:MintUI,在PC端使用的是Element
,官方文档为:Element,各个UI组件的使用方法基本一样,参考官方文档就可以使用,下面简单使用一下Mint UI;
4.1.使用Mint UI
1.下载安装Mint UI
1 | npm install --save mint-ui |
2.下载实现按需打包
1 | npm install --save-dev babel-plugin-component |
3.修改babelrc配置文件
1 | "plugins": ["transform-vue-jsx", "transform-runtime",["component",[ |
4.由于是移动端,可以在index.html 中添加适配
1 | <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1,minimum-scale=1, user-scalable=no" /> |
5.可以在main.js中全局配置我们需要使用的组件
1 | import {Button} from 'mint-ui' |
6.在组件中使用
1 | <mt-button type="primary" style="width: 100%" @click="handleClick">按钮</mt-button> |
五、Vue路由vue-router
5.1.vue-router简介
在spa