vue学习第十章(组件开发)

server/2024/11/18 11:08:43/

🎉🎉🎉欢迎来到我的博客,我是一名自学了2年半前端的大一学生,熟悉的技术是JavaScript与Vue.目前正在往全栈方向前进, 如果我的博客给您带来了帮助欢迎您关注我,我将会持续不断的更新文章!!!🙏🙏🙏

文章目录

  • 1. 组件的基本使用
    • 1.1 创建组件构造器对象
    • 1.2 注册组件
    • 1.3 使用组件
  • 2. 全局组件和局部组件
    • 2.1 全局组件
    • 2.2 局部组件
  • 3. 父组件和子组件的区别
  • 4. 注册组件的语法糖
  • 5. 组件模板的分离写法
    • 5.1 script标签
    • 5.2 template标签
  • 6. 组件的数据
    • 6.1 存放问题
    • 6.2 组件的data为什么必须要是函数
  • 7. 父组件给子组件传递数据
    • 7.1 使用`props`属性,父组件向子组件传递数据
    • 7.2 props属性使用
  • 8. 组件通信
    • 8.1 父传子(props的驼峰标识)
    • 8.2 子传父`$emit`
    • 8.3 父子组件通信案例
  • 9. 父访问子(children-ref)

1. 组件的基本使用

​ 简单的组件示例

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<div id="app"><!-- 3.使用组件 --><my-cpn></my-cpn><my-cpn></my-cpn><my-cpn></my-cpn><cpnc></cpnc>
</div>
<script src="../js/vue.js"></script>
<script>javascript">// 1.创建组件构造器对象const cpnc = Vue.extend({template:`<div><h2>标题</h2><p>内容1...<p><p>内容2...<p></div>`})// 2.全局注册组件Vue.component('my-cpn', cpnc)const app = new Vue({el:"#app",data:{},components:{//局部组件创建cpnc:cpnc}})
</script>
</body>
</html>

​ 组件是可复用的 Vue 实例,且带有一个名字:在这个例子中是 my-cpn。我们可以在一个通过 new Vue 创建的 Vue 根实例中,把这个组件作为自定义元素来使用: <my-cpn></my-cpn>

1.1 创建组件构造器对象

template中是组件的DOM元素内容。

1.2 注册组件

  1. 全局注册,通过 Vue.component
  2. 局部注册,通过 components:{cpnc:cpnc}

1.3 使用组件

​ 像使用html标签一样使用。

  <div id="app"><!-- 3.使用组件 --><my-cpn></my-cpn><my-cpn></my-cpn><my-cpn></my-cpn><cpnc></cpnc></div>

2. 全局组件和局部组件

​ 组件的注册方式有两种,一种是全局组件一种是局部组件。

  <div id="app"><h2>全局组件</h2><my-cpn></my-cpn><h2>局部组件</h2><cpnc></cpnc></div><script src="../js/vue.js"></script><script>javascript">// 1.创建组件构造器对象const cpnc = Vue.extend({template:`<div><h2>标题</h2><p>内容1</p><p>内容2</p></div>`})// 2.注册组件(全局组件,可以在多个vue实例中使用)Vue.component('my-cpn', cpnc)const app = new Vue({el:"#app",components:{//局部组件创建cpnc:cpnc}})</script>

2.1 全局组件

​ 全局组件,可以在多个vue实例中使用,类似于全局变量。

​ 使用Vue.component('my-cpn', cpnc)方式注册,直接使用<my-cpn></my-cpn>调用。my-cpn是全局组件的名字,cpnc是定义的组件对象。

2.2 局部组件

​ 局部组件,只能在当前vue实例挂载的对象中使用,类似于局部变量,有块级作用域。

​ 注册方式

javascript">    const app = new Vue({el:"#app",components:{//局部组件创建cpnc:cpnc}})

​ 使用方式与全局变量一样,直接使用<cpnc></cpnc>调用。cpnc:cpnc第一个cpnc是给组件命名的名字,第二个是定义的组件对象。如果俩个同名也可以直接使用es6语法:

javascript">components:{//局部组件创建cpnc
}

3. 父组件和子组件的区别

  <div id="app"><cpn2></cpn2></div><script src="../js/vue.js"></script><script>javascript">// 1.创建组件构造器对象const cpn1 = Vue.extend({template:`<div><h2>标题1</h2><p>组件1</p></div>`})// 组件2中使用组件1const cpn2 = Vue.extend({template:`<div><h2>标题2</h2><p>组件2</p><cpn1></cpn1></div>`,components:{cpn1:cpn1}})const app = new Vue({el:"#app",components:{//局部组件创建cpn2:cpn2}})</script>

