组件基础

 

 

 

 因为组件是可复用的 Vue 实例,所以它们与 new Vue 都有 datacomputedwatchmethods 以及生命周期钩子等。仅有的例外是像 el 这样根实例特有的选项(组件没有el)。

注意当点击按钮时,每个组件都会各自独立维护它的 count。每用一次组件,就会有一个它的新实例被创建。

 

data 放在函数中(独立的作用域)不会影响其他相同引用的组件实例

data: function () {
  return {
    count: 0
  }
}

 

在components文件创建自己的组件 search.vue

page页面导入

import search from '../../components/search.vue'

  注册以及命名(一下两种命名方式都可以使用my-search的标签)

components:{
            // 'my-search':search,
            'MySearch':search
        }

使用

<my-search></my-search>

 

组件之间传值

【1】父组件给子组件传值:

父组件:
data: 
{ 
    showFaceDia: false 
}
//此为传递动态prop <v-facePop :showFaceDia=“showFaceDia”></v-facePop>

//此为传递静态prop
<v-facePop showFaceDia=“false”></v-facePop>
 
子组件:
//这里的poros为对象的形式,数组形式为props:['showFaceDia'] props:{ showFaceDia: Boolean }

通常你希望每个 prop 都有指定的值类型。这时,你可以以对象形式列出 prop,这些 property 的名称和值分别是 prop 各自的名称和类型:

props: {
  title: String,
  likes: Number,
  isPublished: Boolean,
  commentIds: Array,
  author: Object,
  callback: Function,
  contactsPromise: Promise // or any other constructor
}

 

【2】子组件向父组件传值 (vue写法)

子组件中:
this.showFaceDia = false  
this.$emit('showFaceDia',this.showFaceDia)  //执行showFaceDia函数并把要改变的值作为参数带过去

父组件:
methods:{
showFaceDia(msg){
    this.showFaceDia = msg
  }
}
不要忘记在DOM中引用:
<test :title="title" @showFaceDia="showFaceDia"></test>//注意showFaceDia后不能加括号

 el:

  父:

 data : 

  子:

 

 

$emit 传参

 函数接收参数:

 

 

 $event接收参数

 

 

 

 父子之间传值,例子:

 

组件之间调用方法

父组件调用子组件的方法:

//父组件
<v-test :title="title" ref="aa"></v-test> //通过ref为子组件赋予ID引用
<div @click="getChild()"></div>
getChild(){
  this.$refs.aa.childFun()   // 此处使用
}

 

子组件调用父组件的方法:

2020.12.17再次总结1、emit,2、this.$parent.fn,3、父组件直接通过props传过来

(1)直接在子组件中通过this.$parent.event来调用父组件的方法
(2)在子组件里用$emit向父组件触发一个事件,父组件监听这个事件就行了实例:
子组件:
methods: {
        getParent () {
            this.$emit('togglePop')  //此处直接写父组件的事件名称
        }
    }
父组件:
DOM中:<test :title="title" @togglePop="togglePop"></test>
togglePop(){
            console.log('ddddddd')
        },

 

 

 子调用父组件的方法

 

 爷孙组件之间的删除事件传递

 

 

 数据,方法事件在第一层,删除按钮在第三层

 

方法一:通过父传子的方法 props, props 不仅可以传 对象,数组,还可以传方法 Function

通过绑定事件逐层往下传

第一层

 

 

 第二层

 

 把index 也传过去

 

 

 第三层

直接调用传过来的方法并且传入参数

 

 

 

 

 

方法二:通过自定义事件 第三场触发 this.$emit('方法名',index),层层调用,直到调用第一层的方法

 

兄弟组件之间的传值

用于同级组件之间的传值

方法一:子A传值到父组件保存,父组件再传值给子B

方法二:$emit,中转站(用于接收和监听数据),$on的方式

文件部署

两兄弟组件

 

 中转站文件的创建

(js形式)

(单文件形式)

 import Vue from 'vue'
 export default new Vue;

 

在兄弟组件前引入,我这采用的是 js 的形式

 

 

 如果采用的单文件的形式

 在兄弟组件中 import Transfer from './components/Transfer.vue'

 

传值

兄弟组件1

 

兄弟组件2

 

 


 

组件重构

data

posts: [
{ id: 1, title: 'My journey with Vue',content:'mai le fou leng Why?',data:'2020 year' },
{ id: 2, title: 'Blogging with Vue' ,content:'mai le fou leng Why?',data:'2020 year'},
{ id: 3, title: 'Why Vue is so fun' ,content:'mai le fou leng Why?',data:'2020 year'}
]

看起来当组件变得越来越复杂的时候,我们的博文不只需要标题和内容,还需要发布日期、评论等等。为每个相关的信息定义一个 prop 会变得很麻烦:

 

所以这时候需要重构一下这个 <blog-post> 组件了,让它变成接受一个单独的 post prop:

 

组件中的插槽 slot

<alert-box>
  Something bad happened.
</alert-box>
Vue.component('alert-box', {
  template: `
    <div class="demo-alert-box">
      <strong>Error!</strong>
      <slot></slot>
    </div>
  `
})

在需要的相对应的地方加入插槽就行了

 

<component>内置组件 + v-bind: is:实现动态组件 知识点预告

 <component> 元素是vue 里面的一个内置组件。

在<component>里面使用 v-bind: is,可以实现动态组件的效果。

 

 

 

 

 

 

动态组件

 

上述内容可以通过 Vue 的 <component> 元素加一个特殊的 is attribute 来实现:

<!-- 组件会在 `currentTabComponent` 改变时改变 -->
<component v-bind:is="currentTabComponent"></component>

下面贴上两组实现上面效果的代码:

公共样式:

<style>
        .tab-button {
            padding: 6px 10px;
            border-top-left-radius: 3px;
            border-top-right-radius: 3px;
            border: 1px solid #ccc;
            cursor: pointer;
            background: #f0f0f0;
            margin-bottom: -1px;
            margin-right: -1px;
        }

        .tab-button:hover {
            background: #e0e0e0;
        }

        .tab-button.active {
            background: #e0e0e0;
        }

        .tab {
            border: 1px solid #ccc;
            padding: 10px;
        }
   </style>

html:

<button v-for="(item,index) in tabs" :class="['tab-button',{active: currentTab === item}]" @click="currentTab = tabs[index]">{{item}}</button>
<component :is="componentName" class="tab"></component>

js:

Vue.component("tab-home", {
    template: "<div>Home component</div>"
});
Vue.component("tab-posts", {
    template: "<div>Posts component</div>"
});
Vue.component("tab-archive", {
    template: "<div>Archive component</div>"
});

let vm = new Vue({
    el: '#app',
    data: {
        // currentTab: 0,
        currentTab: "Home",
        tabs: ["Home", "Posts", "Archive"]
        // tabs,
    },            
    computed:{
        componentName(){
            return "tab-"+ this.currentTab.toLowerCase()
        }
    }
})

 

第二种方法思路:将组件的代码放进对象里

 

 

 component 组件 is 直接解析 template

 

 

 总的来说,第二种比较简洁

 

解析DOM模板是的注意事项

有些 HTML 元素,诸如 <ul><ol><table> 和 <select>,对于哪些元素可以出现在其内部是有严格限制的。而有些元素,诸如 <li><tr> 和 <option>,只能出现在其它某些特定的元素内部。

这会导致我们使用这些有约束条件的元素时遇到一些问题。例如:

 

  

 

 

posted on 2020-11-10 14:23  京鸿一瞥  阅读(187)  评论(0)    收藏  举报