vue组件化开发

一般面试时问道组件怎么回答?
**答:**我用vue开发的所有项目,都是采用组件化的思想开发的。一般我在搭建项目的时候,会创建一个views目录和一个commen目录和一个feature目录,views目录中放页面级的组件,commen中放公共组件(如:head(公共头组件),foot(公共底部组件)等),feature目录内放功能组件(如:swiper(轮播功能组件),tabbar(切换功能组件)、list(上拉加载更多功能组件))

首先,组件可以提升整个项目的开发效率。能够把页面抽象成多个相对独立的模块,解决了我们传统项目开发:效率低、难维护、复用性低等问题。

使用组件的好处

组件是可以复用的
易于维护
有封装性,易于使用
大项目中降低组件之间的重复性

全局组件

引用全局组件my-header
<body>
  <div id="main1">
    <!-- 正常模板解析的时候,不会将自定义标签解读出来,而是将自己定义组件里的参数解读出来,也就是下面template中的h1标签 -->
    <my-header></my-header>
  </div>
   <div id="main2">
     <!-- 自定义组件具有复用性 -->
    <my-header></my-header>
  </div>
   <div id="main3">
    <my-header></my-header>
  </div>
</body> 

注册全局组件my-header

//全局组件:在任何地方,任何方式,任何地点都可以使用的标签组件
vue.component("my-header", {
    	// h1标签是我们在自定义主键里面写的参数的标签
    	template: '<h1>标题{{msg}}</h1>',
    	data(){
    	   return {msg:100}
    	}
    })
	new Vue({
	  	el: '#main'
	  });
	  new Vue({
	  	el: '#main2'
	  });
	  new Vue({
	  	el: '#main3'
	  });

局部组件

局部组件:只是在我们规定的范围内才会生效。
 <body>
    <div id="main">
      <my-header></my-header>
      <my-header></my-header>
    </div>
  </body>
  new Vue({
    	el: '#main',
    	components: {
    		"my-header": {
    		template: '<h1>标题{{vue}}</h1>'
    		}
    	}
    })


注意:

当使用 kebab-case(中划线命名) 定义一个组件时,你也必须在引用这个自定义元素时使用 kebab-case,例如
当使用 PascalCase (驼峰式命名) 定义一个组件时,你在引用这个自定义元素时两种命名法都可以使用。也就是说
和 都是可接受的。注意,尽管如此,直接在 DOM(即非字符串的模板) 中使用时只有kebab-case 是有效的

//中划线 使用语法: <my-component-name>`
Vue.component('my-component-name', { /* ... */ })
//驼峰  使用语法:<my-component-name> `和` <MyComponentName>`都可以
Vue.component('MyComponentName', { /* ... */ })

脚手架vue-cli中的组件

我们一般通过脚手架vue-cli开发项目,每个 .vue单文件就是一个组件。在父组件中使用import 导入一个子组件,并在components中注册子组件,子组件需要数据,可以在props中接受定义。而子组件修改好数据后,想把数据传递给父组件。可以采用$emit方法触发自定义事件传递参数。

父传子(props)

prop 的定义应该尽量详细,至少需要指定其类型

<!-- 父组件 -->
<template>
    <div>
        <my-child :parentMessage="parentMessage"></my-child>
    </div>
</template>

<script>
    import MyChild from '@components/common/MyChild'

    export default {
        components: {
            MyChild
        },
        data() {
            return {
                parentMessage: "我是来自父组件的消息"
            }
        }
    }
</script>

<!-- 子组件 -->
<template>
    <div>
        <span>{{ parentMessage }}</span>
    </div>
</template>

<script>
    export default {
        props: {
            parentMessage: {
                type: String,
                default: '默认显示的信息'
                // require: true // 必填
            }
        }
    }
</script>

通过$on传递父组件方法

通过$on传递父组件方法是组件通信中常用的方法传递方式。它可以与通过props传递方法达到相同的效果。相比于props传递function,它更加的直观和显示的表现出了调用关系

<!-- 父组件 -->
<template>
    <div>
        <my-child @childEvent="parentMethod"></my-child>
    </div>
</template>

<script>
    import MyChild from '@components/common/MyChild'

    export default {
        components: {
            MyChild,
        },
        data() {
            return {
                parentMessage: '我是来自父组件的消息',
            }
        },
        methods: {
            parentMethod() {
                alert(this.parentMessage)
            }
        }
    }
</script>

<!-- 子组件 -->
<template>
    <div>
        <h3>子组件</h3>
    </div>
</template>

<script>
    export default{
        mounted() {
            this.$emit('childEvent')
        }
    }
</script>

$parent获取父组件然后使用父组件中的数据(不推荐)

准确来说这种方式并不属于数据的传递而是一种主动的查找。父组件并没有主动的传递数据给子组件,而是子组件通过与父组件的关联关系,获取了父组件的数据。
该方法虽然能实现获取父组件中的数据但是不推荐这种方式,因为vue提倡单向数据流,只有父组件交给子组件的数据子组件才有使用的权限,不允许子组件私自获取父组件的数据进行使用。在父与子的关系中子应当是处于一种被动关系

// 此处的this为子组件实例
this.$parent

通过$emit传递父组件数据 (推荐)

与父组件到子组件通讯中的$on配套使用,可以向父组件中触发的方法传递参数供父组件使用

<!-- 父组件 -->
<template>
    <div>
        <my-child @childEvent="parentMethod"></my-child>
    </div>
</template>

<script>
    import MyChild from '@components/common/MyChild'

    export default {
        components: {
            MyChild
        },
        data() {
            return {
                parentMessage: '我是来自父组件的消息'
            }
        },
        methods: {
            parentMethod({ name, age }) {
                console.log(this.parentMessage, name, age)
            }
        }
    }
</script>

<!-- 子组件 -->
<template>
    <div>
        <h3>子组件</h3>
    </div>
</template>

<script>
    export default {
        mounted() {
            this.$emit('childEvent', { name: 'zhangsan', age:  10 })
        }
    }
</script>

refs获取

可以通过在子组件添加ref属性,然后可以通过ref属性名称获取到子组件的实例。准确来说这种方式和this.$parent
一样并不属于数据的传递而是一种主动的查找。

尽量避免使用这种方式。因为在父子组件通信的过程中。父组件是处于高位是拥有控制权,而子组件在多数情况下应该为纯视图组件,只负责视图的展示和自身视图的逻辑操作。对外交互的权利应该由父组件来控制。所以应当由父组件传递视图数据给子组件,子组件负责展示。而子组件的对外交互通过$emit触发父组件中相应的方法,再由父组件处理相应逻辑

<!-- 父组件 -->
<template>
    <div>
        <my-child ref="child"></my-child>
    </div>
</template>

<script>
    import MyChild from '@components/common/MyChild'

    export default {
        components: {
            MyChild
        },
        mounted() {
            console.log(this.$refs['child'].getData());
        }
    }
</script>

<!-- 子组件 -->
<script>
    export default {
        methods: {
            getData() {
                // do something...
            }
        }
    }
</script>

组件样式修改 样式穿透
css父组件修改子组件中的样式
如果你希望scoped样式中的一个选择器能够作用得“更深”,例如影响子组件,你可以使用 >>> 操作符:

<style scoped>
    .a >>> .b { /* ... */ }
</style>

上一篇:ODBC 、DAO 、ADO 、OLEDB 数据库连接方式区别及联系


下一篇:vue组件化开发