Vue3基础知识(三)jsconfig.json配置文件,以及组件通信,插槽Slot

2,255 阅读4分钟

一.jsconfig.json文件

1.1. jsconfig.json文件的作用

作用:给vsocde来进行读取,VsCode在读取到其中的内容时,给我们的代码更有好的提示。

vue.config.js配置别名

const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({//defineConfig定义配置文件
  transpileDependencies: true,
  // 配置webpack
configureWebpack:{
resolve:{
  // 配置路径别名
  // @已经配置好的路径别名,对应src的路径
  alias:{
    "utils":"@/utils"
  }
}
}
})

jsconnfig.json 例如:让vscode识别utils,从而有更友好的代码提示。

{
  "compilerOptions": {
    "target": "es5",//目标打包成es5的代码
    "module": "esnext",//使用模块化的时候,使用es的模块化
    "baseUrl": "./",//决定路径的src相当于当前目录
    "moduleResolution": "node",//模块的查找顺序按照node的顺序进行查找
    "paths": {
      "@/*": [
        "src/*"
      ],
      //配置utils
     " utils/*":[
      "src/utils/*"
     ]
    },
    "lib": [//可能会用的库
      "esnext",
      "dom",
      "dom.iterable",//使用可迭代对象有更有好的方法提示
      "scripthost"//提供更友好的数组环境
    ]
  }
}

1.2. vue不同版本的作用

  • 默认Vue版本 runtime: 运行时,vue-loader完成template的编译过程。
  • vue.esm-bundler: runtime + compile: 运行+编译,d对template进行编译。
    tempalte模板-->createVNode()(v3:createElementBlock())-->VNnode-->虚拟dom-->真实DOM

1.3. css的scoped作用域

scoped属性让CSS只对当前组件中的元素起作用,防止了CSS全局污染。 设置scoped作用域,相当于添加了一个属性:"data-v-7ba5bd90"

1.4. npm init vue@latest创建项目

  • 执行命令会首先安装一个本地工具:create-vue
  • 使用create-vue创建一个vue项目
  • 底层基于vite打包
Need to install the following packages:
  create-vue@3.6.1
Ok to proceed? (y) y

Vue.js - The Progressive JavaScript FrameworkProject name: ... 03-project-vite
√ Add TypeScript? ... No / YesAdd JSX Support? ... No / YesAdd Vue Router for Single Page Application development? ... No / YesAdd Pinia for state management? ... No / YesAdd Vitest for Unit Testing? ... No / YesAdd an End-to-End Testing Solution? » NoAdd ESLint for code quality? ... No / Yes

二. 组件间的通信

2.1. 组件的嵌套关系

  • 父组件/子组件
  • 父组件传递给子组件:通过props属性;
  • 子组件传递给父组件:通过$emit触发事件;

2.2. 父传子 - props(重要)

1.什么是Props呢?

  • Props是你可以在组件上注册一些自定义的attribute;
  • 父组件给这些attribute赋值,子组件通过attribute的名称获取到对应的值;

2.Props有两种常见的用法:

  • 方式一:字符串数组,数组中的字符串就是attribute的名称;
  • 数组语法的弊端:1.不能对类型进行验证。2.没有默认值
 父组件: <show-info name="www" age="18" height="1.8"> </show-info>
子组件中: props: ["name", "age", "height"]
  • 方式二:对象类型,对象类型我们可以在指定attribute名称的同时,指定它需要传递的类型、是否是必须的、默认值等等;
  • 那么type的类型都可以是哪些呢?
  1. String
  2. Number
  3. Boolean
  4. Array
  5. Object
  6. Date
  7. Function
  8. Symbol
  // 对象语法
  父组件: <show-info name="www" age="18" height="1.8"> </show-info>
 //需要加  " :"age="39",使其变成js代码,里面的30就变成一个数字
        <show-info name="kobe" :age="39" :height="1.99"> </show-info>
        <show-info></show-info>
  
  子组件:  props: {
        name: {
            type: String,
            default: "我是默认的name"
        },
        age: {
            type: Number,
            default: "12"
        },
        height: {
            type: Number,
            default: 0,
        },
    }

父组件:

<template>
    <div class="app">
        <!-- 1.展示why信息 -->
        <show-info name="www" age="18" height="1.8"> </show-info>
        <show-info name="kobe" age="39" height="1.99"> </show-info>

    </div>
</template>
<script>
import ShowInfo from "./ShowInfo.vue"
export default {
    components: {
        ShowInfo
    }
}
</script>
<style scoped></style>

子组件:

<template>
    <div class="showinfo">
        <div class="info">
            <h2>性别:{{ name }}</h2>
            <h2>年龄:{{ age }}</h2>
            <h2>身高:{{ height }}</h2>
        </div>
    </div>
</template>
<script>
export default {
    // 作用接收父组件传递过来的属性
    //数组语法
    props: ["name", "age", "height"]
}
</script>
<style scoped></style>

3.对象类型的其他写法 image.png

2.3. 非prop的attribute

1.什么是非Prop的Attribute呢?

  • 当我们传递给一个组件某个属性,但是该属性并没有定义对应的props或者emits时,就称之为 非Prop的Attribute;
  • 常见的包括class、style、id属性等;
  1. Attribute继承
  • 当组件有单个根节点时,非Prop的Attribute将自动添加到根节点的Attribute中:

