Vue常见问题

140 阅读4分钟

vue常见问题收集

打工累吗?累呀。但是我不能哭,因为骑电动车的时候擦眼泪不安全。早安,打工人!!!

vue组件之间传值

1、父传子

这种传值比较简单,子组件只需用props将父组件传递过来的数据接收,即可使用

//父组件代码
<p>父组件<p>
<input type="text" v-model="parentData">
<Children :parentData="parentData"></Children>
----------------子组件代码------------------
props:{
    parentData:{type:String,required:true}
}

2、子传父

子组件传值给父组件需要提交(this.$emit)一个自定义的方法,父组件监听这个方法来获得子组件传过来的值。

//-----------子组件代码----------
<p><input type="text" v-model="childrenData"></p>
<p><button @click="handelChildren">点击传值给父组件</button></p>
export default{
    name:'Children',
    data(){
        return{
            childrenData:''
        }
    },
    methods:{
        handelChildren(){
            this.$emit('onSetData',this.childrenData)
        }
    }
}
//----------------父组件代码-----------------
<Children @onSetData="handelSetData"></Children>
export default{
    name:'Parent',
    data(){
        return{
            number:''
        }
    },
    methods:{
        handelSetData(val){
            this.number = val
        }
    }
}

3、 $refs

父组件通过$refs获取子组件的数据和方法:在调用子组件的时候写入一个ref="xxx",在父组件中通过this.$refs.xxx.属性可以直接获取子组件的值,this.$refs.xxx.方法通过方法传参,可以实现父组件给子组件传值

//----------------父组件代码-----------------
<template>
    <div>
        <children-comp ref="child"></children-comp>
        <button @click="getChildProp()">获取子组件的属性值</button>
        <button @click="getChildMethod()">获取子组件的方法</button>
    </div>
</template>
<script>
import ChildrenComp from './ChildrenComp.vue'
export default{
    components:{
        ChildrenComp
    },
    data(){
        return{}
    },
    methods:{
        getChildProp(){
            alert(this.$refs.child.msg);
        },
        getChildMethod(){
            this.$refs.child.run();
        }
    }
}
</script>

//----------------子组件代码-----------------
<script>
    export default{
        data(){
            return:{
                msg:'我是子组件的值哦'
            }
        },
        methods:{
            run(){
                alert("我是子组件的方法"+this.msg);
            }
        }       
    }
</script>

4、$parent

子组件通过$parent获取父组件的数据和方法:直接在子组件中使用this.$parent.xxx,不需要做任何多余操作。

//子组件代码示例
<script>
    export default{
        methods:{
            getFatherProp(){
                let fatherMsg = this.$parent.fatherMsg;
            },
            getFatherMethod(){
                this.$parent.fatherRun();
            }
        }       
    }
</script>

5、 兄弟组件传值

//操作步骤
1、创建一个新的Vue实例,让各个兄弟公用同一个事件机制。(关键点:使用Bus事件总线,创建一个中转站来进行传值)
2、传递数据方-->通过事件触发$emit('方法名','传递的数据')
3、接收数据方-->在mounted()钩子函数中触发事件$on('方法名',callback(接收的数据)),此时callback函数中的this已经发生了变化,可以使用箭头函数
  • 在main.js里首先声明
Vue.prototype.$bus = new Vue();
  • 父组件里面有两个子组件,他们是兄弟关系
<template>
    <div>
        <child1></child1>
        <child2></child2>
    </div>
</template>

<script>
import child1 from './userChild/child1'
import child2 from './userChild/child2'
export default {
    components:{
        child1,
        child2
    },
    data(){
        return {
            value:'',
        }
    },
}
</script>
  • 子组件传值
//----------------子组件1----------------
<template>
    <div class="child1">
        子组件1
        <div>
            <el-input v-model="value"></el-input>
            <el-button @click="submit">提交</el-button>
        </div>
    </div>
