热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Vue的组件化

文章目录Vue的组件化一、认识组件化1.什么是组件化2.组件化思想二、注册组件1.组件的使用步骤三、组件其他补充1.全局组件和局部组件2.父组件和子组件3.组件的语法糖写法4.组件


文章目录

  • Vue的组件化
    • 一、认识组件化
      • 1. 什么是组件化
      • 2. 组件化思想
    • 二、注册组件
      • 1. 组件的使用步骤
    • 三、组件其他补充
      • 1. 全局组件和局部组件
      • 2. 父组件和子组件
      • 3. 组件的语法糖写法
      • 4. 组件模板抽离的写法
    • 四、组件数据存放
      • 1. 组件能访问vue中的数据吗
      • 2. 组件中的data为什么必须是函数
    • 五、父子组件通信
      • 1. 父传子props
      • 2. props的驼峰命名
      • 3. 子传父(自定义事件)
      • 4. 数据双向绑定案例
      • 5. 父访子-\$children-\$refs
      • 6. 子访父-\$parent-\$root
    • 六、插槽slot
      • 1. 为什么要使用插槽
      • 2. 插槽的封装和基本使用
      • 3. 具名插槽
      • 4. 作用域插槽


Vue的组件化


一、认识组件化


1. 什么是组件化


  • 如果我们将一个页面中所有的处理逻辑全部放在一起,处理起来就会变得非常复杂,而且不利于后续的管理以及扩展。
  • 但如果,我们将一个页面拆分成一个个小的功能块,每个功能块完成属于自己这部分独立的功能,那么之后整个页面的管理和维护就变得非常容易了。

组件化概念


  • 我们将一个完整的页面分成很多个组件。
  • 每个组件都用于实现页面的一个功能块。
  • 而每一个组件又可以进行细分。

2. 组件化思想


  • 它提供了一种抽象,让我们可以开发出一个个独立可复用的小组件来构造我们的应用。
  • 任何的应用都会被抽象成一颗组件树。
  • 组件化思想的应用:
    • 有了组件化的思想,我们在之后的开发中就要充分的利用它。
    • 尽可能的将页面拆分成一个个小的、可复用的组件。
    • 这样让我们的代码更加方便组织和管理,并且扩展性也更强。

组件化思想


二、注册组件


1. 组件的使用步骤


  • 创建组件构造器
    • Vue.extends()
      • 调用Vue.extend()创建的是一个组件构造器
      • 通常在创建组件构造器时,传入template代表我们自定义组件的模板
      • 该模板就是在使用到组件的地方,要显示的HTML代码
      • 事实上,这种写法在Vue2.x的文档中几乎已经看不到了,它会直接使用下面我们会讲到的语法糖,但是在很多资料还是会提到这种方式,而且这种方式是学习后面方式的基础
  • 注册组件
    • Vue.component()
      • 调用Vue.component()是将刚才的组件构造器注册为一个组件,并且给它起一个组件的标签名称
      • p所以需要传递两个参数:1、注册组件的标签名 2、组件构造器
  • 使用组件
    • 组件必须挂载在某个Vue实例下,否则它不会生效

<div id&#61;"app"><hello-vue>hello-vue><hello-vue>hello-vue><hello-vue>hello-vue><hello-vue>hello-vue>div><script src&#61;"../js/vue.js">script><script>const cpnC &#61; Vue.extend({template:&#96;

hello vue

&#96;})Vue.component(&#39;hello-vue&#39;,cpnC)const app &#61; new Vue({el: &#39;#app&#39;,data: {msg: &#39;hello vue!&#39;}})script>

三、组件其他补充


1. 全局组件和局部组件

上述方式是全局组件&#xff0c;可以在多个vue实例中使用。&#xff08;实际开发一般从头到尾就一个vue实例&#xff09;

局部组件注册&#xff1a;

const app &#61; new Vue({el: &#39;#app&#39;,data: {msg: &#39;hello vue!&#39;},components:{//cpn使用组件时的标签名cpn:cpnC}
})

2. 父组件和子组件

<div id&#61;"app"><cpn1>cpn1>div><script src&#61;"../js/vue.js">script><script>//子组件const cpnC2 &#61; Vue.extend({template: &#96;

hello vue2

