浅谈vue组件

一、组件化思想概念

  • 组件化类似于在node中学习的模块化,模块化是一种思想,一种构建方式,把一种很复杂的事务拆分成一个一个小模块,然后通过某种特定的方式把这些 小模块组织到一起相互协作完成这个复杂的功能。
  • 组件思想就是把一个很大的复杂的 Web 页面视图给拆分成一块一块的组件视图,然后利用某种特定的方式把它们组织到一起完成完整的 Web 应用构建。

在 Vue 中,组件就是用来封装视图的,说白了就是封装 HTML

  • 为什么把视图给组件化拆成一块一块的呢?
    • 开发效率
    • 可维护性
    • 其次才是可重用

二、Element

http://element-cn.eleme.io/#/zh-CN

  1. npm install element-ui --save
  2. 引入组件库css样式(lib/theme-chalk/index.css),再引入vue,其次是组件库js脚本

三、使用组件

  1. 先定义(注册)组件

  2. 使用

  3. 组件的模板 template
    注意:只能有一个根元素,否则警告报错
    3.1 template 可以是字面量字符串,缺点是没有高亮,内置在 JavaScript 中,写起来麻烦
    3.2 template 可以写在 script 标签中,虽然解决了高亮的问题,但是也麻烦
    3.3 以上方式都不好,我们最终的解决方案是使用 Vue 的 .vue 单文件组件来写。(webpack)
    但是要想使用这种方式必须结合一些构建工具

  4. 组件是独立的作用域,就像我们 Node 中的 JavaScript 模块一样,独立的

  5. 组件其实就是一个特殊的 Vue 实例,可以有自己的 data、methods、computed、watch 等等选项

  6. 组件的 data 必须是函数
    函数中返回一个对象作为组件的 data

例:感知基本组件:

Vue.component('my-component', {
      template: `
        <div>
          <div>My Component</div>
          <h2>{{ message }}</h2>
          <input type="text" v-model="message" />
          <button @click="handleClick">点击弹出自己的 message</button>
          <input type="checkbox" v-model="checked" />
          <div class="box" v-if="checked"></div>
        </div>
      `,
      data () {
        return {
          message: 'Component Data',
          checked: true
        }
      },
      methods: {
        handleClick () {
          window.alert(this.message)
        }
      }
    })

    const app = new Vue({
      data: {
        message: 'Hello Vue.js!'
      },
      methods: {}
    }).$mount('#app')

例:单文件组件(.vue文件)

<!-- 
  但是这种方式浏览器不能直接识别,需要结合 webpack 构建工具才能玩儿。
 -->

<!-- 组件的模板,写到 template 中 -->
<template>
<div></div>
</template>

<!-- 组件的 JavaScript 脚本写到 script 标签中 -->
<script>
export default {
  data () {
    return {}
  }
}
</script>

<!-- 组件的 CSS 写到 style 标签中 -->
<style>
</style>

四、组件通信

1. 全局组件和局部组件

  • Vue.component生成的组件是全局的组件
  • 在上面这个vue实例中使用components配置的组件是局部的组件
<body>
  <div id="app">
    <h1>{{ message }}</h1>
    <hello></hello>
    <global-component></global-component>
  </div>
  <script src="node_modules/vue/dist/vue.js"></script>
  <script>
    Vue.component('global-component', {
      template: `<div>
        <h2>global component</h2>
        <global2-component></global2-component>
        <hello></hello>
      </div>`,
      // 组件实例选项 components 也是用来定义组件,但是这种方式定义的组件只能在当前组件中使用
      components: {
        // 键名就是组件名称,值是一个对象,对象中配置组件的选项
        hello: {
          template: '<div>hello component</div>'
        }
      }
    })

    Vue.component('global2-component', {
      template: '<div>global2 component</div>'
    })

    Vue.component('global2-component', {
      template: '<div>global3 component</div>'
    })

    const app = new Vue({
      data: {
        message: 'Hello Vue.js!'
      },
      methods: {}
    }).$mount('#app')
  </script>
</body>

结果如下图所示
结果
可以看出在app中hello报错,因为hello不是全局组件

2. 组件分类

  1. 通用的组件,例如轮播图、评分
  2. 设计具体业务的组件,不通用

所以设计具体业务的尽量定义成局部,不要污染全局

3. 父---->子通信 [props Down]

  1. 在父组件中通过子组件标签声明属性的方式传递数据
    注意:只有 v-bind 才可以传递动态数据
  2. 在子组件中声明 props 接收父组件传递给自己的数据
  3. 然后你就可以在子组件中对数据进行 “为所欲为”
    只能使用,不要修改

例:

  1. 在父组件中将数据绑定传给子组件
<todo-list
		:todos="todos"
		:filterText="filterText"></todo-list>
  1. 在子组件中利用props接收
template,
		// 子组件就会把父组件在标签中声明的 foo 给拿过来
		props: ['todos', 'filterText'],
		data () {
			return {
			}
		},

注意:在父组件传给子组件的数据中

  • 引用类型的数据可以修改,但不能重新赋值(不建议,会违背通信原则即单向数据流原则)
  • 普通类型不允许修改(子组件无修改父组件的能力)

4. 子----> 父传值 [Events Up]

  1. 在父组件中定义一个方法(纯业务方法)
  2. 在子组件内部调用父组件的方法
    在子组件中发布一个自定义事件,通知父亲我可以去添加任务了
  3. 在父组件使用子组件的标签上订阅子组件内部发布的自定义事件

例:
在父组件上定义好方法:

methods: {
			addTodo (titleText) {
				console.log('父组件的 addTodo 方法被调用了')
				titleText = titleText.trim()
				if (!titleText.length) {
					return
				}
				const todos = this.todos
				todos.push({
					id: todos[todos.length - 1].id + 1,
					title: titleText,
					completed: false
				})
			}
		}

在子组件内部调用其方法

methods: {
   		handleKeydown (e) {
   			// 0. 获取文本框的值
   			// 1. 非空校验
   			// 2. 添加任务到 todos 中
   			const target = e.target
   			const value = target.value.trim()
   			if (!value.length) {
   				return
   			}

   			// 在子组件中数据已经准备就绪,可以交给父组件使用了
   			// 子组件通知父组件你去 addTodo 去吧。
   			// 子组件不关心父组员的业务
   			// 父组件到底拿到这个数据干嘛?
   			// 对于子组件来讲,根本不关心,你爱干嘛干嘛
   			// 由于不关心业务,所以该组件重用的几率将会大大的增加
   			// 谁来用我,我就就把数据给谁
   			this.$emit('addTodo', value)

   			target.value = ''

   		}
   	}

在父组件使用子组件的标签上订阅子组件内部发布的自定义事件

<todo-header
		:todos="todos"
		:foo="foo"
		@addTodo="addTodo"></todo-header>
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值