​ 上述代码中定义了两个组件对象cpn1cpn2,在组件cpn2中使用局部组件注册了cpn1,并在template中使用了注册的cpn1,然后在vue实例中使用注册了局部组件cpn2,在vue实例挂载的div中调用了cpn2cpn2cpn1形成父子组件关系。

注意:组件就是一个vue实例,vue实例的属性,组件也可以有,例如data、methods、computed等。

4. 注册组件的语法糖

  <div id="app"><cpn1></cpn1><cpn2></cpn2></div><script src="../js/vue.js"></script><script>javascript">// 1.注册全局组件语法糖Vue.component('cpn1', {template:`<div><h2>全局组件语法糖</h2><p>全局组件语法糖</p></div>`})const app = new Vue({el:"#app",components:{//局部组件创建cpn2:{template:`<div><h2>局部组件语法糖</h2><p>局部组件语法糖</p></div>`}}})</script>

注册组件时候可以不实例化组件对象,直接在注册的时候实例化。{}就是一个组件对象。

5. 组件模板的分离写法

5.1 script标签

​ 使用script标签定义组件的模板,script标签注意类型是text/x-template

  <!-- 1.script标签注意类型是text/x-template --><script type="text/x-template" id="cpn1">javascript"><div><h2>组件模板的分离写法</h2><p>script标签注意类型是text/x-template</p></div></script>

5.2 template标签

​ 使用template标签,将内容写在标签内。

  <!-- 2.template标签 --><template id="cpn2"><div><h2>组件模板的分离写法</h2><p>template标签</p></div></template>

调用分离的模板,使用template:'#cpn1'

  <script src="../js/vue.js"></script><script>javascript">const app = new Vue({el: "#app",components: { //局部组件创建cpn1:{template:'#cpn1'},cpn2: {template: '#cpn2'}}})</script>

6. 组件的数据

6.1 存放问题

​ 前面说过vue组件就是一个vue实例,相应的vue组件也有data属性来存放数据。

  <div id="app"><cpn1></cpn1></div><script src="../js/vue.js"></script><script>javascript">const app = new Vue({el: "#app",components: { //局部组件创建cpn1:{template:'<div>{{msg}}</div>',data(){return {msg:"组件的数据存放必须要是一个函数"}}}}})</script>

template中使用组件内部的数据msg

6.2 组件的data为什么必须要是函数

​ 组件的思想是复用,定义组件当然是把通用的公共的东西抽出来复用。

<div id="app"><h2>data不使用函数</h2><cpn1></cpn1><cpn1></cpn1><hr><h2>data使用函数</h2><cpn2></cpn2><cpn2></cpn2><hr></div><script src="../js/vue.js"></script><template id="cpn1"><div><button @click="count--">-</button>当前计数:{{count}}<button @click="count++">+</button></div></template><template id="cpn2"><div><button @click="count--">-</button>当前计数:{{count}}<button @click="count++">+</button></div></template><script>javascript">const obj = {count:0};const app = new Vue({el: "#app",components: { //局部组件创建cpn1: {template: '#cpn1',data() {return obj;}},cpn2: {template: '#cpn2',data() {return {count: 0}}}}})</script>

上述代码中定义了两个组件cpn1cpn2,都是定义了两个计数器,con1的data虽然使用了函数,但是为了模拟data:{count:0},使用了常量obj来返回count。

图中可以看到,不使用函数data的好像共用一个count属性,而使用函数的data的count是各自用各自的,像局部变量一样有块级作用域,这个块级就是vue组件的作用域。

我们在复用组件的时候肯定希望,各自组件用各自的变量,如果确实需要都用一样的,可以全局组件注册,也可以是用vuex来进行状态管理。

7. 父组件给子组件传递数据

7.1 使用props属性,父组件向子组件传递数据

使用组件的props属性

javascript">const cpn = {template: "#cpn",props: { cmessage: {type: String,default: 'zzzzz',required: true //在使用组件必传值}}
}

向cmessage对象传值