</template>
<script>
export default {
    data(){
        return{
            value:''
        }
    },
    methods:{
        submit(){
            this.$bus.$emit('onName',this.value)
        }
    }
}
</script>
//----------------子组件2----------------
<template>
    <div class="child2">
        子组件2
        <div> {{msg}} 提交了申请</div>
    </div>
</template>
<script>
export default {
    data(){
        return{
            msg:''
        }
    },
    mounted(){
        this.$bus.$on('onName',(value)=>{
            this.msg = value;
        })
    }
}
</script>

6、 依赖注入provide&inject

provide/inject需要一起使用,以允许一个祖先向其所有子孙后代注入一个依赖,单向的,只能父-->后代,不论组件层次有多深,并在起上下游关系成立的时间里始终生效。

有人这么形容:provide就相当于加强版父组件prop,可以跨越中间组件;inject就相当于加强版子组件的props

//-----------父组件中------------
<template>
	<div id="app">
         {{count}}
      <child-component @update:xxx="changeCount"></child-component>
    </div>
</template>
<script>
export default {
    data: {
        count: 2000,
        text: 'hello world!'
    },
    provide: function () {
        return {
            infos:this.text, //这里是data中定义的数据
            fun:this.fun //这里是methods中定义的方法
        }
    },
}
</script>
//-----------后代组件中------------
<script>
export default {
    inject:['infos','fun'], //使用的时候都是通过this,类似于普通的组件传值
    data: {
        count: 2000,
        text: 'hello world!'
    }
}
</script>

7、 Vuex数据共享来相互传值更改状态

vue动态绑定class

第一种:对象的形式

  • 最简单的绑定(这里的active加不加单引号都可以,一下也一样能渲染)
//isActive是在data里面的布尔值,active是class样式类
//isActive为true时样式类active才生效
<div :class='{active:isActive}'>123</div>
  • 判断是否绑定一个active
<div :class='{active:isActive == index}'>123</div>
  • 绑定并判断多个
1、第一种(用逗号隔开)
<div :class='{active:isActive, sort:isSort}'>123</div>
2、第二种(放在data里面)
<div :class='classObject'>123</div>
export default{
    data(){
        return{
            classObject:{active:true, sort:false}
        }
    }
};
3、第三种(使用computed属性)
<div :class='classObject'>123</div>
export default{
    data(){
        return{
            isActive:true,
            isSort:false
        }
    },
    computed:{
        classObject:function(){
            return{
                active:this.isActive,
                sort:this.isSort
            }
        }
    }
};

第二种:数组的形式

  • 单纯的数组
<div :class='[isActive,isSort]'>123</div>
export default{
    data(){
        return{
            isActive:true,
            isSort:false
        }
    }
};
  • 数组与三元运算符结合判断选择需要的class
<div :class="[ isActive ? 'active':'' ]">123</div>
//或者
<div :class="[ isActive==index ? 'active':'otherActive' ]">123</div>
  • 数组结合对象动态判断
//前面的这个active在对象里可以不加单引号,后面这个sort要加单引号
<div :class="[{active:isActive}, 'sort']">123</div>
//或者
<div :class="[{active:isActive==index}, 'sort']">123</div>

vue动态添加style

vue在动态添加style的时候需要注意:

1、凡是有-的style属性名都要变成驼峰式,比如font-weight需要写成fontWeight
2、除了绑定值,其他属性名的值要用引号括起来,比如width:'75px',不要忘记引号
3、动态绑定时,属性值和属性名要用大括号括起来
1、对象形式
:style="{ width:activeWidth,fontSize:fontSize + 'px' }"
2、数组形式
:style="[{height:(warnData.length>0 ? '100px':'200px')},{color:'#fff'}]"
3、绑定data对象的形式
:style="activeStyle"
export default{
    data(){
        return{
            activeStyle:{
                color:'#fff',
                fontSize:'16px'
            }
        }
    }
}

vue动态组件

