Vue/组件

Vue/组件

创建组件

单独声明一个Vue.component,使用只需要在Vue实例下使用定义的组件名

在组件中data不能是一个对象,而必须是一个函数,这个函数返回一个对象

全局组件

<div id='#app'>
    <my-component></my-component>  
</div>

Vue.component('my-component',{
  data(){
    return {
      name: 'sss'
    }
  },
  template: `<div>我的第一个组件 - {{name}}}</div>`
})
//my-component 声明的组件名  
//template 组件的模板

局部组件

放在实例的对象components下,使用只能在实例el下使用

let vm = new Vue({
  el: '#app2',
  components: {
    "child-component": {
       template: `<div>局部组件 - {{name}}}</div>`
    }
  }  
})

组件通信

props down, events up,

父组件传递给子组件数据,通过属性传递,子组件传递给父组件数据,通过事件传递


<div id="app">
  <my-component food="西瓜"></my-component>
</div>
Vue.component('my-component',{
  props:['food'], //一个子组件需要通过props中的获得父组件传递的属性信息
  template: `<div><p>{{food}}</p></div>`
})

//获取实例下数据
<div id="app">
    <my-component v-bild:food="foods"></my-component>
</div>
Vue.component('my-component',{
  props:["food"],
  template:`
    <div>
        <p>{{food}}</p>
    </div>
    `,
})

new Vue({
  el: '#app',
  data: {
    foods: "苹果"
  }
})

//苹果

子组件可以接收来自父组件的数据,为了保证数据的正确性,完整性,安全性,vue会禁止直接修改父组件的数据,如果非要更改这个数据,一定要通过事件的方式通知父组件

比如上面的我们在模版下定义一个按钮,当点击的时候

<div id="app3">
     <my-component :data="foods" @edit-data="callback"></my-component>
</div>
Vue.component('my-component',{
        props:["data"],
        template:`
                <div>
                    <p>{{data}}</p>
                    <button @click="click">按钮</button>  
                </div>
        `,
        methods: {
            click(){
                this.$emit('edit-data',"我要吃苹果")
                //点击后,触发事件
            }
        }
      })
    let vm = new Vue({
        el: '#app3',
        data: {
            foods:
                "苹果"
        },
        methods: {
            callback(v){
                //这边就监听到后,相当于子组件要请求修改数据,通过事件传递给父组件,然后告诉实例,实例自己来修改数据,最后影响到数据的更改
                this.foods = v;
            }
        }
    })
    console.log(vm.foods)

props验证

我们可以为组件的 props 指定验证规格。如果传入的数据不符合规格,Vue 会发出警告。当组件给其他人使用时,要指定验证规格,需要用对象的形式,而不能用字符串数组:

//在props里通过一个对象来给props来限制条件
Vue.component('example', {
  props: {
    // 基础类型检测 (`null` 意思是任何类型都可以)
    propA: Number,
    // 多种类型
    propB: [String, Number],
    // 必传且是字符串
    propC: {
      type: String,
      required: true
    },
    // 数字,有默认值
    propD: {
      type: Number,
      default: 100
    },
    // 数组/对象的默认值应当由一个工厂函数返回
    propE: {
      type: Object,
      default: function () {
        return { message: 'hello' }
      }
    },
    // 自定义验证函数
    propF: {
      validator: function (value) {
        return value > 10
      }
    }
  }
})

非prop属性

如果一个组件标签上的属性没有在props中定义,那么这个属性将会被自动添加到组件的根元素上,对于style和class进行合并(把组件标签上的style或class与区间根元素上的style或class进行合并),但是其他的属性将是覆盖操作


//div background: red; border: 1px solid #000;<div id="app">
    <m-area style="border: 1px solid #000" :r="100"></m-area>
</div>

Vue.component("mArea",{
    props: {
        r: {
            type: Number,
            default: 10
        }
    },
    template: `
        <div style="background: red">  
            <p>面积: {{Math.PI * r * r}}</p>
        </div>
    `
});

let vm = new Vue({
    el: "#app"
})  
//div background: red; border: 1px solid #000;

style标签并没有在props中定义,那就会自动添加在组件模版根元素(div)上,style这个属性也不是被覆盖,而是合并在一起了

插槽slot

在组件模板中通过 <slot></slot> 来定义一个插槽,在解析的时候,会把对应的内容放到slot位置

一个组件中可以使用多个slot,如果有多个的话,需要给slot设置name属性,没有name的就是默认插槽

<div id="app">
  <h1>自身h1标题</h1>
  <my-component>
  <p>自身的文字</p>
  <p>自身的文字1111</p>
  </my-component>