<div id="app"><cpn :cMessage="message"></cpn>
</div>
<script>javascript">    
const app = new Vue({el: "#app",data: {message: "你好",movies: ["复仇者联盟", "钢铁侠", "星际穿越", "哪吒传奇"]},components: {cpn}})</script>

7.2 props属性使用

数组写法

javascript">props: ['cmovies', 'cmessage']

对象写法

javascript">  props: { cmessage: {type: String,default: 'zzzzz',required: true //在使用组件必传值}}

props属性的类型限制

javascript">//1.类型限制(多个类使用数组)
cmovies:Array,//限制为数组类型
cmessage:String,//限制为Strin类型
cmessage:['String','Number']//限制为String或Number类型

props属性的默认值

javascript">// 2.提供一些默认值,以及必传值cmessage: {type: String,default: 'zzzzz',//默认值}

props属性的必传值

javascript">cmessage: {type: String,default: 'zzzzz',required: true //在使用组件必传值}

类型是Object/Array,默认值必须是一个函数

javascript">//类型是Object/Array,默认值必须是一个函数
cmovies: {type: Array,default () {return [1, 2, 3, 4]}
},

自定义验证函数

javascript">vaildator: function (value) {//这个传递的值必须匹配下列字符串中的一个return ['zzzzz', 'ttttt', 'yyy'].indexOf(value) !== -1
}

自定义类型

javascript">    function Person(firstName,lastName) {this.firstName = firstNamethis.lastName = lastName}cmessage:Person//限定了cmeessage必须是Person类型

综合使用

  <div id="app"><cpn :cMovies="movies" :cMessage="message"></cpn></div><template id="cpn"><div><ul><li v-for="(item, index) in cmovies" :key="index">{{item}}</li></ul><h2>{{cmessage}}</h2></div></template><script src="../js/vue.js"></script><script>javascript">function Person(firstName,lastName) {this.firstName = firstNamethis.lastName = lastName}// 父传子:propsconst cpn = {template: "#cpn",// props: ['cmovies', 'cmessage'],//数组写法props: { //对象写法// 1.类型限制(多个类使用数组)// cmovies:Array,// cmessage:String,// cmessage:['String','Number'],// 2.提供一些默认值,以及必传值cmessage: {type: String,default: 'zzzzz',required: true //在使用组件必传值},//类型是Object/Array,默认值必须是一个函数cmovies: {type: Array,default () {return [1, 2, 3, 4]}},// 3.自定义验证函数// vaildator: function (value) {//   //这个传递的值必须匹配下列字符串中的一个//   return ['zzzzz', 'ttttt', 'yyy'].indexOf(value) !== -1// }// 4.自定义类型// cmessage:Person,},data() {return {}},methods: {},};const app = new Vue({el: "#app",data: {message: "你好",movies: ["复仇者联盟", "钢铁侠", "星际穿越", "哪吒传奇"]},components: {cpn}})</script>

8. 组件通信

8.1 父传子(props的驼峰标识)

​ v-bind是 不支持使用驼峰标识的,例如cUser要改成c-User

  <div id="app"><!-- v-bind不支持驼峰 :cUser改成 :c-User--><!-- <cpn :cUser="user"></cpn> --><cpn :c-User="user"></cpn><cpn :cuser="user" ></cpn></div><template id="cpn"><div><!-- 使用驼峰 --><h2>{{cUser}}</h2><!-- 不使用 --><h2>{{cuser}}</h2></div></template><script src="../js/vue.js"></script><script>javascript">// 父传子:propsconst cpn = {template: "#cpn",props: { //对象写法//驼峰cUser:Object,//未使用驼峰cuser:Object},data() {return {}},methods: {},};const app = new Vue({el: "#app",data: {user:{name:'zzz',age:18,height:175}},components: {cpn}})</script>

8.2 子传父$emit

​ 子组件向父组件传值,使用自定义事件$emit

  <!-- 父组件 --><div id="app"><!-- 不写参数默认传递btnClick的item --><cpn @itemclick="cpnClcik"></cpn></div><!-- 子组件 --><template id="cpn"><div><button v-for="(item, index) in categoties" :key="index" @click="btnClick(item)">{{item.name}}</button></div></template><script src="../js/vue.js"></script><script>javascript">const cpn = {template: "#cpn",data() {return {categoties: [{id: 'aaa',name: '热门推荐'},{id: 'bbb',name: '手机数码'},{id: 'ccc',name: '家用家电'},{id: 'ddd',name: '电脑办公'},]}},methods: {btnClick(item) {this.$emit('itemclick', item)}},};const app = new Vue({el: "#app",data() {return {}},methods: {cpnClcik(item) {console.log('cpnClick'+item.name);}},components: {cpn},})</script>

