美文网首页VUE
vue.js入门(三,vue核心概念,属性,事件,插槽)

vue.js入门(三,vue核心概念,属性,事件,插槽)

作者: 感觉不错哦 | 来源:发表于2019-10-09 15:37 被阅读0次

    如果上次安装vue-cli不小心安装了eslint,在build下方的webpack.base.conf.js中注释此段代码即可,有机会再写写如何格式化

    然后顺带提下vue中的scoped


    在APP.vue主组件随意写DOM并打开它的css可以看到是全局的css

    <style scoped>
       input{
         color: red
       }
    </style>
    

    加上scoped的话vue就会自己加个限制



    这样css样式就隔开了,当然你不会如此丧心病狂取这种属性名来让它全局吧

    属性(props)

    Vue组件=Vue实例=new Vue(options)
    一个个小UI模块(组件)构成一个大的结构,有点像oop面向编程思想

    属性分为三类:

    自定义属性props : 组件中props中声明的属性
    原生属性attrs : 没有声明的属性,默认自动挂载到组件根元素上,设置inheritAttrs为false可以关闭自动挂载
    特殊属性class、style : 挂载到组件根元素上,支持字符串、对象、数组等多种语法

    昨天写demo的时候,在子组件中我在下方声明了props数组用来接收属性

    props:['name','type','isVisible','types'],
    

    从搬砖角度讲很舒服,从维护上面却不是,这个当然还是看自己老大怎么安排,如何设置props呢?

        export default {
        // props:['name','type','isVisible','types'],
            props:{
                name:String, //数据类型  也就是说name这个属性它必须是个字符串,
                //如果是多个类型也可以 
                //name:[String,Number]
    
                //如果设置多个,使用对象形式
                type:{
                    //自定义验证值
                    validator: function (value) {
                        // 这个值必须匹配下列字符串中的一个
                        return ['success', 'warning', 'danger'].indexOf(value) !== -1
                    }
                },
                list:{
                    type:Array,
                    //默认值,像对象数组 引用类型的值需要使用工厂函数获取,普通的类似Number直接丢值就行 比如default:10
                    default:()=>[]
                    // default:function(){
                    //     return {vue:'hello'}
                    // }
                },
                isVisible:{
                    type:Boolean,
                    default:false //不写的话Vue默认也是false
                },
            
            }
        }
    

    通常常用的就是这些,再子组件上给他显示一下

        <template>
            <div>
                name:{{name}}
                <hr/>
                type:{{type}}
                <hr/>
                list:{{list}}
                <hr/>
                isVisible:{{isVisible}}
            </div>
        </template>
    

    接下来我把这个子组件引入到主组件中


    此时页面中就能接收到数据了

    可以看到我在标签内写入了几个属性,那么此时子组件中也是会存在这几个属性


    这就是默认挂载上的,如果不想要,在子组件中设置 inheritAttrs:false,即可


    此时加个函数进来,在属性中添加一个函数


    传递一个onChange属性,是一个函数,函数很简单,改变一下type的值

      methods:{
        handleClick(value){
          this.type=value
        }
      }
    

    那么在子组件内,在props中需要声明一下属性

                isVisible:{
                    type:Boolean,
                    default:false //不写的话Vue默认也是false
                },
                onChange:{
                    type:Function,
                    default:()=>{}
                }
    

    然后在下方的methods中声明

            methods:{
                handleClick(){
                    this.onChange(this.type ==='success'?'warning':'success')
                }
            }
    

    此时打开页面会发现type在随之改变,这个效果先带过!那么这里要提一下Vue中的数据流是单向的,也就是如果在这个函数中直接这么写

              methods:{
                handleClick(){
                    this.type ==='success'?'warning':'success'
                }
            }
    

    是会报错的,所以函数也是可以当成属性传递的

    事件

    事件分为两类

    普通事件:@click @input @change @xxx等事件,通过this.$emit(‘xxx’,...)触发
    修饰符事件 : @input.trim,@click.stop,@submit.prevent等,(可百度),一般用于原生HTML元素

    简单写个demo

    <template>
      <div id="app">
          <Event :name="name" @change="handleEventChange">
    
          </Event>
      </div>
    </template>
    
    <script>
    import Event from './components/Event'
    export default {
      name: 'App',
      data(){
        return {
          name:'Hello'
        }
      },
      components:{
          Event
      },
      methods:{
       handleEventChange(value){
          this.name=value
        }
      }
    }
    </script>
    
    <style scoped>
      
    </style>
    

    首先是APP.vue的代码,代码很简单,就是在子组件中传递了一个name,并且绑定了一个@change事件

        <template>
            <div>
                name:{{name||'--'}}
                <br/>
                <input :value="name" @input="handleChange"/>
                <br/>
                <br/>
                <div @click="handleDivClick">
                    <button @click="handleClick">重置成功</button>
                    <button @click.stop="handleClick">重置失败</button>
                </div>
            </div>
        </template>
    
        <script>
        export default {
            props:['name'],
            methods:{
                handleChange(e){
                    this.$emit('change',e.target.value)
                },
                handleDivClick(){
                    this.$emit('change',"")
                },
                handleClick(e){
                    //都会失败
                    //e.stopPropagation
                }
            }
        }
        </script>
    
        <style>
    
        </style>
    

    那么在子组件中,我们通过$emit的形式,将子组件的数据返回给父组件然后传递回来,有萌新可能觉得给父组件加个v-model绑定name,这样是不对的,相当于子组件改变了父组件的数据了,子组件仅仅是接收而已

    (放在这里容易再次理解)
    普通事件:@click @input @change @xxx等事件,通过this.$emit(‘xxx’,...)触发

    这里有个stop修饰符,这是一个阻止冒泡的作用,当然也可以在下面的e.stopPropagation 注释打开,效果相同,
    那么此时@click.stop阻止冒泡之后就无法点击到父元素从而触发handleDivClick函数了

    从网上找了一些修饰符的效果:
    .stop - 调用 event.stopPropagation()。
    .prevent - 调用 event.preventDefault()。
    .capture - 添加事件侦听器时使用 capture 模式。
    .self - 只当事件是从侦听器绑定的元素本身触发时才触发回调。
    .{keyCode | keyAlias} - 只当事件是从特定键触发时才触发回调。
    .native - 监听组件根元素的原生事件。
    .once - 只触发一次回调。
    .left - (2.2.0) 只当点击鼠标左键时触发。
    .right - (2.2.0) 只当点击鼠标右键时触发。
    .middle - (2.2.0) 只当点击鼠标中键时触发。
    .passive - (2.3.0) 以 { passive: true } 模式添加侦听器

    不懂的可以百度一下
    之前自己写过一篇组件通信的例子,有兴趣可以看看
    https://www.jianshu.com/p/b31a53b93ce9 (可能后续会重新写一篇)

    插槽

    先看个demo


    很空白的一段内容,然后在主组件中引入

    OK 此时没得任何问题

    页面也是还OK,此时我更改一下主组件

          <Slots>
               !超会说
          </Slots>
    

    但是页面并没有发生变化


    此时加个插槽,效果就出来了

    到现在,我们知道了什么是插槽:
    插槽就是Vue实现的一套内容分发的API,将<slot></slot>元素作为承载分发内容的出口。

    具名插槽

    <template>
      <div id="app">
          
          <Slots>
               <template slot="girl">
                  18,身材好,漂亮
               </template>
                <template slot="boy">
                  帅气、色胚
              </template>
          </Slots>
      </div>
    </template>
    

    之前也接触过了,只要在子组件中申明name即可

        <slot name="girl"></slot>
    

    就是只显示girl 内容

          <Slots>
               <template slot="girl">
                  18,身材好,漂亮
               </template>
                <template slot="boy">
                  帅气、色胚
              </template>
             <div>
                我是一类人,
                是的 我就是舔狗
            </div>
          </Slots>
    

    如果子组件slot并没有name就会显示其他非具名内容

    作用域插槽slot-scope(其实自己也不是很明白)

    我的理解就是在组件上的属性,可以在组件元素内使用!

        <template>
            <div>
                <slot say="你好"></slot>
            </div>
        </template>
    

    此时我在子组件中声明一个属性,当然可以绑定data中的内容,偷个懒

          <Slots>
                <template slot-scope="a">
              <!-- {"say":"你好"} -->
    
                    {{a}}
                </template>
          </Slots>
    

    在父组件中即可接收到a的值 就是一个对象

    这时候我给他传一个数组过去


    在子组件中接收,并且循环一哈


    注意当前显示的仅仅是a啊,这种时候可以做什么事情呢?比如说

          <Slots :lists="nameList">
                <template slot-scope="a">
                   <Div v-if="a.obj.id==1">
                    你好: {{a.obj.name}}
                   </Div>
    
                   <div v-else>
                      {{a.obj.name}}
                   </div>
                </template>
          </Slots>
    

    好啦,因为自己也不是很懂就不误人子弟了

    相关文章

      网友评论

        本文标题:vue.js入门(三,vue核心概念,属性,事件,插槽)

        本文链接:https://www.haomeiwen.com/subject/rstgpctx.html