vue.js进阶

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}
    }
  }

Document

定位到这个元素

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:





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项:
Vue.component('child',{ data:function(){ return{ content: 'this is a row' } }, template:'{{content}}' }) ref特性:
this is a content of div
methods:{ handleDivClick: function(){ console.log(this.$refs.div) } }, 父子组件传值;组件prop校验;prop特性: $emit() 组件原生事件绑定;非父子组件传值: vuex 插槽; 单个插槽 slot 多个插槽
this is header
作用域插槽 Vue.component('child',{ template:'
' }) v-once 指令: 钩子函数: @before-enter="handleBeforeEnter"; @enter="handleEnter"; @after-enter="handleAfterEnter"; @before-leave="handleBeforeLeave"; @leave="handleLeave"; @after-leave="handleAfterLeave"; handleBeforeEnter:function (el) { console.log(el) el.style.color="red" }, handleEnter:function (el,done) { console.log(el) setTimeout(function(){ el.style.color="yellow" },1000) setTimeout(function(){ done() },2000) } handleAfterEnter:function (el) { console.log(el) el.style.color="blue" } 学习 velocity.js 库: 多个元素或组件的过渡: Vue.component('child',{ template:'
child-one
' }) 列表过渡:
  • {{item.text}}
  • 动画封装:
    hello from div
    Vue.component('fade',{ props:['show'], template: '', methods:{ handleBeforeEnter:function (el) { el.style.opacity= 0; console.log("进场动画即将执行") }, handleEnter:function (el,done) { Velocity(el,{ opacity:1 },{ duration:3000, complete:done }) console.log("进场动画执行中") }, handleAfterEnter:function (el) { console.log("进场动画执行完毕") } } })

    你可能感兴趣的:(vue,Vuex,vue,vuex,axios)