image.png

2.4. 子传父 - $emit(重要)

1.什么情况下子组件需要传递内容到父组件呢?

  • 当子组件有一些事件发生的时候,比如在组件中发生了点击,父组件需要切换内容;
  • 子组件有一些内容想要传递给父组件的时候;
  1. 我们如何完成上面的操作呢?
  • 首先,我们需要在子组件中定义好在某些情况下触发的事件名称;
  • 其次,在父组件中以v-on的方式传入要监听的事件名称,并且绑定到对应的方法中;
  • 最后,在子组件中发生某个事件的时候,根据事件名称触发对应的事件;

3.我们封装一个AddCounter.vue的组件:

  • 内部其实是监听两个按钮的点击,点击之后通过 this.$emit的方式发出去事件;

子组件

<template>
    <div class="add">
        <button @click="btnClick(1)">+1</button>
        <button @click="btnClick(5)">+5</button>
        <button @click="btnClick(10)">+10</button>
    </div>
</template>
<script>
export default {
    methods: {
        btnClick(count) {
            console.log("click");
            // 让子组件发出自定义事件, 
            // 第一个参数add名字可以自定义。
            // 第二个参数是传递的参数
            this.$emit("add",count)
        }
    }
}
</script>
<style scoped></style>

父组件

<template>
    <div class="app">
        <h2>当前计数:{{ counter }}</h2>
        <!-- v-on:  (@) 监听组件内部的事件 -->
        <!--1. 自定义,add-counter,并且监听内部事件 -->
        <add-counter v-on:add="addBtnClick"></add-counter>
        <sub-counter></sub-counter>
    </div>
</template>
<script>
import AddCounter from './AddCounter.vue'
import SubCounter from './SubCounter.vue'
export default {
    data() {
        return {
            counter: 0,
        }
    },
    components: {
        AddCounter,
        SubCounter
    },
    methods: {
        addBtnClick(count) {
            this.counter += count
        }
    }
}
</script>
<style scoped></style>

三. 组件的插槽Slot

3.1. 认识Slot的作用

1.来定义插槽slot

  • 插槽的使用过程其实是抽取共性、预留不同;
  • 我们会将共同的元素、内容依然在组件内进行封装;
  • 同时会将不同的元素使用slot作为占位,让外部决定到底显示什么样的元素;

2.如何使用slot呢?

  • Vue中将 元素作为承载分发内容的出口;
  • 在封装组件中,使用特殊的元素就可以为封装组件开启一个插槽;
  • 该插槽插入什么内容取决于父组件如何使用;

3.2. Slot的基本使用和默认值(重要)

1.子组件

<template>
    <div>
        <h2> show-message</h2>
        <slot>
            <h2>我是默认的内容</h2>
        </slot>
    </div>
</template>

2.父组件

<template>
    <div class="app">
        <div class="content">
            <show-message>
                <button>使用插槽</button>
            </show-message>
        </div>
    </div>
</template>

3.3. Slot的具名插槽(重要)

1.具名插槽使用的时候缩写:

  • 跟 v-on 和 v-bind 一样,v-slot 也有缩写;
  • 即把参数之前的所有内容 (v-slot:) 替换为字符 #; 默认情况:
<nav-bar>
            <template v-slot:left>
                <button>返回</button>
            </template>
            <template #center>
                <button>内容</button>
            </template>
            <template #right>
                <button>登录</button>
            </template>
        </nav-bar>

image.png 1.子组件

<div class="nav-bar">
        <div class="left">
            <slot name="left">left</slot>
        </div>
        <div class="center">
            <slot name="center">center</slot>
        </div>
        <div class="right">
            <slot name="right">right</slot>
        </div>
    </div>

2.父组件中

<template>
    <div class="app">
        <nav-bar>
        //在template中写上对应的名字
            <template v-slot:left>
                <button>返回</button>
            </template>
            <template v-slot:center>
                <button>内容</button>
            </template>
            <template v-slot:right>
                <button>登录</button>
            </template>
        </nav-bar>
    </div>
</template>

使用插槽后

image.png

3.4. 动态插槽名

1.什么是动态插槽名呢?

  • 目前我们使用的插槽名称都是固定的; 比如 v-slot:left、v-slot:center等等;
  • 我们可以通过 v-slot:[dynamicSlotName]方式动态绑定一个名称
   <nav-bar>
     <!--  v-slot:[]动态插槽,引入变量 -->
            <template v-slot:[position]>
                <a href="">注册</a>
            </template>
        </nav-bar>
        <button @click="position = 'left'">按钮</button>
        <button @click="position = 'center'">按钮</button>
        <button @click="position = 'right'">按钮</button>
        
        
    data() {
        return {
            position: "center",
        }
    },

3.5. Vue编译作用域

1.渲染作用域

在Vue中有渲染作用域的概念:

  • 父级模板里的所有内容都是在父级作用域中编译的;
  • 子模板里的所有内容都是在子作用域中编译的;

3.6. 作用域插槽使用

  • 核心: 将子组件中的数据传递给父组件的插槽来使用

image.png