09月01, 2020

VUE组件间传值

Vue的框架开发的项目过程中,经常会用到组件来管理不同的功能,有一些公共的组件会被提取出来。这时必然会产生一些疑问和需求?比如一个组件调用另一个组件作为自己的子组件,那么我们如何进行给子组件进行传值呢。

十五、Props父组件向子组件传值

单组件由三部分组成:
<template>
    <div>

    </div>
</template>

export default {
    name: 'mc',
    data() {
        return {

        }
    }
}

<style scoped>

</style>
  1. template: 里面只能存在一个根元素
  2. script:必须通过export default导出,外部组件才能访问。
    1. name:指定组件名字。
    2. data:绑定数据。
  3. style:样式
    1. scoped:当前样式只在当前组件内生效,局部的。
子父级组件

一个组件被另一个组件嵌套。

如: app组件里面嵌套hellowolrd组件。

子父级组件通信

父 --> 子: props

子 --> 父: emit Event

父向子通信:

父组件:
<son :title="msg"></son>

 msg: 'son hello'

子组件:
props: [
    "title"
]

{{title}}
props数据传递类型验证
子组件接受参数时,指定类型。   
    props: {
        title: {
            type: [String,Number],
            required: true,
            defalut: 100
        }
    }
  1. type:指定接收参数类型,可以有多个类型。

  2. required:是否必传。

    注意:如果是Number、String可以直接默认一个值,如果是其他类型则默认返回一个方法。

    <son :msg="say"></son>
    return {
                say: {
                    name:"Zhangsan",
                    age:20
                }
            }
    
    
   props: {
       msg: {
           type:Object,
           default:function(){
               return {
                   name:"lisi",
                   age:10
                   }
           }
       }
   }


1. 数据验证
2. 多数据类型验证
3. 必选项验证
4. 默认值
5. obj、arr数据类型的默认值



#### 十六、子向父组件通信

使用v-on自定义事件