场景:做tab切换的时候就会涉及到组件动态加载

//通过使用保留的<component>元素,动态的绑定到它的is特性,可以实现动态组建
<component :is="currentTabComponent"></component>
//但是这样每次组件都会重新加载,会消耗大量性能,所以就用到了缓存组件
<keep-alive>
  <component v-bind:is="currentTabComponent"></component>
</keep-alive>
//这样切换效果没有动画效果,这个也不用着急,可以利用内置的动画效果
<transition>
    <keep-alive>
        <component v-bind:is="currentTabComponent"></component>
    </keep-alive>
</transition>

参考文献:①vue动态组件详解

vue组件的双向绑定

vue中父子组件通信都是单向的,直接在子组件中修改prop传的值vue会给出一个警告,所以需要一下方法解决

方法一:model选项(父组件的v-model指令所绑定的属性num通过model选项传给子组件的data属性,子组件通过自定义事件改变父组件的num属性)

//-----------------父组件----------------
<template>
    <div>
        <child v-model="num">{{num}}</child>
    </div>
</template>
<script>
import child from './child'
export default{
    components:{
        child
    },
    data(){
        return{
            num:123
        }
    }
}
</script>
//-----------------子组件----------------
<template>
    <div>
        <input type="text" :value="data" @input="change" ></input>
    </div>
</template>
<script>
import child from './child'
export default{
    model:{
        prop:'data', //指定父组件双向绑定子组件的哪个属性
        event:'on-change' //指定触发双向绑定的事件名
    },
    props:{
        data:Number
    },
    methods:{
        change(event){
            this.$emit('on-change',Number(event.target.value));
        }
    }
}
</script>

方法二:通过prop和自定义属性

//-----------------父组件----------------
<template>
    <div>
        <child :data="num" @on-change="num=$event">{{num}}</child>
    </div>
</template>
<script>
import child from './child'
export default{
    components:{
        child
    },
    data(){
        return{
            num:123
        }
    }
}
</script>
//-----------------子组件----------------
<template>
    <div>
        <input type="text" :value="data" @input="change" ></input>
    </div>
</template>
<script>
import child from './child'
export default{
    props:{
        data:Number
    },
    methods:{
        change(event){
            this.$emit('on-change',Number(event.target.value));
        }
    }
}
</script>

方法三:sync修饰符

//-----------------父组件----------------
<template>
    <div>
        <child :data.sync="num">{{num}}</child> 
    </div>
</template>
<script>
import child from './child'
export default{
    components:{
        child
    },
    data(){
        return{
            num:123
        }
    }
}
</script>
//-----------------子组件----------------
<template>
    <div>
        <input type="text" :value="data" @input="change" ></input>
    </div>
</template>
<script>
import child from './child'
export default{
    props:{
        data:Number
    },
    methods:{
        change(event){
            this.$emit('update:data',Number(event.target.value));
        }
    }
}
</script>

Vue.observable

2.6.0 新增 用法:让一个对象可响应。Vue 内部会用它来处理 data 函数返回的对象; 返回的对象可以直接用于渲染函数和计算属性内,并且会在发生改变时触发相应的更新; 也可以作为最小化的跨组件状态存储器,用于简单的场景。 通讯原理实质上是利用Vue.observable实现一个简易的 vuex

// 文件路径 - /store/store.js
import Vue from 'vue'

export const store = Vue.observable({ count: 0 })
export const mutations = {
  setCount (count) {
    store.count = count
  }
}

//使用
<template>
    <div>
        <label for="bookNum">数 量</label>
            <button @click="setCount(count+1)">+</button>
            <span>{{count}}</span>
            <button @click="setCount(count-1)">-</button>
    </div>
</template>

<script>
import { store, mutations } from '../store/store' // Vue2.6新增API Observable

export default {
  name: 'Add',
  computed: {
    count () {
      return store.count
    }
  },
  methods: {
    setCount: mutations.setCount
  }
}
</script>