vue-cli 脚手架:
1.生成目录结构
2.本地开发调试
3.代码部署
4.热加载
5.单元测试
前端路由:在web开发中,路由是指根据url分配到对应的处理程序。
vue-router
作用:通过管理url,实现url和组件的对应和通过url进行组件之间的切换。
单页应用(SPA):加载单个HTML页面,并在用户与应用程序交互时动态更新该页面。
vue-router使用步骤:
安装模块:npm install vue-router --save
引入模块:import VueRouter from 'vue-router'
作为Vue插件:Vue.use(VueRouter)
创建路由实例对象:
new VueRouter({
mode: 'history',//hash模式和history模式;
...配置参数
})
注入Vue选项参数:
new Vue({
router
})
告诉路由渲染的位置:
hash模式和history模式:
mode: 'history',
router-link:
to/tag/event/exact
嵌套路由:
routes:[
{
path: '/home',
//name:'Home',
component: Home,
alias: '/index' //别名
children: [
{
path:'', //默认的子路由 /home
name:'Home',
component:Home,
},
{
path:'study', //home/study
//path:'/study', //study
name:'Study',
component:Study
},
{
path:'/document',
name:'Document',
components:{
default: Document, //默认
slider: Slider //新建
}
}
]
}
]
命名视图:
重定向(方式):
redirect:'/home'
redirect:{path:'/home'}
redirect:{name: 'Home'}
redirect: (to) =>{ //动态设置重定向的目标
//目标路由对象,就是访问的路径的路由信息
return '/Home'
}
redirect: (to) =>{ //动态设置重定向的目标
//目标路由对象,就是访问的路径的路由信息
if(to.path === '/123'){
return '/home'
}else if(to.path === '/456'){
return {path: '/document'}
}else{
return {name: 'Home'}
}
}
滚动行为:①
scrollBehavior(to,from,savePosition){ //点击浏览器的前进后退或切换导航触发
console.log(to); // 要进入的目标路由对象 要去向哪里
console.log(from); // 离开的路由对象 从哪里来
console.log(savePosition); // 记录滚动条坐标 点击前进后退的时候记录值
if(savePosition){
return savePosition;
}else {
return {x:0, y:0}
}
}
②
scrollBehavior(to,from,savePosition){ //点击浏览器的前进后退或切换导航触发
if(to.hash){
return {
selector: to.hash
}
}
}
动态路径:
匹配到的所有路由,全都映射到同一个组件
路径: /user/:userId suerId为动态路径参数
获取参数:路由信息对象的params
{ path:'/user/:userId?', // /user/1 /suer/2 /user
component: User}
created(){ //生命周期钩子函数
console.log(this.$router)
console.log(this.$router)
}
对组件注入:
通过在Vue根实例的router配置传入router实例
$router router实例
$route 当前激活的路由信息对象,每个组件实例都会有。
beforeRouterEnter() 进入组件前钩子函数
beforeRouteLeave() 离开组件前钩子函数
路由信息对象:
一个路由信息对象表示当前激活的路由的状态信息,每次成功的导航后都会产生一个新对象
path 字符串,对应当前路由的路径
params对象,包含动态路由参数
query对象,URL查询参数
hash字符串,当前路由的hash值
fullPath 字符串,URL包含查询参数和hash的完整路径
matched数组,包含当前路由的所有嵌套路径片段的路由记录
name字符串,当前路由的名称
{ path:'/user/:tip?/:userId?', // /user/vip/1 /user/common/2 /user
component: User
}
created(){
//渲染这个组件会调用一次这个生命周期函数
//复用这个组件,这个函数不会再次被调用了
//地址一旦发生变化,$route会重新生成一个路由信息对象
console.log(this.$route)
console.log(this.$route.params.userId)
this.getData()
}
watch:{
$route(){
//路径发生变化,$route会重新赋值,监控这个属性
console.log("监控$route")
console.log(this.$route.params.userId)
this.getData()
}
},
query字符串传参:
过渡动效:
提供了transition的封装组件,添加过渡动画
添加删除css类名
过度的css类名:
v-enter: 定义进入过渡的开始状态
v-enter-active:定义进入活动状态
v-enter-to:定义进入的结束状态
v-leave: 定义离开过渡的开始状态
v-leave-active: 定义离开活动状态
v-leave-to: 定义离开的结束状态
使用name属性改变类名前缀
过渡模式:
in-out: 新元素先进行过渡,完成之后当前元素过渡离开
out-in: 当前元素先进行过渡,完成之后新元素过渡进入
动态设置name属性
.left-enter{ transform: translateX(100%); } .left-enter-to{ transform: translateX(0); } .left-enter-active{ transition: 1s; }
路由元信息:
在路由配置中meta可以配置一些数据,用在路由信息对象中
访问meta中数据:$route.meta
{ path: '/home',
component: Home,
meta:{
index:0
}
},
当前导航下标:{{$route.meta.index}}
data(){
return{
index:'/home',
names:'left'
}
},
watch:{
$route(to,from){
console.log(to.meta.index); //目标导航下标
console.log(from.meta.index); //离开导航下标
if(to.meta.index < from.meta.index){
this.names = 'right'
}else{
this.names = "left"
}
}
}
编程式导航:
借助于router的实例方法,通过编写代码来实现导航的切换
back 后退一步
forward 前进一步
go 指定前进回退步数 //go(0)刷新当前页
push 导航到不同url,向history栈添加一个新的记录
replace 导航到不同url,替换history栈中当前记录
methods:{
backHandle(){
this.$router.back()
},
frowardHandle(){
this.$router.forward()
},
pushHandle(){
this.$router.push('/home')
this.$router.push({path:'/document'})
},
replaceHandle(){
this.$router.replace({path:'/document'})
}
},
导航钩子函数:
导航发生变化时,导航钩子主要用来拦截导航,让它完成跳转或取消
执行钩子函数位置:
router全局
单个路由
组件中
钩子函数
router实例上:beforeEach、afterEach
单个路由中:beforeEnter
组件内的钩子:beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave
钩子函数接收的参数:
to: 要进入的目标 路由对象 到哪里去
from: 正要离开导航的路由对象,从哪里来
next: 用来决定跳转或取消导航
全局钩子函数:
router.beforeEach((to,from,next) =>{
//next()
//next(false);//取消导航
})
meta:{
index:1;
login:true,
title:'home'
}
router.beforeEach((to,from,next) =>{
if(to.meta.login){
next('/login')
}else{
next()
}
})
router.afterEach((to,from) =>{
if(to.meta.title){
window.document.title = to.meta.title;
}else{
window.document.title = 'miaomiao';
}
})
某个单独的路由设置钩子函数:
{
path:'/document',
name:'Document',
beforeEnter(to,from,next){
next();
}
component: Document,
meta:{
index:1,
title:'document'
}
},
组件级钩子函数:
//beforeRouteEnter先于beforeCreate前执行;
export default {
name: "About",
data(){
return{
test: '改变前'
}
},
beforeCreate(){
console.log('beforeCreate')
},
beforeRouteEnter(to,from,next){
console.log('beforeRouteEnter')
console.log(this)
next((vm)=>{
vm.test = "改变了"
})
},
beforeRouteUpdate(to,from,next){
next()
},
beforeRouteLeave(to,from,next){
next()
}
}
懒加载:
把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件
Vue 异步组件
{
components:{
custom:(resolve,reject) => {}
}
}
webpack代码分割功能
require.ensure代码分块
require.ensure(依赖,回调函数,[chunk名字])
import函数
①import Header from '@/components/Header'
components:{
// HeaderNav: Header
headerNav: (resolve)=>{
setTimeout(() =>{
resolve(Header)
},2000)
}
},
②components:{
// HeaderNav: Header
headerNav: (resolve)=>{
setTimeout(() =>{
resolve(require('@/components/header'))
},2000)
}
},
// import Layout from '@/components/Project' == //懒加载方式
// import Doc from '@/components/Doc'
let Layout = (resolve)=>{
return require.ensure([],()=>{
resolve(require('@/components/Project'))
})
}
let Doc = (resolve)=>{
return require.ensure([],()=>{
resolve(require('@/components/Doc'))
})
}
合并成一个JS文件
let Layout = (resolve)=>{
return require.ensure([],()=>{
resolve(require('@/components/Project'))
},"abc')
}
let Doc = (resolve)=>{
return require.ensure([],()=>{
resolve(require('@/components/Doc'))
},'abc')
}
import方式:(目前不能同时加载多个)
let Doc = (resolve)=>{
return import('@/components/Doc'))
}
打包:
npm run build
服务器配置:
Nginx配置:
location/{
root/home/我的应用根目录;
try_files $url $url//index.html =404;
}
Appache配置:
RewriteEngine On
RewriteBase /
RewriteRule ^index\.html$ [L]
RewriteCond %[REQUEST_FILENAME] !-f
RewriteCond %[REQUEST_FILENAME] !-d
RewriteRule .index.html [L]
Vuex:
Vuex 是什么:
专为Vue.js应用程序开发的状态管理模式
采用集中式存储管理应用的所有组件的状态
以相应的规则保证状态以一种可预测的方式发生变化
状态:
组件内部状态:仅在一个组件内使用的状态(data字段)
应用级别状态:多个组件共用的状态
什么情况下使用 Vuex
多个视图依赖于同一状态
来自不同视图的行为需要变更同一状态
使用Vuex :
安装vuex模块
npm install vuex --save
作为插件使用
Vue.use(Vuex)
定义容器
new Vuex.Store()
注入根实例
{
store
}
Vuex 核心概念
store: 类似容器,包含应用的大部分状态
一个页面只能有一个store
状态存储是响应式的
不能直接改变store中的状态,唯一途径显示地提交mutations
State: 包含所有应用级别状态的对象
Getters: 在组件内部获取store 中状态的函数
Mutations: 唯一修改状态的事件回调函数
Actions:包含异步操作、提交mutation改变状态
Modules: 将store分割成不同的模块
import Vuex from 'vuex'
Vue.use(Vuex)
//定义一个容器
let store = new Vuex.Store({
state:{
count: 1000
},
mutations:{
addIncrement(state,payload){
state.count += payload.n;
},
deIncrement(state){
state.count -= 1
},
deIncrement(state,payload){
state.count -= payload.de
}
}
})
export default store;
{{num}}
methods:{
addHandle(){
//改变状态,提交mutation addIncrement
this.$store.commit("addIncrement",{
n: 5
})
},
deHandle(){
this.$store.commit("deIncrement")
},
deHandle(){
this.$store.commit({
type: 'deIncrement',
de: 10
})
}
},
computed:{
num(){
return this.$store.state.count
}
}
异步改变:
mutations:{
addIncrement(state, payload){
state.count += payload.n;
},
deIncrement(state,payload){
state.count -= payload.de
}
},
actions:{
addAction(context){
setTimeout(()=>{
//改变状态,提交mutations
context.commit("addIncrement",{n:5})
},1000)
}
}
addHandle(){
//改变状态,提交mutation addIncrement
/*this.$store.commit("addIncrement",{
n: 5
})*/
//触发一个action
this.$store.dispatch("addAction")
},
actions:{
addAction(context){
setTimeout(()=>{
//改变状态,提交mutations
context.commit("addIncrement",{n:5})
},1000)
}
}
action异步操作:
actions:{
addAction(context){
console.log(context);
setTimeout(()=>{
//改变状态,提交mutations
context.commit("addIncrement",{n:5})
context.dispatch("textAction",{text:"测试"})
},1000)
},
textAction(context,obj){
console.log(obj)
}
}
actions:{
addAction({commit,dispatch}){
setTimeout(()=>{
commit("addIncrement",{n:5})
dispatch("textAction",{text:"测试"})
},1000)
},
textAction(context,obj){
console.log(obj)
}
}
getter 计算状态:
let store = new Vuex.Store({
state:{
count: 100
},
getters:{
filterCount(state){
return state.count > 120 ? 120 : state.count;
}
},
mutations:{
addIncrement(state, payload){
state.count += payload.n;
},
deIncrement(state,payload){
state.count -= payload.de
}
},
actions:{
addAction({commit,dispatch}){
setTimeout(()=>{
commit("addIncrement",{n:5})
dispatch("textAction",{text:"测试"})
},1000)
},
textAction(context,obj){
console.log(obj)
}
}
})
export default store;
{{num}}
{{num2}}
computed:{
num(){
return this.$store.state.count
},
num2(){
return this.$store.getters.filterCount
}
}
Vuex 的流程图:
vue调试工具:
Vuex 辅助函数:
mapState
mapGetters
mapMutations
mapActions
import {mapState} from 'vuex'
export default {
name: "Increment",
computed: mapState({
// num: state => state.count
// num: 'count'
num(state){
return state.count + 100
}
}),
}
computed: mapState(['count'])
修改{{count}} //传参
import {mapState,mapGetters,mapActions,mapMutations} from 'vuex'
export default {
computed:{
abc(){
return 123
},
...mapState(['count']),
...mapGetters({
num2: 'filterCount'
})
},
methods:{
...mapActions({
addHandle: 'addAction'
}),
...mapMutations({
deHandle:'deIncrement'
})
},
}
easy-mock.com 创建模拟接口
npm install axios --save
代码:
store/index.js:
import Vue from 'vue'
import Vuex from 'vuex'
import Axios from 'axios'
Vue.use(Vuex)
// 划分模块
/*let selectModule = {
state:{
title: 'hello',
list:[]
},
mutations:{
changeTitle(state,payload){
state.title = payload.title
},
changeList(state,list){
state.list = list
}
},
actions:{
getListAction({commit}){
//发送请求
Axios.get('http://www.phonegap100.com/appapi.php?a=getPortalList&catid=20&page=1')
.then((data) =>{
console.log(data.data.result)
commit("changeList",data.data.result)
})
.catch((error)=>{
console.log(error)
})
}
}
}*/
// this.$store.state.title
// this.$store.state.selectModule.title
//定义一个容器
let store = new Vuex.Store({
modules:{
// selectModule
},
state:{
count: 100,
title: '',
list: []
},
getters:{
filterCount(state){
return state.count > 120 ? 120 : state.count;
}
},
mutations:{
addIncrement(state, payload){
state.count += payload.n;
},
deIncrement(state,payload){
state.count -= payload.de
},
changeTitle(state,payload){
state.title = payload.title
},
changeList(state,list){
state.list = list
}
},
actions:{
addAction({commit,dispatch}){
// console.log(context);
setTimeout(()=>{
//改变状态,提交mutations
commit("addIncrement",{n:5})
dispatch("textAction",{text:"测试"})
},1000)
},
textAction(context,obj){
console.log(obj)
},
getListAction({commit}){
//发送请求
Axios.get('http://www.phonegap100.com/appapi.php?a=getPortalList&catid=20&page=1')
.then((data) =>{
console.log(data.data.result)
commit("changeList",data.data.result)
})
.catch((error)=>{
console.log(error)
})
}
}
})
export default store;
Select.vue:
List.vue:
- {{item.title}}
SelectInput.vue:
划分模块module:
例:
let selectModule = {
state:{
title: 'hello',
list:[]
},
mutations:{
changeTitle(state,payload){
state.title = payload.title
},
changeList(state,list){
state.list = list
}
},
actions:{
getListAction({commit}){
//发送请求
Axios.get('http://www.phonegap100.com/appapi.php?a=getPortalList&catid=20&page=1')
.then((data) =>{
console.log(data.data.result)
commit("changeList",data.data.result)
})
.catch((error)=>{
console.log(error)
})
}
}
}
let store = new Vuex.Store({
modules:{
selectModule
},
})
export default store;
注意取值:
// this.$store.state.title = > // this.$store.state.selectModule.title
Axios
简介:
基于Promise 用于浏览器和nodejs的与服务端通信库
特征:
支持Promise API
拦截请求和相应
转换请求和响应数据
取消请求
自动转换JSON 数据
使用:
$ npm install axios --save
CDN地址:https://unpkg.com/axios/dist/axios.min.js
Mock 模拟数据:
http://easy-mock.com
使用axios
需要的模块中引入使用:
import axios from 'axios'
语法:
1.axios(config)
2.axios[method]()
返回值为 promise
支持的请求方式:
axios.get(url[,config])
axios.post(url[,data[,config]])
axios.delete(url[,config])
axios.head(url[,config])
axios.options(url[,config])
axios.put(url[,data[,config]])
axios.patch(url[,data[,config]])
import axios from 'axios'
created(){
/*axios.get('http://www.phonegap100.com/appapi.php',{
params:{
a: 'getPortalList',
catid: '20',
page: '1'
}
})*/
axios({
method: 'get',
url: 'http://www.phonegap100.com/appapi.php?a=getPortalList&catid=20&page=1'
})
.then((response) =>{
console.log(response)
})
.catch((error)=>{
console.log(error)
})
}
自定义请求实例:
创建:
axios.create(config)
配置:
{
baseURL: '',
timeout:1000,
headers:{},
reaponseType: 'json',
params:{},
transformRequest:[] //只适合PUT、POST和PATCH
transformResponse:[]
validateStatus: function(){ }
cancelToken
}
import axios from 'axios'
var HTTP = axios.create({
baseURL:'',
timeout: 1000,
headers: {
'custom-header':''
},
responseType: 'json',
params: { }
})
created(){
HTTP.get("")
.then((response) =>{
console.log(response.data)
})
.catch((error)=>{
console.log(error)
})
}
取消请求:
创建取消请求令牌:
var CancelToken = axios.CancelToken;
var source = CancelToken.source();
配置
cancelToken: source.token
捕获取消错误
if(axios.isCancel(error)){
console.log(error.message);
}
调用取消
source.cancel('操作被用户取消')
并发请求;
请求;
axios.all(iterable)
axios.spread(callback)
created(){
function http1(){
return HTTP.get("")
}
function http2(){
return HTTP.post("")
}
axios.all([http1(),http2()]).then((response)=>{
console.log(response)
})
.catch((error)=>{
if(axios.isCancel(error)){
console.log(error.message);
}else{
console.log(error)
}
})
}
axios.all([http1(),http2()]).then(axios.spread((res1,res2)=>{
console.log(res1)
console.log(res1)
}))
.catch((error)=>{
if(axios.isCancel(error)){
console.log(error.message);
}else{
console.log(error)
}
})
拦截器:
全局拦截:
拦截请求
axios.interceptors.request.use(function(config){
//在发送请求之前做某事
return config;
},function(error){
//请求错误时做某事
return Promise.reject(error);
});
拦截响应
axios.interceptors.response.use()
取消拦截:
axios.interceptors.request.eject(myInterceptor);
例
HTTP.interceptors.request.use(function(config){
//在发送请求之前做某事
console.log(config)
return config;
},function(error){
//请求错误时做某事
return Promise.reject(error);
});
HTTP.interceptors.response.use(function(data){
console.log(data);
return data;
})
在vue 中使用
安装:
npm install axios vue-axios --save
作为插件
Vue.use(VueAxios,Axios)
在组件中使用
this.$http[method]()
import Axios from 'axios'
import VueAxios from 'vue-axios'
Vue.use(VueAxios, Axios)
import Axios from 'axios'
methods:{
getData(){
//请求数据
var api='http://www.phonegap100.com/appapi.php?a=getPortalList&catid=20&page=1';
this.$http.get(api).then(function(response){
console.log(response);
//注意this指向
this.list=response.body.result;
}, function (err) {
console.log(err)
})
},
getData2(){
var api2='http://www.phonegap100.com/appapi.php?a=getPortalList&catid=20&page=1';
Axios.get(api2).then((response)=>{
console.log(response)
this.list2=response.data.result;
}).catch((error)=>{
console.log(error)
})
}
},
mounted(){ /*生命周期函数*/
this.getData();
this.getData2()
}
vue 的几个特点: 1.应用范围广 2.生态环境好 3.代码轻量(vuejs的底层帮助我们做了很多事情) 4.上手简单,使用容易(使用react要学习JSX语法、es6语法,angular要学习TypeScript语法) 学习NUXT框架、WEEX框架: v-once指令,; rawHTML、v-html="rawHTML"; v-if 和 v-show 区别: key=index 与 key=id 区别; v-for="(item,index) in list" :key="index" :key="item.id" 数组不能根据索引改变值 Vue.set(vm.list, 3, {id:'1004',text:'明天见!'} ) vm.$set(vm.list, 4, {id:'1005',text:'后天见!'} ) vm.list.splice(3, 1, {id:'1004',text:'明天见!'} ) 循环对象 v-for="(item,key,index) in userInfo" Vue.set(vm.userInfo, 'age', '20' ) vm.$set(vm.userInfo, 'country', 'china' ) is特性/data项: