vue基础梳理_阶段1

vue基础

组件

组件制作

封装
// 定义Demo.vue ---------------------------------------------------------------
<template>
  <div class="container" @click="e=>onClick(e,'我是点击事件')">
      <div v-for="(item, index) in data" :key="index">
          {{item}}
      </div>
  </div>
</template>

<script>
export default {
  name:'Demo',
  props: {
    data: {
      type: Array,
      default: ()=>(['num1','num2','num3'])
    },
  },
  methods:{
      onClick(e,msg){
          console.log('event',e)
          console.log('msg',msg)
      }
  }
};
</script>
// 在home.vue中使用 ---------------------------------------------------------------
import Demo from '@/components/Demo.vue'
export default {
  name: 'home',
  components: {
    Demo
  }
}
// 非vue使用 ---------------------------------------------------------------
var vm = new Vue({
  el: '#example', // 挂在的dom节点
  template:'',
  data: data  // 绑定的数据
})
组件切换
// 情景1 ---------------------------------------------------------------
// html
 <component :is="comp" :data="data" msg="Welcome to Your Vue.js App"/>
// Js
props:{
    comp:{
      default:Demo
    }
  },
// 情景2  注意是字符串名-----------------------------------------------------
// html  <component :is="'Demo'" :data="data" msg="Welcome to Your Vue.js App"/>
// js
  import Demo from "@/components/Demo.vue";
  components: {
      Demo:Demo
  },
插槽
普通插槽
具名插槽
// 组件定义
<slot name="head"></slot>
// 使用
<comp>
   <template slot="head">
       <h3>window</h3>
   </template>
</comp>
自定义指令

(主要用来重构组件属性特质)

// 全局定义
Vue.directive('color-block', function (el, binding) {
  console.log('bind',binding)
  switch (binding.value) {
    case 'red':
      {
        el.style.backgroundColor = '#fddec4'
        el.style.border = '1px solid #ff6131'
      }
      break;
    case 'yellow':
      {
        el.style.backgroundColor = '#fbfdc4'
        el.style.border = '1px solid #ffd831'
      }
      break;
  }
})

// 使用
 <div v-color-block="'green'" class="a">{{data | toFixed }}</div>

组件通信

父子通信
父向子
// 父发送
<Demo :data="data" msg="Welcome to Your Vue.js App"/>
// 子接收
 props: {
    data: {
      type: Array,
      default: ()=>(['num1','num2','num3'])
    },
 }

子向父
// 子发送
handleClick(){
    this.$emit('childrenClick', this.emitData)
}
// 父接收
<Demo @childrenClick="onChildrenClick"/>
兄弟间通信
总线模式

(尽量不要用总线进行通信, 压平层级, 如果层级很深的话考虑provider和vuex )

建立总线
// 在main.js中
Vue.prototype.$bus = new Vue();
总线发射
 this.$bus.$emit('addGoods', good);
总线接收
created(){
    this.$bus.$on('addGoods',(good)=>{
        this.addCart(good)
    })
},
使用中介者模式
两个子组件绑定父组件的值, 修改时通过向父组件发送修改请求让父组件修改
多层级通信

(自己发送自己监听)

provider inject (祖 -> 孙)
// 父组件发送:  provider可以给所有子组件提供数据
 provide(){
     return {
         parentsKey:'祖先值'
     }
 }
// 后代组件接收
 inject:['parentsKey']
跨级修改 (孙-> 祖)

先引入一个向上递归查找的工具类

// 说明: 一直向上查找, 让名为"componentName"的祖组件发送一个名为"eventName"的事件并绑定参数
     $dispatch(componentName, eventName, params){
        let parent = this.$parent || this.$root;
        let name   = parent.$options.name;
        // 向上循环查找
        while(parent && (!name || name !== componentName)){
            parent = parent.$parent;
            if(parent){
                name = parent.$options.name;
            }
        }
        if(parent){
            parent.$emit.apply(parent,[eventName].concat(params));
        }
     }

 /* 使用(需先附加到总线 Vue.prototype.$dispatch=xxxx):
 后代元素: this.$dispatch.bind(this)('formItem','doValidate',this.inputValue);
 祖先元素:
    created(){
          this.$on('doValidate',this.doValidate);
    } 
*/

