vue 组件详解

组件

什么是组件

组件时html,css, js等得一个聚合体。

组件化目的

  • 将一个具备完整功能的模块从项目中分离出来。
  • 一个项目可以由多个组件构成可以加快项目进度,层次清晰。
  • 每个项目都可以在不同项目中复用。

152

组件注册

全局注册

Vue.component( 组件名称, 组建的配置项)

import CustomButton from './components/ComponentDemo.vue'
Vue.component('CustomButton', CustomButton)

示例

JS代码:

// 注册
Vue.component('my-component', {
  template: '<div>A custom component!</div>'
})
var vm = new Vue({
  el: '#example',
  data: {
       
  } 
})

html代码:

<div id="example">
  <my-component></my-component>
</div>

渲染结果:

<div id="example">
  <div>A custom component!</div>
</div>

另一种注册方式,通过 全局API:Vue.extend()

// 注册
var MyComponent = Vue.extend({
  template: '<div>A custom component!</div>'
});

Vue.component('my-component', MyComponent);
var vm = new Vue({
  el: '#example',
  data: {
       
  }
})

局部注册

通过一个简单的js对象来注册组件

var ComponentA = { /* ... */ }
var ComponentB = { /* ... */ }

使用组件

new Vue({
  el: '#app'
  components: {
    //局部组件注册(组件名称:组件对象),前面的组件名称可以不填用默认值
    'component-a': ComponentA,
    'component-b': ComponentB
  }
})

示例

<body>
  <div id="app">
     <Father></Father>
  </div>

   <div id="out">
        <Father></Father>
  </div>
</body>



<script>

  var Hello = Vue.extend({
     template:'<div>这是局部组件</div>'
  })

  new Vue({
     el:"#app",
     components:({//局部注册组件
        'Father': Hello,
     })
  });
   
   //在#app内注册的组件,#out访问不到
  new Vue({
     el:"out",
  })
  
</script>

全局注册 和 局部注册比较

  • 全局注册可以在其他地方直接使用

  • 全局注册不需要compenents指定组件

  • 全局注册的组件会全部一起打包,增加app.js体积

  • 局部注册按需载入

  • 局部注册每次使用必须导入,然后components指定

  • 全局注册适合基础组件,局部注册适合非基础组件

组件命名

  • 一个单词命名时首字母大写,注意不要和原生h5标签重名eg:header、footer等
  • 多个单词时,用小写,中间用 - 作为连接符,eg:header-title
  • 不能使用大驼峰命名 eg:Header-Title,会被解析成header-title

引入组件

上面组件注册的示例,是放在一个vue中,更多情况下组件是放在独立的vue中,需要我们去引入。

组件listBox: 路径 src/components/listBox.vue

<template>
    <div class="listBox">listBox222</div>
</template>

<script>
export default {
    name: "listBox",
    data:function(){
        return {}
    }
}
</script>

<style scoped>

</style>

局部注册引入组件

比如在App.vue中使用listBox 那么,App.vue下发如下:

<template>
  <div id="app">
    <img src="./assets/logo.png">
    <router-view/>
    <listBox></listBox>
  </div>
</template>

<script>
import listBox from './components/listBox'

export default {
    name: 'App',
      components:{
        'listBox':listBox
      }
}
</script>

<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>

全局注册引入组件

mian.js文件

import listBox from './components/listBox'

//全局组件注册
Vue.component('listBox',listBox);

prop

props用于父组件向子组件传值,prop就是我们注册再props中的值。

基本用法

Prop的基本用法很简单,只需要在子组件的Vue实例中定义该属性并把值设为目标属性的数组即可。

Vue.component('child', { 
  ... 
  // 接收message 
  props: ['message'] 
  ... 
})

静态传值

Prop可以接受静态属性,例如父组件在子组件标签上定义了静态属性type,子组件依然通过Prop拿到了静态属性type。

/* 父组件 */ 
<child type="video"></child> 
 
/* 子组件 */ 
Vue.component('child', { 
  ... 
  // 成功接收 
  props: ['type'] 
  ... 
})

动态传值

Prop动态值**,一般在父组件中通过v-bind定义一个动态值,子组件通过Prop接收该值。

子组件:

<template>
  <div>
    <h1>{{ msg }}</h1>
  </div>
</template>

<script>
export default {
  props: ["msg"]
}
</script>

父组件:

<template>
  <div id="app">
    <HelloWorld :msg="hello"/>
  </div>
</template>

<script>
import HelloWorld from "./components/HelloWorld.vue";

export default {
  components: {
    HelloWorld
  },
  data() {
    return {
      hello: "hello world"
    }
  }
};
</script>

props验证

验证传入的 props 参数的数据规格,如果不符合数据规格,Vue 会发出警告。

能判断的所有种类(也就是 type 值)有:String, Number, Boolean, Function, Object, Array, Symbol

Vue.component("example", {
 props: {
 // 基础类型检测, null意味着任何类型都行
 propA: Number,
 // 多种类型
 propB: [String, Number],
 // 必传且是String
 propC: {
  type: String,
  required: true
 },
 // 数字有默认值
 propD: {
  type: Number,
  default: 101
 },
 // 数组、默认值是一个工厂函数返回对象
 propE: {
  type: Object,
  default: function() {
  console.log("propE default invoked.");
  return { message: "I am from propE." };
  }
 },
 // 自定义验证函数
 propF: {
  isValid: function(value) {
  return value > 100;
  }
 }
 }
});
let childNode = {
 template: "<div>{{forChildMsg}}</div>",
 props: {
 "for-child-msg": Number
 }
};
let parentNode = {
 template: `
   <div class="parent">
   <child :for-child-msg="msg"></child>
   </div>
  `,
 components: {
 child: childNode
 },
 data() {
 return {
  // 当这里是字符串 "123456"时会报错
  msg: 123456
 };
 }
};

自定义事件

父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件!

每个 Vue 实例都实现了事件接口 (Events interface)
使用 $on(eventName) 监听事件
使用 $emit(eventName) 触发事件

示例


<div id="app">
    <div id="counter-event-example">
      <p>{{ total }}</p>
      <button-counter v-on:increment="incrementTotal"></button-counter>
      <button-counter v-on:increment="incrementTotal"></button-counter>
    </div>
</div>
 
<script>
Vue.component('button-counter', {
  template: '<button v-on:click="incrementHandler">{{ counter }}</button>',
  data: function () {
    return {
      counter: 0
    }
  },
  methods: {
    incrementHandler: function () {
      this.counter += 1
      this.$emit('increment')
    }
  },
})
new Vue({
  el: '#counter-event-example',
  data: {
    total: 0
  },
  methods: {
    incrementTotal: function () {
      this.total += 1
    }
  }
})
</script>

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×