1.在子组件中定义一个方法btnClick(item),使用$emit,'itemclick’是事件名,item是传过去的值。

javascript">      methods: {btnClick(item) {this.$emit('itemclick', item)}},

2.在子组件中监听点击事件并回调此方法

<div><button v-for="(item, index) in categoties" :key="index" @click="btnClick(item)">{{item.name}}</button></div>

3.在父组件中定义一个方法cpnClcik(item)

javascript">methods: {cpnClcik(item) {console.log('cpnClick'+item.name);}
},

4.并在父组件(vue实例)中调用<cpn @itemclick="cpnClcik"></cpn>不写参数默认传递btnClick的item ),父组件监听事件名为itemclick的子组件传过来的事件。

<cpn @itemclick="cpnClcik"></cpn>

8.3 父子组件通信案例

​ 实现父子组件的值双向绑定。

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>组件通信-父子通信案例</title>
</head><body>
<!-- 父组件 -->
<div id="app"><h2>子组件</h2><cpn :number1='num1' :number2='num2'@num1change="num1Change"@num2change="num2Change"></cpn><h2>--------------</h2><h2>父组件{{num1}}</h2><input type="text" v-model="num1" ><h2>父组件{{num2}}</h2><input type="text" v-model="num2"></div><!-- 子组件 -->
<template id="cpn"><div><h2>number1:{{number1}}</h2><h2>dnumber1:{{dnumber1}}</h2><input type="text" :value="dnumber1" @input="num1input"><h2>number2:{{number2}}</h2><h2>dnumber2:{{dnumber2}}</h2><input type="text" :value="dnumber2" @input="num2input"></div>
</template><script src="../js/vue.js"></script><script>javascript">// 父传子:propsconst cpn = {template: "#cpn",data() {return {dnumber1:this.number1,dnumber2:this.number2}},props:{number1:[Number,String],number2:[Number,String],},methods: {num1input(event){this.dnumber1 = event.target.valuethis.$emit('num1change',this.dnumber1)},num2input(event){this.dnumber2 = event.target.valuethis.$emit('num2change',this.dnumber2)}},};const app = new Vue({el: "#app",data: {num1:1,num2:2},methods: {num1Change(value){this.num1=value},num2Change(value){this.num1=value}},components: {cpn},})
</script>
</body></html>

使用watch实现。

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>组件通信-父子通信案例(watch实现)</title>
</head><body><!-- 父组件 --><div id="app"><cpn :number1='num1' :number2='num2' @num1change="num1Change" @num2change="num2Change"></cpn><h2>父组件{{num1}}</h2><input type="text" v-model="num1" ><h2>父组件{{num2}}</h2><input type="text" v-model="num2"></div><!-- 子组件 --><template id="cpn"><div><h2>{{number1}}</h2><input type="text" v-model="dnumber1"><h2>{{number2}}</h2><input type="text" v-model="dnumber2"></div></template><script src="../js/vue.js"></script><script>javascript">// 父传子:propsconst cpn = {template: "#cpn",data() {return {dnumber1:this.number1,dnumber2:this.number2}},props:{number1:[Number,String],number2:[Number,String],},watch: {dnumber1(newValue){this.dnumber1 = newValue * 100this.$emit('num1change',newValue)},dnumber2(newValue){this.dnumber1 = newValue * 100this.$emit('num2change',newValue)}},};const app = new Vue({el: "#app",data() {return {num1:1,num2:2,}},methods: {num1Change(value){this.num1=value},num2Change(value){this.num1=value}},components: {cpn},})</script>
</body></html>

9. 父访问子(children-ref)

​ 父组件访问子组件,有时候需要直接操作子组件的方法,或是属性,此时需要用到$children$ref

  <!-- 父组件 --><div id="app"><cpn></cpn><cpn></cpn><cpn ref="aaa"></cpn><button @click="btnClick" >按钮</button></div><!-- 子组件 --><template id="cpn"><div>我是子组件</div></template><script src="../js/vue.js"></script><script>javascript">// 父传子:propsconst cpn = {template: "#cpn",data() {return {name:"我是子组件的name"}},methods: {showMessage(){console.log("showMessage");}},};const app = new Vue({el: "#app",data() {return {message:"hello"}},methods: {btnClick(){// 1.children// console.log(this.$children[0].showMessage)// for (let cpn of this.$children) {//   console.log(cpn.showMessage)// }// 2.$refconsole.log(this.$refs.aaa.name)}},components: {cpn},})</script>

