Vue组件模板--深入浅出

组件模板

如果仅仅具备前面的知识,那你的前端开发与Jquery、甚至原生Javascript形式的开发别无二样,Vue真正的强大之处在于,它不仅彻底实现了网页组件的模块化,还提供了大量实用且美观的模块
基础组件
W3C命名规范:字母全小写,包含连字符
核心语法

// 组件定义(组件应定义在脚本内容的前方)- 参数1:组件名	参数2:组件逻辑 
Vue.component('cmp-a', {		// 组件名:cmp-a
    props: [{},],               // 组件属性
    template: '',   			// 组件内容(只能有一个"根")
    methods:{},					// 组件函数库
    data:{}						// 组件的变量
    // ,...
  }
);

简单样例

<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
<script>
    Vue.component('cmp-a', {
            props: ['attr1'],
            template: '<li>{{ attr1 }}</li>'
        }
    );
    // ..
</script>
<div id="demo">
    <!-- 值传递:message ~ x → attr1 → <cmp-a> -->
    <cmp-a 
           v-for="x in message" 
           v-bind:attr1="x"
           v-bind:key="x.id">		<!-- 为每个组件提供一个“key” -->
    </cmp-a>
</div>

<script>
    // ViewModel
    let vue = new Vue({
        el: '#demo',
        data: {
            message: [
                  { id: 0, text: 'A' },
                  { id: 1, text: 'B' },
                  { id: 2, text: 'C' }
            ]
        }
    });
</script>