数据过滤

计算: computed

适用场景: 根据一个数据生成另一个数据

// 普通模式 
computed:{
    reMsg(){
        return this.msg.split('').reverse().join('')
    }
}
// 高级模式 (先get值后set) 
computed:{
     reMsg:{
         get:function(){
             return this.msg.split('').reverse().join('')
         },
         set:function(value){
             this.msg = value; //最后修改了msg    
         }
     }
 }

侦听:watch

适用于订阅性质的处理

    data(){
        return{
            msg:''
        }
    },
    watch:{
        msg:{
            handler(new,old){
                // msg变量更改后触发
            },
            deep:true  //深度观察, 对象里面的变动也会触发
        },
        $route(){
           // 路由信息变化就会引发此函数     
        }
    }

响应式赋值

(一般用于给对象对象内部元素赋值, 直接赋值对象一般不会触发响应式)

// $set是Vue.set的别名
this.$set(this.obj, k, v)
Vue.set(this.obj, k, v)

this.$delete(this.obj, k)
Vue.delete(this.obj, k)

// 全局使用
Vue.set(target, 'key', value)
Vue.set(_this.data[4].avatarAfter,'title',hiddenPhone(value))

大批量处理时候可以借助assign

vm.userProfile = Object.assign({}, vm.userProfile, {
  age: 27,
  favoriteColor: 'Vue Green'
})
this.userProfile = userProfile;

过滤器(针对template)

// 组件内定义
export default {
    filters:{
        toFix: function(value,places) {
      		if (!value) return "";
      		return (+value).toFixed(places);
   		}
    }
}
// 全局定义, 在普通Js文件中
Vue.filter('toFixed', function (value,places=2) {
  return (+value).toFixed(places);
})


// 使用方式相同
<div>{{data | toFix(2)}}</div>
<div :id="rawId | toFix(2)"></div>


状态管理

模块化构建

module/home.js

import router from '@/router';
const home = {
    state: {
        router: router,
        selectedLabel:'进行中',
        navOffset:150,
      },
      mutations: {
        go(path) {
          this.state.path = path;
        },
        changeLabel(state, newLabel){
          state.selectedLabel = newLabel;
        },
        clearNavOffset(state){
          state.navOffset = 0;
        }
      }
}

export default home;

index.js

// import Vue from 'vue';
// import Vuex from 'vuex';
import home  from './modules/home';
import user  from './modules/user';
// Vue.use(Vuex);   // 使用cdn替换


const store = new Vuex.Store({
  modules: {
    home,
    user
  }
})
export default store;

state操作

// 取 ---------------------------------------------------------------
this.$store.state.user.authState
// 用map取
computed: {
    ...mapState({
        authState: state => state.user.authState
    })
}
// 存 (mutation合并到vuex的根下)
this.$store.commit("changeLabel", 'key_1');

// map操作
methods: {
    ...mapMutations(['increase'])
}

/* 技巧: data中直接用this.$store.user.authState更改值不触发响应式变更, 可以用watch配合更改data中的值

  watch: {
    authState(newValue) {
      this.data[2].avatarAfter.title = newValue;
    }
  }
  
 */

action操作

// 定义
actions: {
    increaseAsync({state, commit},asyncValue){
        setTimeout(() => {
          commit('increase',asyncValue)
        }, 2000);
    }
  }
// 使用
 this.$store.dispatch('increaseAsync',4);
// map操作
 methods: {
    ...mapActions(['increaseAsync'])
}

Getters操作

(相当于vuex中的computed)

// 定义 ---------------------------------------------------------------
state:{
		 // 应用启动时, count置为0
		count:0,
		todos: [
			{ id: 1, text: '水果类', done: true },
			{ id: 2, text: '苹果', done: true }
	    ]
},
getters: {
		doneTodos: state => {//通过方法访问
		  return state.todos.filter(todo => todo.done)
		}
}
// 使用, 直接当变量用即可
 computed: {
     ...mapGetters(['doneTodos'])  // 模块化时候不用像state那样分组
 }

let tok =store.getters.getToken;  // 模块化时候不分组

订阅, 同步localStorage

store.js文件中
store.subscribe((mutation, state)=>{
    switch(mutation.type){
        case 'setToken':
            localStorage.setItem('token',Json.stringfy(state.token))
            break;
    }
})

路由

模块化构建

module/project.js

import ProjectLayout from 'views/layouts/ProjectLayout';

const routes = [
  {
    path: '/project',
    name: 'project',
    component:ProjectLayout,
    children:[
      {
        path:'award',
        name:'projectAward',
        component:()=>import('views/ProjectAward')
      },
      {
        path:'detail',
        name:'projectDetail',
        component:()=>import('views/ProjectDetail')
      }
    ]
  }
]

export default routes

routes.js

import root from './modules/root';
import user from './modules/user';
import order from './modules/order';
import project from './modules/project';
import system from './modules/system';

export default [
  ...root,
  ...user,
  ...order,
  ...project,
  ...system,
  {
    path:'/login/:id?',
    name:'login',
    component:()=>import(/* webpackChunkName:'login'*/'views/Login')
  },
  {
    path: '*',
    redirect: '/home'
  }
]

index.js

import Vue from 'vue';
import Router from 'vue-router';
import routes from './routes';

// Vue.use(Router);
// https://router.vuejs.org/zh-cn/api/options.html
const router = new Router({
  // mode: 'history',
  routes

  // base: '/',
  // linkActiveClass: 'router-link-active',
  // linkExactActiveClass: 'router-link-exact-active',
  // fallback: true,
});
// 全局守卫
router.beforeEach((to, from, next) => {
  // 登录鉴权
  if (to.meta.auth) {
    doLogin();
    return;
  }
  next();
});

function doLogin() {
  router.push('/login')
}
export default router;

参数处理

params参数
// 方案一 (推荐) ---------------------------------------------------------------
// 路由配置(加接参配置)
  {
     path: '/describe/:id?',
     name: 'Describe',
     component: Describe
   }
// 传参
this.$router.push({
    path: `/describe/${id}`,
})
// 提取参数
this.$route.params.xxx

// 方案二 ---------------------------------------------------------------
// 路由配置(不加接参配置)
{
     path: '/describe',
     name: 'Describe',
     component: Describe
 }
// 传参
this.$router.push({
    name: 'Describe',
    params: {
        id: id
    }
})
// 提取参数
this.$route.params.xxx
query参数
// 标签传参
<route-link :to=`/path/path?id=${id}` >我是跳转链接</router-link>
// 跳转传参
this.$router.push({
    path: '/describe',
    query: {
        id: id
    }
})

// 提取参数
this.$route.query.id

路由重定向

// 重定向
doLogin(){
    store.state.isLogin=false;
    router.replace({
         path:'/login',
        query:{
            redirect:router.currentRoute.fullPath
        }
    })
}

// 跳转
{
    path:'/lesson/2?redirect='+to.path
}
// 提取
const {redirect} = this.$route.query;
if(redirect){
    this.$router.push(redirect);
}else{
    this.$router.push('/')
}

子路由

children:[
    {
        path: routInfo.lesson3.routePath,
        name: routInfo.lesson3.name,
        component: Lesson3
    }
]
// 注意 需要在此路由中放入
<router-view></router-view> // 路由视图

路由守卫

