创建项目 #

vue create <project>
cd project 
yarn install axios iview

使用iview #

在main.js引入iview

import iView from 'iview';
import 'iview/dist/styles/iview.css';
Vue.use(iView);

配置axios参数以及拦截器 #

对请求参数拦截器进行封装

import axios from 'axios';
import store from '../store';
import {getLocal} from '../libs/local'
class AjaxRequest{
    constructor(){ // 配置基本参数
        this.baseURL = process.NODE_ENV === 'production'?'/':'http://localhost:3000'
        this.timeout = 3000;
        this.queue = {};
    }
    merge(options){
        return {...options,baseURL:this.baseURL,timeout:this.timeout}
    }
    setIntercpetor(instance,url){
        // 请求前 执行此方法
        instance.interceptors.request.use(config=>{
            config.headers.authorization = getLocal('token');
            if(Object.keys(this.queue).length === 0){
                store.commit('show_loading')
            }
            this.queue[url] = url;
            return config;
        });
        // 请求后执行此方法
        instance.interceptors.response.use(res=>{
            store.commit('hide_loading')
            delete this.queue[url];
            if( Object.keys(this.queue).length === 0){
                store.commit('hide_loading')
            }
            return res.data;
        });
    }
    request(options){
        let instance = axios.create();
        let config = this.merge(options);
        this.setIntercpetor(instance,options.url);
        return instance(config); // axios();
    }
}
export default new AjaxRequest();

配置vuex存储用户状态 #

用户信息通过vuex来进行存储

import {login, validate} from './api/user'
import {setLocal} from './libs/local'
export default new Vuex.Store({
  state: {
    username:'', // 存储用户
    isShowLoading:false // 调用接口时是否显示loading
  },
  mutations: {
    hide_loading(state){
      state.isShowLoading = false;
    },
    show_loading(state){
      state.isShowLoading = true;
    },
    set_user(state,payload){
      state.username = payload
    }
  },
  actions: {
    async set_user({commit},username){
       let data = await login(username)
        if(data.code !== 0){
          return Promise.reject(data.data);
        }
        commit('set_user',data.username);
        setLocal('token',data.token);
    },
    async validate({commit}){
      let r = await validate();
      if(r.code === 0){
        commit('set_user',r.username);
        setLocal('token',r.token);
      }
      return r.code === 0;
    }
  }
})

全局拦截器配置 #

页面切换时进行权限获取

router.beforeEach(async (to,from,next)=>{
  let needLogin = to.matched.some(match=>match.meta.needLogin);
  let result = await store.dispatch('validate');
  if(needLogin){ // 需要登录
    if(result){
      next();
    }else{
      next({path:'/login'})
    }
  }else{ // 不需要登录
    if(result && to.path == '/login'){ // 已经登录而且还是login
      next({path:'/'});
    }else{
      next();
    }
  }
});

EventBus应用 #

// Boy组件 发射dinner事件
<template>
    <div>男孩
        <button @click="sayToGirl()">对女孩说话</button>
    </div>
</template>
<script>
export default {
    methods: {
        sayToGirl(){
           this.$bus.$emit('dinner','你饿吗');
        }
    }
}
</script>
// Girl组件 监听dinner事件
<template>
    <div>
    女孩 <span>男孩对我说: {{message}}</span>
    </div>
</template>


<script>
export default {
    data(){
        return {message:''}
    },
    mounted() {
        this.$bus.$on('dinner',(data)=>{
            this.message = data;
        })
    }
}
</script>

render函数 #

渲染dom元素 #

h('div',{
    class:'test',
    attrs:{
        id:1
    },
    style:{
        color:'red'
    },
    on:{
        click(){
            alert(1)
        }
    }
},'hello world');

渲染组件 #

h(Test,{
    props:{
      name:'zf'
    },
    on:{
        change(){
          alert('123')
        }
    },
    nativeOn:{
      click(){
        alert(1);
      }
    }
},'hello world')

render函数优势 #

Vue.component('MyTitle',{
  props:{
    level:{},
  },
  render(h){
    return h('h'+this._self.level,this.$slots.default)
  }
});
new Vue({
  router,
  store,
  render:h=>{
    return h('MyTitle',{
      props:{
        level:2
      }
    },'hello world')
  } 
}).$mount('#app');

用jsx改写 #

Vue.component('MyTitle',{
  props:{
    level:{},
  },
  render(h){
    let tag = 'h'+this.level;
    return <tag>{this.$slots.default}</tag>  
  }
});
new Vue({
  router,
  store,
  render:h=>{
    return <MyTitle level="1">hello world</MyTitle>  
  } 
}).$mount('#app');

函数式组件 #

通过render函数订制组件

<List :render="renderFn"></List>
import List from './components/List.vue';
export default {
  components:{
    List
  },
  methods:{
    renderFn:(h,name)=>{
      return <h1>{name}</h1>
    }
  }
}

// 通过函数式组件进行数据的转化
<template>
    <div>
        <div v-for="i in 3" :key="i">
            <div v-if="!render">{{i}}</div>
            <Functional v-else :render="render" :val="i"></Functional>
        </div>
    </div>
</template>
<script>
import Functional from './Functional.js'
export default {
   props:{
       render:{}
   },
   components:{
       Functional
   }
}
</script>

// 函数式组件
export default {
    functional:true,
    render:(h,ctx)=>{
        return ctx.props.render(h,ctx.props.val);
    }
}

可编辑表格 #

基于iview使用jsx扩展成可编辑的表格

<template>
     <Table height="200" :columns="innerColumn" :data="data"></Table>
</template>
<script>
export default {
    data(){
        return {innerColumn:[],index:-1,}
    },
    methods:{
        editor(key){
            this.index = key;
        },
        save(){
             this.index = -1;
        },
        change(row,column,value){
            row[column['key']] =value
        }
    },
    props:{
        column:{},
        data:{}
    },
    mounted(){
        this.innerColumn = this.column.map(item=>{
            if(item.edit){
                item.render = (h,{row,index,column})=>{
                    let flag = this.index== index
                    return <div>
                    {flag?
                    <i-input value={row[column['key']]} on-input={(value)=>{
                        this.change(row,column,value)
                    }}/>:
                    <span >{row[column['key']]}</span>
                    }
                       {!flag?
                        <i-button on-click={this.editor.bind(this,index)}>
                            编辑
                        </i-button>:
                         <i-button on-click={this.save.bind(this,index)}>
                            保存
                        </i-button>}
                     </div>
                }
                return item;
            }
            return item;
        })
    }
}
</script>