Vue
声明式渲染 — 组件系统 – 客户端路由 – 集中式状态管理 – 项目构建
易用
灵活
高效
vue 的基本使用步骤:
- 需要提供标签用于填充数据
- 引入vue.js库文件
- 可以使用vue语法做功能
- 把vue提供的数据填充到标签里面
<body>
<!-- {{}} 差值表达式 支持基本的计算操作 -->
<div id="app">{{msg}}</div>
<script type="text/javascript" src="../vue.min.js"></script>
<script >
/* vue的基本使用步骤
1. 需要提供标签用于填充数据
2. 引入vue.js库文件
3. 可以使用vue的语法做功能
4. 把vue提供的数据填充到标签里面 */
var vm = new Vue({
el:'#app',//元素的挂载位置(值可以式css选择器或者DOM元素)
data:{ //模型数据(值可以是对象)
msg:'hello Vue'
}
})
</script>
</body>
vue 运行原理:
前端渲染:
把数据填充到HTML标签中
方式:
js 拼接字符串
模板引擎
vue
指令:
指令的本质是自定义属性
格式:以 v- 开始 (比如:v-cloak)
v-cloak
取消插值表达式的闪动问题
原理:先通样式隐藏内容然后在内存中进行值的替换替换好后在显示最终的结果
v-text
与插值表达式比较:
没有闪动
v-html
填充html 片段
v-pre
填充原始的信息 跳过编译过程
响应式
html5 中响应式(屏幕尺寸的变化导致样式的变化)
数据的响应式(数据的变化导致页面内容的变化)
数据绑定:将数据填充到标签中
v-once 只编译一次
显示内容之后不在有响应式的功能
应用场景:如果显示的信息后续不需要修改:可以使用v-once,这样可以提高性能
双向数据绑定
v-model 指令
当页面把页面内容改变时 数据会变 数据时 页面改变
MVVM 设计思想
M(model) 数据
V(view) 模板
VM(view-Model)
view ------> DOMListeners ---------> model
model -------> Data Bindings ----------> view
DOM Listeners 事件监听
DataBindings 事件绑定
事件绑定
v-on
<button v-on:click='num++'>+</button>
<button @click='num++'>+</button>
事件函数调用
直接调用;
<button v-on:click=‘say'>Hello</button>
调用函数:
<button v-on:click='say()'></button>
this 指向:
是vue的实例对象
<script>
var vm = new Vue({
el:'#app',
data:{
msg:'Hello Vue',
num:0
},
methods:{
handle:function(){
//this --> data:num
this.num++
console.log(this.num)
}
}
})
</script>
传递事件属性:
<div>
<button v-on:click='handle($event)'>+</button>
</div>
<script>
var vm = new Vue({
el:'#app',
data:{
msg:'Hello Vue',
num:0
},
methods:{
handle:function(形参,event){
//this --> data:num
this.num++
console.log(this.num)
// 获取事件
console.log(event.target.tagName)
//获取内容
console.log(event.target.innerHTML)
}
}
})
事件修饰符
.stop 阻止冒泡
<button v-on:clic.stopk='handle($event)'>+</button>
.prevent 阻止默认行为 (跳转)
<button v-on:click.prevent='handle($event)'>+</button>
按键修饰符
自定义按键修饰符
名字是自定义的 但是对应的值是event.keyCode
<body>
<div id="app">
<div>{{num}}</div>
<input type="text" v-model='msg'>
<input type="text" v-on:keyup='handled'>
</div>
<script src="../vue.min.js"></script>
<script>
//Vue.config.keyCodes.f1 = 112
var vm = new Vue({
el:'#app',
data:{
msg:'Hello Vue',
num:0
},
methods:{
handled:function(event){
console.log(event.keyCode)//获取键盘的数值
}
}
})
</script>
</body>
============================
<input type="text" v-on:keyup.65='handled'>
=========================
案例 计算器:
body>
<div id="app">
<!-- 主要用到双向数据绑定 -->
<span>
数值A:<input type="text" v-model='a'>
</span>
<span>
数值B:<input type="text" v-model='b'>
</span>
<button v-on:click='handle'>计算</button>
<div>计算结果:<span v-text='result' ></span></div>
</div>
<script src="../vue.min.js"></script>
<script>
var vm = new Vue({
el:'#app',
data:{
a:'',
b:'',
result:''
},
methods:{
handle:function(){
//计算逻辑
this.result = parseInt(this.a) + parseInt(this.b)
}
}
})
</script>
属性绑定
v-bind
<a v-bind:href='url'>跳转</a>
v-model 的处理机制:
v-bind:属性绑定 v-on:绑定事件监听
事件相同:
<input type="text" v-bind:value='msg' v-on:input='handled'>
<input type="text" v-bind:value='msg' v-on:input='msg=$event.target.value'>
<input type='text' v-model='msg'>
样式绑定
class 样式处理
对象语法:
<div v-bind:class=“{active:isActive}”><div>
handless:function(){
// this.isactive = !this.isactive
this.active = ''
}
数组语法:
直接操作值
<div v-bind:class='[activeClass,errorClass]'></div>
acitveClass//是在data里的类
细节:
- 对象绑定和数组绑定可以结合使用
<div v-bind:class='[activeClass,errorClass,{test:isTest}]'></div>
-
class绑定值可以简化操作
data:中设置 arrClasses:['active','error']/对象都可以
-
默认的class
默认的class 会保留
Style处理
对象语法
<div v-bind:style=“{color:activeColor}”><div>
在:data 中定义
数组语法
<div v-bind:style=“[baseStyles]”><div>
v-show原理
v-showd的原理:控制元素样式是否显示 display
v-show 与 v-if 区别:
v-if 控制元素是否渲染到页面
v-show 控制元素是否显示( 已经渲染到了页面)
循环结构:
v-for 遍历数组
<li v-for='item in list'>{{item}}</li>
<li v-for='(item,index/索引) in list'>{{item}}+'-----'+{{index/索引}}</li>
key 的作用:帮助Vue 区分不同的元素,从而提高性能
<li :key='item.id' v-for='(item,index) in list'>{{item}} + '----' {{index}}</li>
v-for 遍历对象
<li v-for=‘(value,key,index)in object’>{{item}}</li>
v-if 和 v-for 结合使用
div v-if='value==12' v-for='(value key index) in object'
Vue 常用特性:
侦听器:
watch
<body>
<div id="app">
<input type="text" v-model.lazy='uname'>
<span>{{tip}}</span>
</div>
<script src="../vue.min.js"></script>
<script>
let vm = new Vue({
el:'#app',
data:{
uname:'',
tip:''
},
methods: {
checkName:function(uname){
var that = this
setTimeout(function(){
if(uname == 'admin'){
that.tip = '存在'
}else{
that.tip = '不存在'
}
},2000)
}
},
watch: {
uname:function(val){
this.checkName(val)
this.tip = '正在验证:'
}
},
})
</script>
</body>
过滤器:
filter:
带参数的过滤器
vue.filter('format',function(value,arg1){
//value 就是过滤传递过来的参数
})
使用
<div>{{date| format('yyy-MM-id')}}</div
<body>
<div id="app">
<div>{{date|format('yyyy-MM-dd')}}</div>
</div>
<script src="../vue.min.js"></script>
<script>
Vue.filter('format',function(value,arg){
if(arg == 'yyyy-MM-dd'){
var ret = '';
ret += value.getFullYear() + '-' +(value.getMonth()+1) + '-' +value.getDate()
return ret
}
})
var vm = new Vue({
el:'#app',
data:{
date: new Date()
}
})
</script>
</body>
生命周期:
- 挂载(初始化相关属性)
- beforeCreate
- created
- befroeMount
- mounted 调用 代表初始化完成 开始调用
- 更新(元素或组件的变更操作)
- beforeUpdate
- update
- 销毁(销毁相关属性)
- beforeDestroy
- destroyed
数组和对象动态修改
修改响应式数据:
除了 vue检测更新外还可以
Vue.set(vue.items,indexOfltem,newValue)
vm.$set(vm.items,indexOfltem,newValue)
- 参数一 表示要处理的数组名称
- 参数二表示处理数组的索引
- 参数三表示要处理的数组值
图书管理
添加:
实现表单的静态效果
添加表单域数据绑定
添加按钮事件绑定
实现添加业务逻辑
修改:
修改信息填充到表单
修改后重新提交表单
重用添加和修改的方法
1;
过滤器(格式化日期)
自定义指令(获取表单焦点)
计算属性(统计图书数量) 图书的长度
侦听器(验证图书是否存在性)
生命周期(图书数据处理)
Vue 组件开发
开发思想
标准 分治 重用 组合
- 注册组件
Vue.component(组件名称,{
data:组件数据,
template:组件模板内容
})
组件注册注意事项:
如果使用驼峰式命名组件,那么在使用组件的时候,只能在字符串中使用驼峰的方式使用
如果在标签使用的化必须是短横线方式
局部组件只能在注册它的父组件中使用
父组件向子组件传值
-
组件内部通过props接收传递过来的值
Vue.component('menu-item',{ props:['title'], template:'<div>{{title}}</div>' })
-
父组件通过属性将值传递给子组件
<menu-item title='来自父组件的数据'></menu-item>
<menu-item :title=‘title></menu-item>
props 属性名规则
- 在props中使用驼峰形式,模板中需要使用短横线的形式
- 字符串形式的模板中没有这个限制
vue.component('menu-item',{
//在javaScript 中是驼峰式的
props:['menuTitle'],
//字符串中
template:'<div>{{menuTitle}}</div>'
})
//在html中是短横线方式的
<menu-item ment-title='nihao'></menu-item>
props 属性值类型
- 字符串Sting 2. 数值Number 3.布尔值Boolean 4.数组Array 5.,对象Object
子组件向父组件传值:
props 传递数据原则:单向数据流
子组件通过自定义事件向父组件传递信息
<button v-on:click="$emit('enlarge-text')">扩大字体</button>
父组件监听子组件的事件
<menu-item v-on:enlarge-text='fontSize += 0.1'></menu-item>
兄弟组件:
兄弟组件直接不能传递值 必须通过事件中心转接一下
- 单独的事件中心管理组件间的通信
var eventHub = new Vue()
- 监听事件与销毁事件
eventHub.$on('add-todao',addTodo)
evenHub.$off('add-todo')
- 触发事件
eventHub.$emit('addd-todo',id)
组件开发的原则:
-
根据业务功能进行组件划分
- 标题组件(展示文本)
2. 列表组件(列表展示,商品数量变更,商品删除)
3. 结算组件(计算商品总额)
- 标题组件(展示文本)
-
功能实现步骤:
- 实现整体布局和样式效果
- 划分独立的功能组件
- 组合所有的子组件形成整体结构
- 逐个实现各个组件功能
- 标题组件
- 列表组件
- 结算组件
前后端交互模式
- 原生ajax
- 基于jQuery的ajax
- fetch // ajax 升级版
- axios
客户端 -------> 互联网---------->服务器
服务器---->返回一个完整的HTML页面or特定格式的数据比如json ----->客户端
- 传统形式的URL
格式:schema://host:post/path?query#fragment
-
schema: 协议。 例如/http/https/ftp等
-
host: 域名或者IP地址
-
port: 端口,http默认端口80,可以省略
-
path:路径,例如/abc
-
query: 查询参数,例如 uname=lisi&age=12
-
fragment: 锚点(哈希Hash),用于定位页面的某个位置
-
Restful形式的URl
HTTP 请求方式
1 GET 查询
2 POST 添加
3 PUT 修改
4 DELETE 删除
Promise 用法:
用来处理异步编程
Promise是一个对象,从它可以获取异步操作的消息
好处:
可以避免多层异步调用嵌套问题(回调地狱)
Promise 对象提供了简洁的API 使得控制异步操作更加容易
异步效果分析:
- 定时任务
- Ajax
- 事件函数
用法:
实例化 Promise 对象 构造函数中传递函数, 该函数中用于处理异步任务
resolve 和 reiect 两个参数用于处理成功和失败两种情况,并通过 p.then 获取处理结果
var p = new Promise(function(resolve,reject){
//成功时调用 resolve()
//失败时调用 reject()
})
p.then(functinn(ret){
// 从resolve 得到正常结果
},function(ret){
//从reject得到错误信息
}
)
<script>
var p = new Promise(function(resolve,reject){
//这里用于实现异步任务
setTimeout(function(){
var flag = true
if(flag){
//正常情况
resolve("hello")
}else{
reject('出错了')
}
},100)
})
p.then(function(data){
console.log(data)
},function(info){
console.log(info)
})
基于promise处理ajax
<script>
/* 基于Promise发送Ajax请求 */
function queryData(){
var p = new Promise(function(resolve,reject){
var xhr = new XMLHttpRequest()
//当请求被发送到服务器时,我们需要执行一些基于响应的任务。
xhr.onreadystatechange = function(){
if(xhr.readyState != 4) return;
if(xhr.readyState == 4 && xhr.status == 200){
// 处理正常的情况
resolve(xhr.responseText)
}else{
//处理异常情况
reject('服务器错误')
}
};
xhr.open('get',url)
xhr.send(null)
})
return p
}
queryData('http://localhost:3000/data')
.then(function(data){
console.log(data)
},function(info){
console.log(info)
})
// 解决回调地狱
1. 返回值
queryData('http://localhost:3000/data')
.then(function){
return queryData('http://localhost:3000/data1)
}
// 调用的时 queryData('http://localhost:3000/data1)
.then(function(data){
})
</script>
then 参数中函数返回值
- 返回Promise实例对象
返回的该实例对象会调用下一个then
- 返回普通值
返回的普通值会直接传递给下一个then 通过then 参数中函数的参数接收该值
常用的API
p.then() 得到异步任务的正确结果
p.catch() 获取异常信息
p.finally() 成功与否都会执行( 尚且不是正式标准)
对象方法
Promise.all() 并发处理多个异步任务 所有任务都执行完成才能得到结果
Promise.reace() 并发处理多个异步任务,只要有一个任务完成就能得到结果
接口调用 - fetch 用法
fetch 概述
更加简单的数据获取方式,功能更加强大,更灵活,可以看做是xhr的升级版
基于 Promise 实现
fetch(url).then(function(data){
//text 方式属于fechAPI 一部分 它返回一个Promise实例对象 用于或是实例对象
return data.text())
}).then(function(data){
//这样才是真实的数据必须用data.text 返回
console.log(data)
})
fethc 请求参数
- 常用配置选项
method(Sting):HTTP 请求方式默认为GET(GET,POST,PUT,DELETE)
body(string):HTTP的请求参数
headers(Object):HTTP的请求头,默认为{}
fetch 响应数据
- text(): 将返回体处理成字符串类型
- json(): 返回结果和JSON.parse(responseText)一样
fetch(url).then(function(data){
//text 方式属于fechAPI 一部分 它返回一个Promise实例对象 用于或是实例对象
return data.json())
}).then(function(data){
//这样才是真实的数据必须用data.text 返回
console.log(data)
})
调用接口 - axios
支持浏览器和node.js
支持 Promise
能拦截请求和响应
自动转化JSON数据
axios.get('/adata')
.then(ret=>{
//data属性名称是固定的用法,用于获取后台的实际数据
console.log(ret.data)
})
参数传递:
get: 查询
axios.put('/adata/123',{
uname:'tom',
pwd:123
}).then(ret=>{
console.log(ret.data)
})
post: 添加数据
-
一个是 json 格式
-
另外一个是
var params = new URLSearchParams()
put: 修改数据
delete: 删除数据
响应结果
主要属性:
data: 实际响应回来的数据
headers: 响应头信息
status: 响应状态码
statusText: 响应状态信息
axios 的全局配置:
axios.defaults.timeout = 3000 // 超时时间
axios.defaults.baseURL = http://locallhost:3000/a00 // 默认地址
axios.defaults.headers[‘mytoken’] = ‘apwerwqer’ // 设置请求头
axios.defaults.baseURL = 'http://localhost://3000/'
axios.get('axios-json').then(function(ret){
console.log(ret.data.uname)
})
拦截器
请求拦截器
axios|拦截器|--------------》服务器
在请求发出之前设置一些信息
axios.interceptors.request.use(function(config){
//在请求发送之前进行一些信息
return config
},function(err){
//处理错误信息
})
响应拦截器
axios|响应拦截器|《-----------------服务器
axios.interceptors.response.use(function(res){
//在这里返回数据进行处理
return res
},
function(err){
//处理响应的错误信息
}
)
接口调用 - async/await 用法
ES7 引入
async function queryData(id){
const ret = awit axios,get('/data')
return ret
}
queryData.then(ret =》{
console.log(ret)
})
图书管理系统接口
- 图书列表数据加载 Get http://localhost:3000/books
- 添加图书 POST http://localhost:3000/books
- 验证图书名称是否存在 GET http://localhost:3000/books/book/:name
- 编辑图书 - 根据ID 查询图书信息 GET http://localhost:3000/books/:id
- 编辑图书- 提交图书信息 PUT http://locathost:3000/books/:id
- 删除图书 DELETE http://locathost:3000/books/:id
路由
后端路由:
概念:根据不同的用户URL请求,返回不同的内容
本质:URL 请求地址与服务器资源之间的对应关系
浏览器------------url地址---------------->后端路由------>服务器资源内容
服务器资源内容---------->后端路由------------->浏览器
前端路由:
概念: 根据不同的用户事件 显示不同的页面内容
本质: 用户事件与事件处理函数之间的对应关系
用户------触发事件-------》前端路由—事件处理函数
Vue router
支持HTML5 历史模式或hash 模式
支持嵌套路由
支持路由参数
支持编程式路由
支持命名路由
基本使用
引起相关的库文件
1 先引入 vue 在引入 vue-router
添加路由链接
router-link 是vue 中提供的标签 默认会被渲染为a 标签
to 属性默认被渲染成 href 属性
添加路由填充位
将来同那个路由规则匹配的组件到 router-view 所在的位置
router-view
定义路由组件
const user = {
template:'<h1> '
}
配置路由规则并创建路由实例
// 创建路由实例对象
var router = new VueRouter({
//router 是路由规则数组
routes:[
//每个路由规则都是一个配置对象其中包含 path 和 componter 两个属性
//path 表示当前路由规则匹配的 hash
//component 表示当前路规则对应要展示的组件
{path:'/user',component:user}
{path:'/regiser',component:regiser}
]
})
把路由挂载到Vue根实例中
new Vue({
el:’#app:}
router:router)
路由从定向
用户在访问地址A 的时候 强制用户跳转到地址 c 从而展示特点的组件页面
通过 redirect 属性
var router = new VueRouter({
routes:{
//其中 path 表示需要别重定向原地址 redirect 表示将要被重定向的新地址
{path:'/',redirect:'/user'}
{path:'user',component:user},
{path:'/register',component:register}
}
})
vue-router嵌套路由
1父路由组件模板
父级路由连接
父组件路由填充位
<P>
router-link to=‘/user'
router-ling to=‘/register’
</p>
<div>控制组件的显示位置
<router-view></router-view>
</div>
2 子路由模板
子级路由链接
子级路由填充位
const Register = {
template:"<div>
<h1> register 组件 </h1>
<hr/>
router-link to='/register/tabl'> Tabl <router-link
子路由填充位置
}
动态匹配路由
应用场景: 通过动态路由参数的模式进行路由匹配
var router = new VueRouter({
routes:[
// 动态路径参数 以冒号开头
{ path:'/user/:id',component:user}
]
})
const User = {
// 路由组件中通过$router.params 获取路由参数
template:'<div>User {{$route.params.id}}</div>'
}
$route 不够灵活一般使用 props 的值为布尔类型
const router = new VueRouter({
routes:[
// 如果 props 被设置为true ,route,params 将会被设置为 组件属性
{ path:'/user/:id',component: User,props:true}
]
})
const User = {
props:['id'].// 使用 props 接收路由参数
template:"<div> 用户{{id}} </div>" // 使用路由参数
}
命名路由
为了更加方便的表示路由的路径,可以给路由规则起一个别名,即为“命名路由”
const router = new VueRouter({
routes:[
{
path: '/user/;id',
name'"user",
component:user
}
]
})
案例:
- 路由的基础用法
- 嵌套路由
- 路由重定向
- 路由传参
- 编程式路由