说明:<组件标签>会被加载替换成其定义时的`组件内容

生存范围

全局作用
Vue.component()方式定义的组件是全局可用的,如果打包程序不够细节,就意味着即便你已经不再使用一个组件了,它仍然会被包含在你最终的构建结果中,用户需要无谓的下载。
局部作用

// 手动导入局部组件A和C,并存到组件库
import ComponentA from './ComponentA'
import ComponentC from './ComponentC'

export default {
  components: {
    ComponentA,
    ComponentC
  },
  // ...
}

// 自动导入需要的组件(Vue CLI 3+)
// https://cn.vuejs.org/v2/guide/components-registration.html#%E5%9F%BA%E7%A1%80%E7%BB%84%E4%BB%B6%E7%9A%84%E8%87%AA%E5%8A%A8%E5%8C%96%E5%85%A8%E5%B1%80%E6%B3%A8%E5%86%8C

属性验证

Vue.component('my-component', {
  props: {
    // 基础的类型检查 (`null` 和 `undefined` 会通过任何类型检查验证)
    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 ['success', 'warning', 'danger'].indexOf(value) !== -1
      }
    }
  }
})

自定义属性的继承

Vue.component('base-input', {
  inheritAttrs: false,
  //...
})

跨级传递数据
如果A组件内嵌套着B组件,B组件内嵌套着C组件,那么A传递数据到C的办法是在B中:

<ComponentC v-bind="$attrs" />

文件组件

命名规范:文件名采用驼峰命名,导入时如果以驼峰命名则在使用时对应的是"-"式
<aside-list>:

import AsideList from "./components/List";
...
	components: {Test, AsideList, Main, Login}

基本语法

<template>								// 组件内容
  <p>{{ greeting }} World!</p>
</template>

<script>
module.exports = {						
  data: function() {					// 组件的变量
    return {
      greeting: "Hello"
    };
  }
};
  export default {						// 组件暴露
    name: 'Xxx',						// 组件名字【可选】
    components: {}						// 组件库
  }
</script>

<style scoped>							// 组件样式:scope指仅作用于当前
p {
  font-size: 2em;
  text-align: center;
}
</style>

return

(1) 返回对象,当前组件可引用来进行初始化,作用域仅限于当前组件!

(2) rules对象为组件配置监听,作用域仅限于当前组件!
集成样例:

</template>
<script>
import ChildComponents from './ChildComponents.vue' // 提前引入子组件
import Cookie from '../lib/cookie.js'  			// 引入公共Js脚本或类库

export default {
  data () {  						//组件的私有数据(基于函数来返回私有对象)
    return {
      title: '...',
      firstName: '...',
      lastName: '...',
    }
  },
  props: ['age'],					// 父组件传递过来的数据(数组或对象)
  computed: {						// 计算属性
      函数名: function (){}
  },						
  watch: {							// 监听
    title (preVal, newVal) {
        console.log(`改变之前的值:${preVal};改变之后的值:${newVal}`)
    }
  },
  methods: {},						// 函数集
  beforeCreated () {}				// 各种钩子函数...
}
</script>


<style lang="scss" scoped>			// CSS样式:scoped省略后会应用到全局
@import "../base/reset.css";		// 支持import语法引入css文件	
...
</style>

插座插槽

为了拼接组合多个组件,Vue提出了插座插槽的概念,巧妙的是,Vue通过对插座插槽里的组件进行拔插就能实现局部更新(后续)!
编写组件

Vue.component('cmp-a', {                      // 组件名:cmp-a
        props: ['a_attr1'],                   // 属性名:a_attr1
        template: '<li>{{ a_attr1 }}</li>'    // 组件内容
    }
);
Vue.component('cmp-b', {                      // 组件名:cmp-b
        props: ['b_attr1'],                   // 属性名:b_attr1
        template: '<li>{{ b_attr1 }}</li>'    // 组件内容
    }
);

编写插座

Vue.component('slot-x', {	// 组件名:slot-x
        template:			// 组件内容:插座=[slot-a]+[slot-b]+..
            '<div>\
                <slot name="slot-a"></slot>\
                <ul>\
                    <slot name="slot-b"></slot>\
                </ul>\
             </div>'
    }
);

编写视图模型

let vue = new Vue({
    el: '#demo',
    data: {
        msg1: "Alpha",
        msg2: ["A", "B", "C"]
    }
});

使用插座

<div id="demo">
  <!-- 插座:<slot-x>的作用是在此处放置一个插座 -->
  <slot-x>
    <cmp-a slot="slot-a" :a_attr1="msg1"></cmp-a>
    <cmp-b slot="slot-b" v-for="ele in msg2" :b_attr1="ele"></cmp-b>
  </slot-x>
</div>

组件事件

组件调用自定义事件的函数其实分为两种,一个是调用组件内部的函数,另一个是调用视图模型的函数
组件函数

// 1、编写组件
Vue.component('cmp', {                          // 组件名:cmp
        props: ['attr1'],                       // 属性:attr1
        template:                               // 组件内容
            '<li>{{ attr1 }}  <button v-on:click="emit_remove">删除</button></li>',
        methods: {                              // 函数:emit_remove()
            emit_remove: function () {
                alert("你点击了删除!");
            }
        }
    }
);

说明:v-on:click事件调用属性可以简写为@click,二者作用完全相同!
使用组件

<div id="demo">
  <cmp slot="slot-b" v-for="(ele, index) in msg" :attr1="ele"></cmp>
</div>

模型函数

由于ViewModel和组件分别属于两个访问域,所以组件内部并不能直接访问ViewModel,这样就一来,组件事件函数就不能修改视图模型中的数据。不过,Vue巧妙地借助事件分发解决了问题。

所谓分发,指当触发组件的事件函数时,this.$emit()语句又会触发属性所绑定的函数,就像是一次触发被分给了两个函数!
编写组件

Vue.component('cmp', {                          // 组件名:cmp
        props: ['attr1', 'del'],                // 属性
        template: '<li>{{ attr1 }}  <button v-on:click="emit_remove">删除</button></li>',    	 // 组件内容
        methods: {                              // 函数
            emit_remove: function (del) {
                // 事件分发:触发emit_remove属性所绑定的函数
                this.$emit('emit_remove', del);
            }
        }
    }
);

编写视图模型

let vue = new Vue({
    el: '#demo',
    data: {
        msg: ["A", "B", "C"]
    },
    methods: {
        remove: function (begin) {
            // splice(begin, len): 从指定索引开始删除数组的若干个元素
            this.msg.splice(begin, 1);
        }
    }
});

使用组件

<div id="demo">
    <cmp slot="slot-b" v-for="(ele, index) in msg"
         :attr1="ele" :del="index" v-on:emit_remove="remove(index)"></cmp>
</div>
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值