$children方式

javascript">// 1.children
console.log(this.$children[0].showMessage)
for (let cpn of this.$children) {console.log(cpn.showMessage)
}

使用this.$children直接获取**当前实例的直接子组件,需要注意 $children 并不保证顺序,也不是响应式的。**如果你发现自己正在尝试使用 $children 来进行数据绑定,考虑使用一个数组配合 v-for 来生成子组件,并且使用 Array 作为真正的来源。

$refs方式

先定义子组件

<cpn ref="aaa"></cpn>

直接调用

Hi👋,这里是瑞雨溪一个喜欢JavaScript和Vue的大学生,如果我的文章给你带来的帮助,欢迎您关注我,我会持续不断的更新更多优质文章.你的关注就是我的动力!!!🎉🎉🎉


http://www.ppmy.cn/server/142891.html

相关文章

2024下半年自学黑客(网络安全)

CSDN大礼包&#xff1a;&#x1f449; 基于入门网络安全/黑客打造的&#xff1a;&#x1f449;黑客&网络安全入门&进阶学习资源包 前言 什么是网络安全 网络安全可以基于攻击和防御视角来分类&#xff0c;我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术&…

在Google Cloud Platform (GCP) 中用Pub/Sub+Dataflow+BigQuery构建数据处理仓库

在 Google Cloud Platform (GCP) 中&#xff0c;Pub/Sub、Dataflow 和 BigQuery 是构建数据处理和分析管道的强大工具。以下是它们的架构搭配及详细实现攻略。 架构概述 Pub/Sub&#xff1a;作为消息队列&#xff0c;Pub/Sub 用于接收和传输实时数据流。它能够处理高吞吐量的消…

AWTK-WIDGET-WEB-VIEW 实现笔记 (1) - 难点

webview 提供了一个跨平台的 webview 库&#xff0c;其接口简单&#xff0c;提供的例子也直观易懂。但是把它集成到 AWTK 里&#xff0c;还是遇到一些难题&#xff0c;这里记录一下&#xff0c;供有需要的朋友参考。 1. 作为 AWTK 控件 webview 提供的例子都是独立的程序&…

数据处理与统计分析——04-Pandas中Series的常用方法、属性、布尔索引、运算操作

Series 概述 Series也是Pandas中的最基本的数据结构对象&#xff0c;也是DataFrame的列对象或者行对象&#xff0c;series本身也具有行索引。Series是一种类似于一维数组的对象&#xff0c;由下面两个部分组成&#xff1a; values&#xff1a;一组数据&#xff08;numpy.ndar…

Http常⻅见请求/响应头content-type内容类型讲解(笔记)

常见的 Content-Type 媒体类型 text类型&#xff1a; text/html&#xff1a;HTML格式&#xff0c;常用于网页内容。text/plain&#xff1a;纯文本格式&#xff0c;未进行任何格式化。text/xml&#xff1a;XML格式&#xff0c;表示以 XML 格式传输的数据。 image类型&#xff08…

【Nginx】反向代理Https时相关参数:

在Nginx代理后台HTTPS服务时&#xff0c;有几个关键的参数需要配置&#xff0c;以确保代理服务器能够正确地与后端服务器进行通信。一些重要参数的介绍&#xff1a; proxy_ssl_server_name&#xff1a;这个参数用于指定是否在TLS握手时通过SNI&#xff08;Server Name Indicati…

Docker基础概念

Docker基础概念 文章目录 Docker基础概念前言一、docker结构二、容器的概念 前言 为什么要学习docker?docker是现在主流流行的容器化部署服务的技术栈之一。过去传统部署服务器的时候有这些缺点 1.各种中间件&#xff0c;数据库等部署麻烦&#xff0c;版本控制难度大 2.一个服…

go+powershell脚本实现预填写管理凭据安装软件

这里使用了powershell脚本进行操作&#xff0c;使用golang进行简单的封装,实现普通用户下安装软件 powershell命令解释 $securePassword ConvertTo-SecureString "yourpasswd" -AsPlainText -Force #转换密码为SecureString格式 $credential New-Object System.Ma…