&#96;})//父组件const cpnC1 &#61; Vue.extend({template: &#96;

hello vue

&#96;
,components:{cpn2:cpnC2}})const app &#61; new Vue({el: &#39;#app&#39;,data: {msg: &#39;hello vue!&#39;},components: {//cpn使用组件时的标签名cpn1: cpnC1}})script>

3. 组件的语法糖写法

省去extend

//全局组件
Vue.component(&#39;hello-vue&#39;,{template:&#96;

hello vue

&#96;
})
//局部组件
const app &#61; new Vue({el: &#39;#app&#39;,data: {msg: &#39;hello vue!&#39;},components:{//cpn使用组件时的标签名cpn:{template:&#96;

hello vue

&#96;
}}
})

4. 组件模板抽离的写法

标签中写&#xff0c;两种方式&#xff1a;


  • 中写
  • 标签中写

然后使用id选择器放到模板后面


四、组件数据存放


1. 组件能访问vue中的数据吗


  • 组件无法访问vue实例中的数据
  • 组件的数据存放在组件中的data里&#xff0c;数据为函数格式&#xff0c;返回一个值

2. 组件中的data为什么必须是函数

当我们封装好一个组件之后&#xff0c;在html使用组件实例&#xff0c;例如封装计数器组件&#xff0c;我们创建三个组件实例&#xff0c;每个组件实例都有数值的改变&#xff0c;如果组件中的data是对象或者数组形式&#xff0c;其中一个组件实例的数字改变&#xff0c;其他组件的数值也会跟着改变&#xff0c;因为组件在使用data中的数据时&#xff0c;三个组件的内存地址都会指向同一个data中的内存地址。而使用函数进行返回值&#xff0c;函数每次返回数据都会开辟一个新的内存地址&#xff0c;这就使得每一个组件指向的data中的数据都是不同的内存地址&#xff0c;这样其中一个计数器数值增加&#xff0c;其他计数器数值才不会跟着增加


五、父子组件通信


  • 在上一个小节中&#xff0c;我们提到了子组件是不能引用父组件或者Vue实例的数据的。
  • 但是&#xff0c;在开发中&#xff0c;往往一些数据确实需要从上层传递到下层&#xff1a;
    • 比如在一个页面中&#xff0c;我们从服务器请求到了很多的数据。
    • 其中一部分数据&#xff0c;并非是我们整个页面的大组件来展示的&#xff0c;而是需要下面的子组件进行展示。
    • 这个时候&#xff0c;并不会让子组件再次发送一个网络请求&#xff0c;而是直接让大组件(父组件)将数据传递给小组件(子组件)。

1. 父传子props