```vue
子组件代码:
<template>
    <div>
        <button @click="send">发送</button>
    </div>
</template>


export default {
    name: 'OneSon',
    data() {
        return {
            msg: '父组件,您好。'
        }
    },
    methods: {
        send() {
            this.$emit("msg",this.msg);
        }
    }
}


<style>

</style>
父组件代码:
<template>
    <div>
        <one-son @msg="getData"></one-son>
        <H1>{{msg}}</H1>
    </div>
</template>


import OneSon from '../components/OneSon'
export default {
    name: 'One',
    components:{
        OneSon
    },
    data() {
        return {
            msg: ''
        }
    },
    methods: {
        getData(data) {
            this.msg = data;
        }
    }
}


<style>

</style>
父组件向子组件传递数据步骤
  1. 子组件通过一个事件来触发。

  2. 事件中有两个参数,一个key,用来在父组件中作为事件。另一个数据。

  3. 父组件使用key作为事件,定义一个事件接受数据

    数据交互式同步的。

input所有内容为String,可以通过下面进行转换成数字。
<one-son @msg="getData" :sendMsg="getNum"></one-son>

computed: {
        getNum(){
            return this.newMsg -0;
        }
    }

十七、插槽与缓存

使用插槽分发内容
  1. 单个插槽

    父组件:
    <template>
        <div>
            <two-son>
                <span>{{msg}}</span>
            </two-son>
        </div>
    </template>
    
    import TwoSon from '../components/TwoSon'
    export default {
        name: 'Two',
        components: {
            TwoSon
        },
        data() {
            return {
                msg: '使用插槽'
            }
        }
    }
    
    <style scoped>
    span{
    color: red;
    font-size: 40px;
    }
    </style>
    子组件:
    <template>
        <div>
            <slot>我是插槽,但是我会被父组件插入内容覆盖。</slot>
        </div>
    </template>
    
    export default {
        name: 'TwoSon',
        data() {
            return {
    
            }
        }
    }
    
    <style>
    
    </style>
    

    注意:插槽的样式,可以在父组件中设置,也可以在子组件中设置。

  2. 具名插槽

            <two-son>
                <span slot="s1">{{msg}}</span>
                <p slot="s2">我是插槽2哦</p>
            </two-son>
    
        <div>
            <slot name="s1">我是插槽,但是我会被父组件插入内容覆盖。</slot>
            <hr>
            <slot name="s2"></slot>
        </div>

注意:当没有传递视图时,可以显示查查默认设置的值。

  1. 作用域插槽(传递参数)

    作用于插槽传递数据
子组件:
<slot name="s2" text="google hjhlj"></slot>


父组件:
 <span slot="s2" slot-scope="key">
               {{ key.text}}
           </span>
props与slot插槽对比
名称 props slot
传递数据 父组件 ---> 子组件 子组件---> 父组件
数据 由父组件决定 由子组件决定
视图 由子组件决定 由父组件决定

十八、动态组件

<template>
  <div id="app">
    <component v-bind:is="currentView"></component>
    <button @click="change">change</button>
  </div>
</template>


import Events from './components/Events'
import FormData from './components/FormData'
import Styles from './components/Style'
import MyCompent from './components/myCompent'
import Father from './components/Father'
import One from './components/One'
import Two from './components/Two'
export default {
  name: 'App',
  data() {
    return {
      currentView: "FormData"
    }
  },
  methods: {
    change() {
      this.currentView = 'MyCompent';
    }
  },
  components: {
    Events,
    FormData,
    Styles,
    MyCompent,
    Father,
    One,
    Two
  }
}


<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

注意:这样的来回切换,每次都重新渲染了。因此下面介绍了keep-alive

<template>
  <div id="app">
    <keep-alive>
      <component :is="currentView"></component>
    </keep-alive>
    <button @click="change">change</button>
  </div>
</template>


import Events from './components/Events'
import FormData from './components/FormData'
import Styles from './components/Style'
import MyCompent from './components/myCompent'
import Father from './components/Father'
import One from './components/One'
import Two from './components/Two'
export default {
  name: 'App',
  data() {
    return {
      currentView: "FormData",
      flag: true,
    }
  },
  methods: {
    change() {
      if(this.flag){
        this.currentView ="FormData";
        this.flag=false;
      }else{
        this.currentView ="Father";
        this.flag=true;
      }
    }
  },
  components: {
    Events,
    FormData,
    Styles,
    MyCompent,
    Father,
    One,
    Two
  }
}


<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

keep-alive:将组建保留在内存中,做到了缓存效果。

注意:什么情况使用keep-alive缓存?

实时更新不能使用缓存。

十九、过度与动画

单元素与组建的过渡

自动应用class

<template>
    <div>
        <transition name="fade">
            <h1 v-show="show">{{msg}}</h1>
        </transition>
        <br>
        <button @click="change">测试</button>
    </div>
</template>

export default {
    name: 'Donghua',
    data() {
        return {
            msg: '动画测试',
            show: true,
        }
    },
    methods: {
        change() {
            this.show = ! this.show;
        }
    }
}

<style>
.fade-enter-active, .fade-leave-active {
  transition: opacity .5s;
}
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
  opacity: 0;
}
</style>
过渡类名
  1. v-enter:定义进入过渡的开始状态。在元素被插入之前生效,在元素被插入之后的下一帧移除。

  2. v-enter-active:定义进入过渡生效时的状态。在整个进入过渡的阶段中应用,在元素被插入之前生效,在过渡/动画完成之后移除。这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数。

  3. v-enter-to: 2.1.8版及以上 定义进入过渡的结束状态。在元素被插入之后下一帧生效 (与此同时 v-enter 被移除),在过渡/动画完成之后移除。

  4. v-leave: 定义离开过渡的开始状态。在离开过渡被触发时立刻生效,下一帧被移除。

  5. v-leave-active:定义离开过渡生效时的状态。在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,在过渡/动画完成之后移除。这个类可以被用来定义离开过渡的过程时间,延迟和曲线函数。

  6. v-leave-to: 2.1.8版及以上 定义离开过渡的结束状态。在离开过渡被触发之后下一帧生效 (与此同时 v-leave 被删除),在过渡/动画完成之后移除。

    <template>
        <div>
            <transition name="fade">
                <h1 v-show="show">{{msg}}</h1>
            </transition>
            <br>
            <button @click="change">测试</button>
        </div>
    </template>
    
    export default {
        name: 'Donghua',
        data() {
            return {
                msg: '过渡测试',
                show: true,
            }
        },
        methods: {
            change() {
                this.show = ! this.show;
            }
        }
    }
    
    <style>
    .fade-enter, .fade-leave-to{
        opacity: 0;
    }
    .fade-enter-to, .fade-leave{
        opacity: 1;
    }
    .fade-enter-active, .fade-leave-active{
        transition: opacity .9s
    }
    </style>

移动的过渡

<template>
    <div>
        <transition name="fade">
            <h1 v-show="show">{{msg}}</h1>
        </transition>
        <br>
        <button @click="change">测试</button>
    </div>
</template>

export default {
    name: 'Donghua',
    data() {
        return {
            msg: '过渡测试',
            show: true,
        }
    },
    methods: {
        change() {
            this.show = ! this.show;
        }
    }
}

<style>
.fade-enter, .fade-leave-to{
    transform: translate(20px,0);
    /* opacity: 0; */
}
.fade-enter-to, .fade-leave{
    /* opacity: 1; */
    transform: translate(-20px,0)
}
.fade-enter-active, .fade-leave-active{
    /* transition: opacity 3s */
    transition: all 2s
}
</style>
CSS过渡
<template>
    <div>
        <transition name="fade">
            <h1 v-show="show">{{msg}}</h1>
        </transition>
        <br>
        <button @click="change">测试</button>
        <br>
        <button @click="dong">test</button>
        <br>
        <transition name="dongba">
            <p v-show="newshow">我现在住在加利福尼亚州的奥克兰</p>
        </transition>
    </div>
</template>

export default {
    name: 'Donghua',
    data() {
        return {
            msg: '过渡测试',
            show: true,
            newshow: true,
        }
    },
    methods: {
        change() {
            this.show = ! this.show;
        },
        dong() {
            this.newshow = ! this.newshow;
        }
    }
}

<style>
.fade-enter, .fade-leave-to{
    transform: translate(20px,0);
    /* opacity: 0; */
}
.fade-enter-to, .fade-leave{
    /* opacity: 1; */
    transform: translate(-20px,0)
}
.fade-enter-active, .fade-leave-active{
    /* transition: opacity 3s */
    transition: all 2s
}

.dongba-enter-active{
animation: bounce-in .5s;
}
.dongba-leave-active{
     animation: bounce-in .5s reverse;
}
@keyframes bounce-in {
  0% {
    transform: scale(0);
  }
  50% {
    transform: scale(1.5);
  }
  100% {
    transform: scale(1);
  }
}
</style>

动画可以控制过程,过渡不能。

使用第三方css

引入外部css方式

  1. 直接添加到index.html中。

    <template>
        <div>
            <transition name="fade">
                <h1 v-show="show">{{msg}}</h1>
            </transition>
            <br>
            <button @click="change">测试</button>
            <br>
            <button @click="dong">test</button>
            <br>
            <transition name="dongba">
                <p v-show="newshow">我现在住在加利福尼亚州的奥克兰</p>
            </transition>
    
            <br>
            <button @click="san">第三方动画库</button>
            <br>
            <transition name="word" enter-active-class="animated hinge"  leave-active-class="animated flip">
                <h1 v-show="newsan">CSS动画库</h1>
            </transition>
        </div>
    </template>
    
    export default {
        name: 'Donghua',
        data() {
            return {
                msg: '过渡测试',
                show: true,
                newshow: true,
                newsan: true,
            }
        },
        methods: {
            change() {
                this.show = ! this.show;
            },
            dong() {
                this.newshow = ! this.newshow;
            },
            san() {
                this.newsan = !this.newsan;
            }
        }
    }
    
    <style>
    .fade-enter, .fade-leave-to{
        transform: translate(20px,0);
        /* opacity: 0; */
    }
    .fade-enter-to, .fade-leave{
        /* opacity: 1; */
        transform: translate(-20px,0)
    }
    .fade-enter-active, .fade-leave-active{
        /* transition: opacity 3s */
        transition: all 2s
    }
    
    .dongba-enter-active{
    animation: bounce-in .5s;
    }
    .dongba-leave-active{
         animation: bounce-in .5s reverse;
    }
    @keyframes bounce-in {
      0% {
        transform: scale(0);
      }
      50% {
        transform: scale(1.5);
      }
      100% {
        transform: scale(1);
      }
    }
    h1{
        position: absolute;
    }
    </style>
    

    所用动画都应该设置为浮动的,不然会出现下拉或滚动条

    position: absolute;
SVG

可参考这里

二十、自定义指定

全局指令

如自定义自动聚焦输入框指定:

main.js中自定义指令

// 注册一个全局自定义指令 `v-focus`
Vue.directive('focus', {
  // 当被绑定的元素插入到 DOM 中时……
  inserted: function (el) {
    // 聚焦元素
    el.focus()
  }
})

自定义指令的使用:

<template>
    <div>
        <input type="text" v-focus>
    </div>
</template>

export default {
    name: 'zidingyi',
}

<style></style>
局部指令

将自定义指令放在使用的组建中:

<template>
    <div>
        <input type="text" v-focus>
    </div>
</template>

export default {
    name: 'zidingyi',
    directives: {
        focus: {
    // 指令的定义
    inserted: function (el) {
      el.focus()
    }
  }
    }
}

<style></style>

二十一、过滤器

如:自动转换首字母为大写:

<template>
    <div>
        首字母自动转换:
        <input type="text" v-focus v-model="msg">
        <br>
        <span>{{ msg | capitalize}}</span>
    </div>
</template>

export default {
    name: 'zidingyi',
    data() {
        return {
            msg: '',
        }
    },
    directives: {
        focus: {
        // 指令的定义
        inserted: function (el) {
            el.focus()
            }
        }
    },
    filters: {
        capitalize: function (value) {
            if (!value) return ''
            value = value.toString()
            return value.charAt(0).toUpperCase() + value.slice(1)
        }
    }
}

<style></style>

本文链接:https://www.yanxizhu.com/post/Value transfer between VUE components.html

-- EOF --

Comments