首页 > 其他分享 >Vue笔记4--组件和插槽

Vue笔记4--组件和插槽

时间:2022-12-14 10:44:24浏览次数:46  
标签:Vue return -- 插槽 Content default vue 组件 message

1、组件基础

Vue的特点:组件开发。页面将为是一颗嵌套的组件树

src目录下有个components,组件都放在其中。组件首字母一般为大写。组件是带有名称可复用的实例。


1.1 vue2做法

1、在components下新建Content.vue的文件

2、在App.vue中引入,并且components注册,标准写法Content:Content,前为方便别名后为引入的组件。也可以直接简写如下

export default {
  data() {
    return {
    };
  },
  components:{
   Content//简写
  }
};

3、使用组件。ps.直接写<Content然后会跳出来选项自动补全代码。

  <div>
    <Content></Content>
  </div>

组件嵌套,在Content.vue中引入另一个组件

<template>
    <div>
        <h2>我是组件内容</h2>
        <Hello></Hello>
    </div>
</template>
<script>
import Hello from './Hello.vue'
export default{
    components:{
        Hello
    }
}
</script>

组件复用

父组件和子组件,在上面的例子中App.vue是根组件,Content.vue是Hello.vue的父组件,组件是单独功能模块的封装。

组件数据存放

父子组件并不可以随意的获取对方的数据,需要使用对应的方法。并且连续使用三个同样的组件,修改其中某一组件的data(),另外两个组件是独立的不受影响的。

data()是一个函数,每一次执行完都是返回一个新的对象

    data(){
        return{msg:"helloworld"} 
    },

除非定义const,让三个组件用的同一个obj。但这是不推荐的,会造成数据的污染。

const obj={
    msg:"helloworld"
}
export default{
    data(){
        return obj
    },
    components:{
        Hello
    }
}

1.2 父传子Prop

Prop是可以在组件上注册的一些自定义的属性

Content.vue中

    data(){
        return{
            msg:"helloworld"
        } 
    },
<Hello :message='msg' aaa="123"></Hello>

Hello.vue中

export default{
    props:['message','aaa'],
}
    <div>
        <h2>--{{message}}--{{aaa}}</h2>
    </div>

以数组的形式传递数据过去,其中message是动态而且绑定的,aaa静态,两个都可以传

Prop常用法

不以数组而是对象的形式

1 限制类型,可以限制传递过来数据的格式,可多种

    props:{
        message:String
        //message:[String,Number]
    }

2 设置默认值default

3 设置必传值required

    props:{
        message:{
            type:String,
            default:"你好",
            required:true,
        }
    }

对于默认值对象和数组的默认值必须从一个工厂返回

    props:{
        ···
        list:{
            type:Array,
            //default:[],错误写法
            default(){
                return []
            },
        }
    }

单项数据流

prop让父子之间相乘一个单向下行绑定,父更新会流动到子中,反过来却不行。

1.3 子传父$emit监听

在App.vue中监听Content.vue子组件数据,通过自定义事件

1、在子组件Content.vue中通过$emit来触发事件

this.$emit(' 自定义事件的名称 ',' 发送的事件参数 ')

    methods:{
        sendParent:function(){
            this.$emit('injectMsg',this.msg)
        }
    },
<button @click="sendParent">提交数据给父组件</button>

2、在父组件App.vue中,通过v-on监听子组件的自定义事件

通过@绑定了在子组件里写的injectMsg事件,点击按钮事件触发,进而运行getChildMsg方法。

<Content @injectMsg="getChildMsg"></Content>
  methods:{
    getChildMsg:function(value){
      console.log(value);
    }
  },

3、在父组件App.vue中,存储获得数据

默认参数value就是传过来的数据

  data() {
    return {
      message: ""
    };
  },
  methods: {
    getChildMsg: function (value) {
      this.message = value;
    }
  },

1.4 父访问子 $refs

父组件访问子组件,$refs和$children。vue3已经废弃$children,他有缺陷因为传递的是数组类型。

$refs需要搭配一个ref指令来使用,ref:用来给元素或者子组件注册引用信息,开发中经常用到,给子组件绑定自己的起的id名。