<body><div id&#61;"app"><cpn :cmovies&#61;"movies">cpn>div><script type&#61;"text/x-template" id&#61;"cpn"><ul><li v-for&#61;"item in cmovies">{{item}}</li></ul>script><script src&#61;"../js/vue.js">script><script>const cpn &#61; {template: &#39;#cpn&#39;,data() {return {}},props: [&#39;cmovies&#39;]}const app &#61; new Vue({el: &#39;#app&#39;,data: {msg: &#39;hello vue!&#39;,movies: [&#39;a&#39;, &#39;b&#39;, &#39;c&#39;]},components: {cpn}})script>

  • 在子组件中使用props属性给要传的数据命名
  • 在子组件模板中直接使用命名后的数据命
  • 在html中引用组件时使用v-bind绑定父组件的数据
  • props有两种写法&#xff1a;
    • 上面的数组写法&#xff0c;一般不用

    • 对象写法

      • 可以设置默认值
      • 可以进行数据类型验证
    • 对象写法可验证的数据类型

      • String
      • Number
      • Boolean
      • Array
      • Object
      • Date
      • Function
      • Symbol
      • 自定义类型
    • props: {//基础的类型检查&#xff08;null匹配任何类型&#xff09;propA: Number,//多个可能的类型propB: [String, Number],//必填的字符串propC: {type: String,required: true},// 带有默认值的数字prorD: {type: Number,default: 100},// 带有默认值的对象propE: {type: Object,// 对象或数组默认值必须从一个工厂函数获取default() {return {msg: &#39;hello&#39;}},},// 自定义验证函数propF: {validator(value) {// 这个值必须匹配下列字符串中的一个return [&#39;success&#39;, &#39;warning&#39;, &#39;danger&#39;].indexOf(value) !&#61;&#61; -1}}}


2. props的驼峰命名

在子组件中我们习惯使用驼峰命名&#xff0c;但是在html中绑定时&#xff0c;html无法识别驼峰命名&#xff0c;因此会报错&#xff0c;此时我们要么不使用驼峰命名&#xff0c;要么在html使用该名字时将驼峰命名改为用-连接&#xff0c;即cMovies---->c-movies


3. 子传父(自定义事件)

<div id&#61;"app"><cpn &#64;itemclick&#61;"nameclick">cpn>
div>
<template id&#61;"cpn"><div><button &#64;click&#61;"cnameClick(name)" v-for&#61;"name in names">{{name.name}}button>div>
template>
<script src&#61;"../js/vue.js">script>
<script>const cpn &#61; {template: &#39;#cpn&#39;,data() {return {names: [{id: 1, name: &#39;老子&#39;},{id: 2, name: &#39;孟子&#39;},{id: 3, name: &#39;孔子&#39;},{id: 4, name: &#39;荀子&#39;},]}},methods: {cnameClick(name){console.log(name,&#39;c&#39;)this.$emit(&#39;itemclick&#39;,name)},}}const app &#61; new Vue({el: &#39;#app&#39;,data: {msg: &#39;hello vue!&#39;},components: {cpn},methods: {nameclick(name){console.log(name)}}})
script>

  • 监听子组件中发生的事件

  • <template id&#61;"cpn"><div><button &#64;click&#61;"cnameClick(name)" v-for&#61;"name in names">{{name.name}}button>div>
    template>

  • 在子组件中写调用的方法

    • methods: {cnameClick(name){console.log(name,&#39;c&#39;)this.$emit(&#39;itemclick&#39;,name)},}

    • 并将该方法事件发送给父组件&#xff0c;参数为&#xff1a;自定义事件名&#xff0c;要传的参数

      • this.$emit(&#39;itemclick&#39;,name)
  • 在html中使用该组件&#xff0c;并使用自定义事件监听

    • <div id&#61;"app"><cpn &#64;itemclick&#61;"nameclick">cpn>
      div>

    • 调用的方法未写参数默认传发射过来的第一个参数

  • 在父组件中写自定义事件的回调方法

    • methods: {nameclick(name){console.log(name)}}

    • 方法带的参数与$emit发射的参数相同


4. 数据双向绑定案例

<body><div id&#61;"app"><cpn :number1&#61;"num1" :number2&#61;"num2" &#64;num1change&#61;"num1change" &#64;num2change&#61;"num2change">cpn>div><template id&#61;"cpn"><div>props:{{number1}}data:{{dnumber1}}<input type&#61;"text" :value&#61;"dnumber1" &#64;input&#61;"num1input">props:{{number2}}data:{{dnumber2}}<input type&#61;"text" :value&#61;"dnumber2" &#64;input&#61;"num2input">div>template><script src&#61;"../js/vue.js">script><script>const app &#61; new Vue({el: &#39;#app&#39;,data: {num1: 1,num2: 0},components: {cpn: {template: &#39;#cpn&#39;,props: {number1: Number,number2: Number,},data(){return {dnumber1 : this.number1,dnumber2 : this.number2,}},methods:{num1input(event){this.dnumber1 &#61; event.target.valuethis.$emit(&#39;num1change&#39;,this.dnumber1)this.dnumber2 &#61; this.dnumber1 * 100this.$emit(&#39;num2change&#39;,this.dnumber2)},num2input(event){this.dnumber2 &#61; event.target.valuethis.$emit(&#39;num2change&#39;,this.dnumber2)this.dnumber1 &#61; this.dnumber2 / 100this.$emit(&#39;num1change&#39;,this.dnumber1)}}}},methods: {num1change(num){this.num1 &#61; parseInt(num)},num2change(num){this.num2 &#61; parseInt(num)}}})script>
body>

需求&#xff1a; 子组件的输入框中显示父组件中定义的num1&#xff0c;num2&#xff0c;更改子组件输入框中的内容&#xff0c;父组件的num1&#xff0c;num2跟着改变

思路&#xff1a;


  1. 用父传子props把数据传给子组件&#xff0c;然后在输入框中使用v-model双向绑定父传过来的数据
    1. 不可行
    2. 因为官方规定&#xff0c;父组件传过来的数据只能有父组件更改&#xff0c;否则造成混乱&#xff0c;因此报错
  2. 用父传子props把数据传给子组件&#xff0c;子组件在data中将传过来的数据用另一个变量number1&#xff0c;number2保存&#xff0c;在子组件输入框中更改时&#xff0c;将数据保存到number1&#xff0c;number2中&#xff0c;然后使用自定义事件&#xff0c;将更改后的数据传入给父组件&#xff0c;父组件在自己内部将子组件传过来的数据给原来的num1,num2
    1. 可行
    2. 这种双向绑定的方法就是v-model的原理
    3. 完整代码在上方

5. 父访子-$children-$refs

当父组件要访问子组件中的方法或者属性时&#xff0c;可以使用以下两种方法


  • $children
    • 写法&#xff1a;this.$children
    • 作用&#xff1a;拿到所有子组件实例&#xff0c;返回一个数组
    • 由于不能固定拿到某个组件&#xff0c;使用很少
  • $refs
    • 写法&#xff1a;this.$refs.xxxx,在子组件实例中要加上ref&#61;"xxxx"属性
    • 作用&#xff1a;拿到对应名字的组件实例&#xff0c;返回一个对象
    • 使用多

6. 子访父-$parent-$root

使用很少&#xff0c;且不建议使用&#xff0c;耦合度高

写法与父访子类似&#xff0c;两个的区别&#xff0c;字面意思可看出


六、插槽slot


1. 为什么要使用插槽

生活中插槽目的是让我们原来的设备进行扩展性

vue中组件的插槽也是为了让封装的组件更加有扩展性&#xff0c;让使用者可以决定组件内部一些内容到底展示什么


2. 插槽的封装和基本使用

封装&#xff1a;


  • 在组件中定义一个标签即可
  • 标签中可以写上默认要放的东西

使用&#xff1a;


  • 在组件实例标签中写的所有内容会替换标签
  • 如果不写则显示默认内容

3. 具名插槽

上述方法只能将组件实例标签中的所有内容替换给所有的标签

假设我们定义了3个插槽&#xff0c;而我们只想替换中间那个插槽那我们就要给中间那个插槽命名

写法&#xff1a;


  • 插槽&#xff1a;
  • 组件实例标签&#xff1a;

4. 作用域插槽

一句话总结&#xff1a;父组件替换插槽的标签&#xff0c;但是内容由子组件来提供。

个人理解&#xff1a;子组件定义数据&#xff0c;父组件决定表现形式

需求&#xff1a;


  • 子组件中包括一组数据&#xff0c;比如&#xff1a;pLanguages: [‘Javascript’, ‘Python’, ‘Swift’, ‘Go’, ‘C&#43;&#43;’]
  • 需要在多个界面进行展示&#xff1a;
    • 某些界面是以水平方向一一展示的
    • 某些界面是以列表形式展示的
    • 某些界面直接展示一个数组
  • 内容在子组件&#xff0c;希望父组件告诉我们如何展示&#xff0c;怎么办呢&#xff1f;
    • 使用作用域插槽

写法&#xff1a;


  • 子组件插槽中定义一个名字并绑定一个数据&#xff0c;这里定义data绑定pLanguages

  • 在父组件中使用该插槽时&#xff0c;使用包裹需要使用的子组件的数据即可引用

    • <cpn><template slot-scope&#61;"slot">{{slot.data}}template>
      cpn>

表现形式

需求&#xff1a;


  • 子组件中包括一组数据&#xff0c;比如&#xff1a;pLanguages: [‘Javascript’, ‘Python’, ‘Swift’, ‘Go’, ‘C&#43;&#43;’]
  • 需要在多个界面进行展示&#xff1a;
    • 某些界面是以水平方向一一展示的
    • 某些界面是以列表形式展示的
    • 某些界面直接展示一个数组
  • 内容在子组件&#xff0c;希望父组件告诉我们如何展示&#xff0c;怎么办呢&#xff1f;
    • 使用作用域插槽

写法&#xff1a;


  • 子组件插槽中定义一个名字并绑定一个数据&#xff0c;这里定义data绑定pLanguages

  • 在父组件中使用该插槽时&#xff0c;使用包裹需要使用的子组件的数据即可引用

    • <cpn><template slot-scope&#61;"slot">{{slot.data}}template>
      cpn>

参考&#xff1a;vue从入门到精通


推荐阅读
  • Vue.Js_Vue之vue.js声明式渲染
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了Vue之vue.js声明式渲染相关的知识,希望对你有一定的参考价值。ht ... [详细]
  • Voicewo在线语音识别转换jQuery插件的特点和示例
    本文介绍了一款名为Voicewo的在线语音识别转换jQuery插件,该插件具有快速、架构、风格、扩展和兼容等特点,适合在互联网应用中使用。同时还提供了一个快速示例供开发人员参考。 ... [详细]
  • VueCLI多页分目录打包的步骤记录
    本文介绍了使用VueCLI进行多页分目录打包的步骤,包括页面目录结构、安装依赖、获取Vue CLI需要的多页对象等内容。同时还提供了自定义不同模块页面标题的方法。 ... [详细]
  • 从零基础到精通的前台学习路线
    随着互联网的发展,前台开发工程师成为市场上非常抢手的人才。本文介绍了从零基础到精通前台开发的学习路线,包括学习HTML、CSS、JavaScript等基础知识和常用工具的使用。通过循序渐进的学习,可以掌握前台开发的基本技能,并有能力找到一份月薪8000以上的工作。 ... [详细]
  • 【Vue基础】监听属性watch
    Vue监听属性是watch,我们可以通过watch来响应数据的变化。代码示例: ... [详细]
  • 认识Vue关于Vue的描述有不少,不外乎都会拿来与Angular和React对比,同样头顶MVVM双向数据驱动设计模式光环的Angular自然被对比的最多,但到目前为止,Angul ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • Webpack5内置处理图片资源的配置方法
    本文介绍了在Webpack5中处理图片资源的配置方法。在Webpack4中,我们需要使用file-loader和url-loader来处理图片资源,但是在Webpack5中,这两个Loader的功能已经被内置到Webpack中,我们只需要简单配置即可实现图片资源的处理。本文还介绍了一些常用的配置方法,如匹配不同类型的图片文件、设置输出路径等。通过本文的学习,读者可以快速掌握Webpack5处理图片资源的方法。 ... [详细]
  • 本文介绍了如何使用Express App提供静态文件,同时提到了一些不需要使用的文件,如package.json和/.ssh/known_hosts,并解释了为什么app.get('*')无法捕获所有请求以及为什么app.use(express.static(__dirname))可能会提供不需要的文件。 ... [详细]
  • 本文介绍了Sencha Touch的学习使用心得,主要包括搭建项目框架的过程。作者强调了使用MVC模式的重要性,并提供了一个干净的引用示例。文章还介绍了Index.html页面的作用,以及如何通过链接样式表来改变全局风格。 ... [详细]
  • Node.js学习笔记(一)package.json及cnpm
    本文介绍了Node.js中包的概念,以及如何使用包来统一管理具有相互依赖关系的模块。同时还介绍了NPM(Node Package Manager)的基本介绍和使用方法,以及如何通过NPM下载第三方模块。 ... [详细]
  • express工程中的json调用方法
    本文介绍了在express工程中如何调用json数据,包括建立app.js文件、创建数据接口以及获取全部数据和typeid为1的数据的方法。 ... [详细]
  • 方便不想看完全篇文章的童鞋,简单总结一下,这是篇软广,主要是推广自己在业务中沉淀的一个开源组件vue-dynamic-form-component。基于element-ui实现的v ... [详细]
  • vue.js2.0点击获取自己的属性和jquery
    <!DOCTYPEhtml><html><head><metacharsetUTF-8><title>< ... [详细]
  • html css在线便宜,在线HTML、CSS和JS工具汇总
    本文提供了在线HTML、CSS和JS工具汇总,它们都是直接在浏览器上可以使用的在线工具,基本上都是比较简单操作的,只适合简单的调试工作&# ... [详细]
author-avatar
新洋之家140
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有