全局级守卫
const router = new Router({
  // mode: 'history',
  routes
});
router.beforeEach((to, from, next) => {
   // 全局鉴权
});

// 其他
afterEach  // 适合做历史记录自定义堆栈
beforeRouteUpdate // 仅路由参数变更时触发
路由级守卫
// 路由中放入钩子
{
    path:'xxx',
    name:'xxx',
    component:()=>import('@/xxx')   // 懒加载
    beforeEnter(to, from, next){
        
    }
}
组件级守卫
beforeRouteEnter
beforeRouteUpdate 
beforeRouteLeave

export default {
    name: "Admin",
    data(){
        return{
            infor:'hw'
        }
    },
    beforeRouteEnter:(to,from,next)=>{
        //此时该组件还没被实例化
        alert(this.infor);       //弹出消息框信息为 undefined
        next(vm =>{
            //此时该组件被实例化了
            alert(vm.infor);         //弹出消息框信息为 hw
        })
    }
}

动画

基本形式

// 注意: 进行动画的组件或视图请使用position:absolute
<transition name="fade" mode="out-in" appear>
  <component :is="view"></component>
</transition>

// 常用类名 ---------------------------------------------------------------
v-enter{}
v-leave-to{}
v-enter-active,v-leave-active{
    
}
// 常用api ---------------------------------------------------------------
mode="in-out"
appear  // 是否页面一加载就执行
enter-active-class="animated bounceInUp"  // 进入时的动画 常配合anmate.css
leave-active-class="animated swing" // 离开时的动画
appear-active-class="animated swing"  // 刷新页面时的开始动画样式
// 常用过度动画
transform: translate3d(100%,0,0)  // 配合position:absolute

// js动画钩子 ---------------------------------------------------------------
@before-enter="beforeEnter"
@enter="enter"
@after-enter-"afterEnter"

异步

async await

async getGoodsData(){
    try {
        const res            = await axios.get('/api/goods');
        this.goodsData = res.data.list;
    } catch (error) {
        console.log(error);
    }
}

promistAll

Api

生命周期

// 创建
beforeCreate
created   // 一般可以用来发送异步请求, 放置监听总线事件
// 挂载
beforeMount
mounted
// 刷新
beforeUpdate
updated
// 销毁
beforeDestroyed  // 一般用来销毁计时器和echarts
destroyed

路由

router.go() // 历史记录上前进异步
router.replace() // 替换掉本条历史记录, 常用来做Login鉴权

原型链api

this.$parent
this.$router
this.$route
this.$emit()
this.$refs
this.$nextTick()

绑定类api

// 属性
:class="{ 'active': isActive, 'text-danger': hasError }"
// 事件
@click="e=>handleClick(e,params)"

v指令

v-for: <Comp v-for="(todo,index) in todos" :key="index"/>
v-model: <input v-model="message">
v-once: <span v-once>这个将不会改变: {{ msg }}</span>
v-show: 只是切换display 不删除节点
v-if="" && v-else-if && v-else  // 如果要切换多个元素可以使用template


修饰符

// 按键修饰符 ---------------------------------------------------------------
// keycode数字
	<input @keyup.13="submit">
// keycode别名
	<input @keyup.enter="submit">
/* 常用
.enter
.tab
.delete (捕获“删除”和“退格”键)
.esc
.space
.up
.down
.left
.right
*/
// 事件修饰符 ---------------------------------------------------------------
	<form @submit.prevent="onSubmit">...</form>
/* 常用
.stop           阻止事件冒泡
.prevent    阻止默认事件
.capture
.self            只有是自身元素时候才触发
.once          只触发一次
.passive
*/
// 命令键修饰符 ---------------------------------------------------------------
    <input @keyup.alt.67="clear">  // alt+c
/* 常用
.ctrl
.alt
.shift
.meta
*/
// 鼠标键修饰符 ---------------------------------------------------------------
/* 常用
.left
.right
.middle
*/

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值