在子组件Content.vue中

<Hello :message='msg' aaa="123" :list="list" ref="hello"></Hello>
<p ref="p"></p>
export default {
    ···
    mounted(){//生命周期函数
        console.log(this.$refs);
        console.log(this.$refs.hello.aaa);
    },
    ···
}

通过控制台即可看到访问成功,通过$refs.hello.aaa即可拿到其中的内容,又或者$refs.p.id拿到p标签的属性。

1.5 子访问父$parent

但是在实际开发中不推荐使用this.$parent.*去获取父组件。因为组件复用性很高,会像吕布一样分不清是哪个爸爸。

更推荐使用props传值,需要就从父传过来不需要就不传。

export default {
    ···
    mounted(){//生命周期函数
        console.log(this.$parent);
    },
    ···
}

1.6 子访问根$root

更常用

export default {
    ···
    mounted(){//生命周期函数
        console.log(this.$root);
    },
    ···
}

2、插槽

2.1 基本使用

在移动端开发中用的较多。以导航栏举例:大多数移动应用导航栏都是左返回;中页面名称;右三点展开更多。

这时候就可以把左中右看成三个坑(插槽),由父组件来决定我需要填进什么萝卜。

Content.vue中通过Vue自定<slot>作为一个插入内容的占位符。

        <div>
            <slot></slot>
        </div>

在父组件中引用后使用它

    <Content><button>按钮</button></Content>
    <Content><input type="text"/></Content>

Content.vue中,如果父组件没有提供内容的时候默认展示备用内容

<slot name="button"><button>默认按钮</button></slot>

2.2 具名插槽

如果有多个值,同时放入组件进行替换式,一起作为替换元素。当子组件功能复杂,需要具体插槽具体对待。vue3和vue2区别

            <slot name="button"></slot>
            <slot name="input"></slot>
            <slot name="h2"></slot>

vue3做法

template元素上使用v-slot指令

<Content>
    <template v-slot:button><button>按钮</button></template>
    <template v-slot:input><input type="text"/></template>
    <template v-slot:h2><h2>插槽</h2></template>
</Content>

vue2做法

<button slot="button">按钮</button>

2.3 作用域插槽

App.vueContent.vue中data都存在massage的数据,这种方式将会显示App中的massage。

类似局部变量,父模板中所有内容都是在父级作用域中编制的,这个massage拿不到子的数据。

<template v-slot:button>
    <button>按钮{{ massage }}</button>
</template>

作用于插槽是父组件替换插槽的标签,但是数据由子组件提供。vue3和vue2区别

vue3做法

Content.vue中绑定在slot上的属性值被成为插槽prop

export default {
    data() {
        return {
            message: '你好',
            list: [1, 2, 3, 5, 6],
        }
    }
}
<slot :list="list" :msg="message"></slot>

App.vue中使用带值的v-slot定义插槽名字,就会得到传过来的{ "list": [ 1, 2, 3, 5, 6 ], "msg": "你好" }的数据。

这里用过插槽prop的对象命名为slotProps,可以随便取

    <Content>
      <template v-slot:default="slotProps">
        {{ slotProps }}
      </template>
    </Content>

通过.list.msg拿到数据。(但实际上推荐Content.vue中:message="message",msg只是为了区分传过来的是等号前的自定义名字)

展示无序列表

    <Content>
      <template v-slot:default="slotProps">
        <ul>
          <li v-for="item in slotProps.list" :key="item">{{ item }}</li>
        </ul>
      </template>
    </Content>

展示有序列表

<ol>
    <li v-for="item in slotProps.list" :key="item">{{ item }}</li>
</ol>

3、组件跨级通信

3.1 Provide / Inject

祖先组件和孙子组件跨级通信,实际中一级级传递数据不现实。不论层次结构,父组件provide提供数据,子组件inject使用数据。(此处源码演示到了day2)

HelloWorld.vue祖先组件、Content.vue父组件、Hello.vue子组件。从Hello.vueHelloWorld.vue数据

HelloWorld.vue中provide以key-value的形式传字符串