</div>

Vue.component('my-component',{
  template:`
  <div>
  <p>模版文字</p>
  <span>moban</span>
  <slot>slot的文字</slot> 
  </div>
`
});
//如果外面使用模版,有模版以为的内容,看里面是否有插槽,有就把外面自身的内容放到插槽位置里,没有内容就是用插槽的内容

具名

<slot> 元素可以用一个特殊的属性 name 来配置如何分发内容。多个 slot 可以有不同的名字。具名 slot 将匹配内容片段中有对应 slot 特性的元素。

仍然可以有一个匿名 slot,它是默认 slot,作为找不到匹配的内容片段的备用插槽。如果没有默认的 slot,这些找不到匹配的内容片段将被抛弃。

<div id="app">
    <my-component>
        <p>没有固定要放的位置</p>
        <h1 slot="head">我要放的自己的头部内容</h1>
        <p>没有固定要放的位置111</p>
        <p slot="foot">我要放的自己的底部内容</p>
        <p slot="head">我要放的自己的头部内容111</p>
    </my-component>
 </div>

Vue.component('my-component',{
template:`
    <div>
        <header>
            <slot name="head"></slot>    
        </header>
        <main>
            <slot></slot>
        </main>
        <footer>
            <slot name="foot"></slot>    
        </footer>
</div>
                `
});  

//展示
<div>
    <header>
        <h1>我要放的自己的头部内容</h1>
        <p>我要放的自己的头部内容111</p>
    </header>
    <main>
        <p>没有固定要放的位置</p>
        <p>没有固定要放的位置111</p>
    </main>
    <footer>
        <p>我要放的自己的底部内容</p> 
    </footer>
</div>

作用域插槽

作用域插槽是一种特殊类型的插槽,用作使用一个 (能够传递数据到) 可重用模板替换已渲染元素。

在父级中,具有特殊属性 scope<template> 元素必须存在,表示它是作用域插槽的模板。scope 的值对应一个临时变量名,此变量接收从子组件中传递的 props 对象:

<div id="app">
  <div class="parent">
    <my-component>
      <template scope="props"> 
        <span>{{props.text}}</span>
      </template>
    </my-component>
  </div>
</div>

Vue.component('my-component',{
    template:`
        <div class="child">
            <slot a=10></slot>
            <slot b=10></slot>
            <slot age="18"></slot>
            <slot text="hello from child"></slot>
        </div>
`
});
//相当于循环了模版里的内容,你有几个slot就循环几次,那就是4个span标签,内容就用{{props.需要的属性}},没有就为空标签
//展现
<div class="parent">
    <div class="child">
        <span></span>
        <span></span>
        <span></span>
        <span>hello from child</span>
    </div>
</div>

具名作用域

<div id="app">
    <my-component>
        <template scope="props" slot="list">  //
            <li>{{props.text}}</li>
        </template>
    </my-component>
</div>

Vue.component('my-component',{
    template:`
        <ul>
            <slot name="list" v-for="item in items" :text="item"></slot>
        </ul>
`

new Vue({
    el: '#app',
    data: {
        items: ["a","b","c","d","e"]
    }
})

//显示
<ul>
    <li>a</li>
    <li>b</li>
    <li>c</li>
    <li>d</li>
    <li>e</li>
</ul>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,290评论 6 491
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,107评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,872评论 0 347
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,415评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,453评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,784评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,927评论 3 406
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,691评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,137评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,472评论 2 326
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,622评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,289评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,887评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,741评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,977评论 1 265
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,316评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,490评论 2 348

推荐阅读更多精彩内容

  • 三、组件 组件 (Component) 是 Vue.js 最强大的功能之一。组件可以扩展 HTML元素,封装可重用...
    小山居阅读 599评论 0 1
  • 此文基于官方文档,里面部分例子有改动,加上了一些自己的理解 什么是组件? 组件(Component)是 Vue.j...
    陆志均阅读 3,806评论 5 14
  • 前言 本文主要介绍属性、事件和插槽这三个vue基础概念、使用方法及其容易被忽略的一些重要细节。如果你阅读别人写的组...
    IT小鲍阅读 460评论 0 0
  • 测试代码 创键组件 两种方式:方法一:使用Vue.extend({}) 方法二:使用字面量 注册组件 全局注册语法...
    放风筝的小小马阅读 550评论 0 0
  • 今天的军训没有之前那么累,可能是下雨一直休息的原因,感觉济南下雨的时候真是少。 昨晚梦到我躺在家里大床上睡觉,...
    微Rain阅读 215评论 0 0