export default{
  data(){
    return{
      massage:'HelloWorld'
    }
  },
  provide:{
    message:'HelloWorld'
  },
  ···
}

Hello.vue中inject

export default {
    data() {
        return {};
    },
    inject: ['message'] 
}
<h2>我是Hello组件</h2>
<h2>{{ message }}</h2>

其中需要注意HelloWorld.vue中,这种写法报错

  provide:{
    message:this.message
  },

如果想要访问组件实例的属性需要以函数的形式

  provide(){
    return{
      massage:this.massage
    }
  },

3.2 与prop区别

1、不会像prop父组件数据改变子组件也变,Provide / Inject不是响应式。在非组合式API下,传响应式对象or函数形式

传响应式对象

HelloWorld.vue

  data() {
    return {
      obj:{message: 'HelloWorld',}
    }
  },
  provide() {
    return {obj:this.obj}
  },

Hello.vue

export default {
    ···
    inject: ["obj"] 
}
<h2>{{ obj.message }}</h2>

函数形式

HelloWorld.vue

  data() {
    return {message: 'HelloWorld',}
  },
  provide() {
    return {//箭头函数返回响应式数据
      message: () => this.message
    }
  },

Hello.vue

export default {
    ···
    inject: ["message"] 
}
<h2>{{ message() }}</h2>

此处为了方便将函数直接卸载{{}}中,这是不推荐的。应该使用computed属性

标签:Vue,return,--,插槽,Content,default,vue,组件,message
From: https://www.cnblogs.com/TimothyWen/p/16981458.html

相关文章

  • 编译原理基础知识02
    1、文法:用来描述表达式的规则2、上下文无关文法(四个要素组成)①一个终结符号集(或者叫词法单元)②一个非终结符号集(或者叫语法变量)③一个产生式集合:就是由非终结符到终结......
  • CSS
    第一个CSS程序index.html<head><metacharset="UTF-8"><title>Title</title><linkrel="stylesheet"href="css/style.css"></head><body><h1>ti......
  • UrlEncode 会把对象的大写转成小写
      Dictionary<string,object>pairs=newDictionary<string,object>(){{"bookId",2},{"virtualQuantity","10"}};varjson=Newtonsoft.Json.Js......
  • 查找算法
    9.1静态查找表仅作查询和检索操作使用 关键字数据元素中某个数据项的值,用以标识一个数据元素。若用此关键字可以识别唯一的一个数据元素,则称之为“主关键字”。若用......
  • Eureka的自我保护模式
    默认情况下,如果EurekaServer在90s内没有接收到某个微服务的心跳,EurekaServer将会移除该微服务。但是当发生网络故障时,微服务与EurekaServer之间无法正常通信,而微服务本......
  • ubuntu安装vmware tools不起作用
    安装VMwaretools之后从windows复制文件到ubuntu发现没有成功重新执行vmware-uninstall-tools.pl脚本提示之前已经安装了版本,需要卸载重装解决方案:1)不需要卸载2)命令行......
  • 实施 GitOps 的三个关键步骤
    GitOps是一种自动化和管理基础架构和应用程序的模型,通过许多团队已经使用的相同DevOps最佳实践来形成的模型,例如版本控制、代码审查和CI/CD流水线。在实施DevOps时,......
  • 搞清webpack、vite、vue-cli、create-vue的区别
    1.要区分脚手架、构建项目、打包代码的概念1.1脚手架:创建项目,选择性安装需要的插件,指定统一的风格,生成demo。(vue-cli和create-vue是由vue提供的脚手架,创建项目时......
  • 排序算法
    10.1内部排序与外部排序内部排序:待排序的所有记录全部存放在计算机内存中,整个排序过程不需要访问外存外部排序:等待排序的记录数量很大,以至于整个序列的排序过程不可能在......
  • linux中安装mysql
    1.安装Linux系统中自带的MySQL安装包在现在常用的发行版本里都集中了MySQL安装包CentOS系统中的YUM中包含了MySQL安装包,版本是MySQL5,rpm软件包的名称是mysql-server......