Vue基础-day03

156 阅读7分钟

Vue基础-day03

今天是Vue基础的第3天

复习前天内容

  • v-bind绑定类名时传数组

    v-bind:class="[c1, c2, c3]"
    
    • c1,c2,c3分别是变量,变量值是什么就代表它有什么类
    v-bind:class="[c1,c2,'xx']"
    
    • c1,c2分别是变量,变量值是什么就代表它有什么类,并且有一个固定的xx类
    v-bind:class=[c1, {'类名': 布尔值}]
    
    • c1是变量,它是值就有什么类,当布尔值为true就有这个类名
  • 侦听器

    • 简约写法

      watch: {
          
          要侦听的数据 (修改后,修改前) {
              
          }
      }
      
      • 细节:数组那些能改变自身的方法:push、pop、unshift、shift、splice、sort、reverse这些方法可以侦听到,但是concat、通过下标改值,侦听不到
      • 对象的属性改变也侦听不到
    • 完整写法

      • 主要是为了解决侦听对象内任意属性改变都要侦听到(深度侦听)
      watch: {
          
          对象: {
              // 开启深度侦听
              deep: true,
              handler () {
                  // 当有改变调用的函数
              },
              // 当前页面一打开就默认调用handler
              immediate: true
          }
      }
      
  • 组件化开发

    • 以后可以把项目中一个大、小界面都称之为组件
      • 因为属于组成网页的一部分所以就称之为组件
    • 既然组件本质是界面,所以一定有
      • html结构
      • css样式
      • js逻辑
    • 所以我们以后写vue项目,用.vue文件作为组件
  • vue-cli

    • 俗称脚手架

    • 相当于就是类似webpack的打包工具,但是不需要做太多复杂的配置,开箱即用

    • 脚手架只是一个全局包,所以只要装一次

      npm i -g @vue/cli
      
    • 如何创建项目

      vue create 项目名
      
    • 默认入口文件是?

      • src/main.js
      • 所以全局东西要写到main.js
    • 项目启动的第一个组件是?

      • App.vue
      • 也称之为主组件
    • components文件夹

      • 放组件的
    • assets文件夹

      • 放静态资源:图片、字体
    • 脚手架的配置文件叫?

      • vue.config.js
  • ESLint

    • 是一种语法规范的检查工具,能让不符合规范的代码报错

    • 学习时可以先关掉

      • vue.config.js加一条配置

        lintOnSave: false
        
  • 我们以后除了App.vue会自己再写组件,但默认写好的组件看不到

  • 要想看到要导入并注册再使用

    • 局部

      // 导入
      import 组件名 from '组件路径'
      
      // 注册
      export default {
          components: {
              组件名
              // 完整写法是
              使用的名字: 组件名
          }
      }
      
      <组件名 />
      
      • 如果组件名是驼峰的,可以拆成小写,每个单词用-连接
      <单词1-单词2 />
      
      • 在哪导入就只能在哪用
    • 全局

      • 导入一次,哪里都能用
      // 导入
      import 组件名 from '组件路径'
      // 注册
      Vue.component('使用的名字', 刚刚导入的组件名)
      
      
      <使用的名字 />
      
  • 组件名规范:

    • 开发建议大驼峰,至少两个单词
      • 使用标签时,不要用大驼峰,而是用小写带-
    • 例:
      • 组件名叫 DemoLogin
      • 但是使用时建议用 <demo-login />
  • 组件关系

    • 父子关系:
      • 包含与被包含的关系
      • 包含别人的叫父组件,被包含的叫子
    • 兄弟关系:
      • 平级关系

作业

昨天的作业不需要逻辑,只需要使用提供好的组件拼接成界面即可

  • 首先建立项目

    vue create 项目名
    
  • 先关掉ESLint,来到 vue.config.js加一条规则

    lintOnSave: false
    
  • App.vue代码如下---原生实现

      <div id="app">
        <BaseBox style="width: 480px">
          <!-- 标题部分 -->
          <div class="title">
            <h2>记事本</h2>
            <input type="text" />
          </div>
          <ul>
            <li>
              <div class="content"><span>1.</span> 西瓜</div>
              <button></button>
            </li>
          </ul>
          <!-- 底部 -->
          <div class="bottom">
            <span>合计:0</span>
            <button>🗑️</button>
          </div>
        </BaseBox>
      </div>
    
  • App.vue代码如下 --- 改成组件实现

    • 就是把原生标签换成组件
      <div id="app">
        <BaseBox style="width: 480px">
          <!-- 标题部分 -->
          <base-title></base-title>
          <!-- 输入框 -->
          <base-input />
    
          <ul>
            <li>
              <div class="content"><span>1.</span> 西瓜</div>
              <base-button>❌</base-button>
            </li>
          </ul>
          <!-- 底部 -->
          <div class="bottom">
            <span>合计:0</span>
            <base-button>🗑️</base-button>
          </div>
        </BaseBox>
      </div>
    

讲插槽之前的总结

  • 我们发现给组件写内容,默认不会改变组件显示的内容

    • 例如
     <base-title>囧事本</base-title>
    
  • 我们发现给组件加原生dom有的那些事件,默认也无法添加成功

    <base-button @click="del"></base-button>
    
  • 原因:组件本质上并不是原生dom,但是它可以实现上面的2个功能,这就需要需要今天的知识:插槽(slot)、$emit

slot-基本使用

  • 组件什么时候用插槽?

    • 我封装了一个组件,但是这个组件有个区域的内容我不想写死,那就可以写插槽(slot)
  • 语法

    • 在不想写死的地方,写一个 slot

      <slot />
      
      • 这种写法代表没有默认值,外界不传,这里就没有
    • 有默认值的写法

      <slot>默认值</slot>
      

03-子默认不能传给父的报错.png

  • 外界传递的语法

    <组件>传递的内容</组件>
    

BaseTitle组件

结合刚刚学习插槽部分的知识点,咱们来完成昨天作业中的的BaseTitle标题组件

  • 最后改良这个组件,因为这个组件之前写死了,名字只能叫记事本

  • 为了不写死,所以使用插槽

      <h2 class="base-title">
        <!-- 挖了一个坑(专业叫法:插槽) -->
        <!-- 如果光这么写,代表没有默认值 -->
        <!-- 就意味着外面没传,这里没有显示 -->
        <!-- <slot /> -->
    
        <!-- 你传什么,这里就显示什么 -->
        <!-- 但是如果你没传,就显示记事本 -->
        <slot>记事本</slot>
      </h2>
    </template>
    

slot-具名插槽

需求:BaseBox组件我有两个地方不想写死,怎么办?

  • 什么叫具名插槽

    • 就是具有名字的插槽
  • 为什么要用具名插槽?

    • 因为我一个组件里可能多个地方都不想写死,那就使用具名插槽
  • 语法

    <slot name="名字">默认值</slot>
    
  • 如何给具名插槽传递?要依赖 template包裹,并且用 v-slot:来指定插槽名字

    <template v-slot:插槽名>
      要传递的内容
    </template>
    
  • 简写就是把 v-slot: 变成 #

    <template #插槽名>
      要传递的内容
    </template>
    
  • 以上语法是vue2.6以后推出的语法,也是官方推荐语法

  • 在vue2.6以前,有其他语法,但是目前已经废弃了(Vue3.0里已经明确不能用了)

  • vue2.6以前废弃语法(只要求会认,不要求以后拿来写

    <template slot="插槽名字">
       要传递的内容
    </template>
    
    <!-- 如果只有一个要传,也可以直接写标签 -->
    <标签 slot="插槽名字">内容</标签>
    
  • 默认插槽其实也有名字,只不过名字叫 default

  • 小结

    • 如果是新语法,不管传一个还是传多个,都要用 template包裹
    • 新语法:
      • v-slot:插槽名字指定插槽,简写为: #插槽名字
    • 旧语法
      • slot="插槽名字" 指定插槽

BaseBox组件

接下来咱们基于刚刚学习的具名插槽来完成BaseBox组件

  • BaseBox需要标题部分不写死,又希望main这一部分也不写死,所以有两个插槽,为了区分,所以要用具名插槽

      <div class="base-box">
        <div class="top">
          <!-- 这里有一个具名插槽 -->
          <slot name="title">标题</slot>
        </div>
        <div class="main">
          <!-- 这里有一个默认插槽 -->
          <slot />
        </div>
      </div>
    
  • 传递部分

        <BaseBox style="width: 480px">
            
           <!-- 传递给具名插槽 -->
          <template #title>
            <!-- 标题部分 -->
            <base-title>黑马本</base-title>
            <!-- 输入框 -->
            <base-input />
          </template>
    
          <!-- 即使是默认插槽,最好也包一个template -->
          <template>
            <ul>
              <li>
                <div class="content"><span>1.</span> 西瓜</div>
                <base-button @click="del"></base-button>
              </li>
            </ul>
            <!-- 底部 -->
            <div class="bottom">
              <span>合计:0</span>
              <base-button>🗑️</base-button>
            </div>
          </template>
        </BaseBox>
    

props - 基本使用

通过props定义外部可以传递进来的数据

传送门:通过prop向子组件传递数据

子组件模板

<template>
  <div class="props-container">
      <h1>我叫:jack</h1>
      <h2>我今年:18岁</h2>
      <h3>我是:男孩子</h3>
      <h4>我喜欢的食物是:</h4>
    <ul>
      <li>西兰花</li>
      <li>花菜</li>
      <li>西红柿</li>
    </ul>
  </div>
</template>

<script>
export default {
    name:'PropsCom'
}
</script>

<style >
.props-container {
  border: 1px solid orange;
  width: 300px;
  background-color: yellowgreen;
  padding: 10px;
}
h1,
h2,
h3,
h4 {
  margin: 0;
}
</style>
  • props是用来实现:父传子

  • 步骤:

    1. 子里使用 props 来声明需要传递哪些数据

      • props跟data这些平级
      • props里声明的数据可以像data中的数据一样使用
      props: ['数据名1', '数据名2', '数据名3']
      // 例
      props: ['name', 'age', 'sex', 'foods'],
      
    2. 父传递的语法

      <子组件 :数据名="数据"/>
      <!-- 例子 -->
          <!-- 学习父子通信的组件 -->
          <!-- 父给子传写 :参数名="数据" -->
          <!-- 
            :name="obj.name"
              把父组件里的obj里的name,传递给子组件里的name
           -->
          <my-son :name="obj.name" :age="obj.age" :sex="'男'" :foods="['话梅','酸梅','溜溜梅','青梅']"/>
      
      

props-使用进阶

通过数组的方式定义prop,基本功能上并没有问题,如果要设置类型限制,设置默认值。。可搞不定咯,所以开发中更为推荐的是如下的写法

传送门:props定义

传送门:props验证

  • 官方不推荐,props传数组,推荐传对象

  • 以下是官方对于对象的说明

     props: {
        // 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证)
        propA: Number,
        // 多个可能的类型
        propB: [String, Number],
        // 必填的字符串
        propC: {
          type: String,
          required: true
        },
        // 带有默认值的数字
        propD: {
          type: Number,
          default: 100
        },
        // 带有默认值的对象
        propE: {
          type: Object,
          // 对象或数组默认值必须从一个工厂函数获取
          default: function () {
            return { message: 'hello' }
          }
        },
        // 自定义验证函数
        propF: {
          validator: function (value) {
            // 这个值必须匹配下列字符串中的一个
            return ['success', 'warning', 'danger'].indexOf(value) !== -1
          }
        }
      }
    
  • 小结:

    • 用什么属性限制要传递的类型?
      • type
    • 用什么属性限制必传
      • requiredtrue
    • 用什么设置默认值?
      • default,基本类型直接给,复杂类型要用函数来返回
    • 用什么设置自定义校验规则
      • validator
        • 它是一个函数,函数有一个参数,参数就是传递过来的值
        • 如果函数里return true代表校验通过,为false校验失败

props-单向数据流

父组件中数据的改变会传递给子组件,但是反过来却不行

传送门:单向数据流

  • 概念

    • 父组件的数据改变了会自动流入到子组件,但是子 不允许修改由props流过来的数据
  • 如图

03-子默认不能传给父的报错.png

  • 所谓单向数据流不允许子修改,是不允许改,但是可以改

    • 例如:父传了数组给子,在子里面可以通过调用push、pop、shift、unshift、splice等等方法来改堆,而且改完后父也会跟着改,因为他们指向的是同一个堆

    • 但是在子里不允许改props栈上的数据,父可以改,而且改完后能流入到子

  • 小结

    • 父的一个数据传递给了子,在父里如果把这个数据改了,请问会影响子吗?
    • 子里是否允许修改props里流入的数据
      • 不允许
    • 子里能否使用push方法让父的数组多一个元素
      • 可以
    • 子里能否把父传递过来的对象的属性值给改了?
      • 可以

emit-基本使用

如何在子组件中给父组件传递信息呢?可以通过$emit来实现哦

传送门:监听子组件的事件

传送门:使用只组件抛出一个值

  • 子里要如何给父传递数据?

    • 利用通知的形式来间接传数据

    • 发通知的语法

      this.$emit('自定义的事件名', 数据)
      
    • 父里要订阅这个通知(相当于就是监听这个事件)

      <子组件 @自定义的事件名="函数"/>
      
    • 当子的$emit执行时,就会自动调用父里绑定的 函数,函数的参数就是子传递过来的数据

    • 子里的代码

      <button @click="$emit('youya', '永不过时')">点击后-要给父传递数据</button>
      
      • 解释:当子里面点了这个按钮,就会发一个叫 youya的事件,那么父里如果监听了youya就会调用
    • 父里的代码

      <子组件 @youya="函数"/>
      
      • 当youya通知时,就会自动调用上面的函数,函数的参数就是子里传递过来的 永不过时
  • 小结:

    • $emit相当于通知一个事件,父里要不要监听才能触发
      • @事件名
    • $emit一定要传值吗?
      • 不一定要传
    • 如果要传值,父里如何接这个值?
      • 绑定的函数的参数,就是这个值

BaseButton组件

接下来咱们来完成BaseButton组件

  • 父里默认情况下对着封装的组件的,加 click无效

    <base-button  @click="del"></base-button>
    
    • 因为这并不是原生的标签,而是一个组件,而组件希望能够被 @事件名 的语法触发一些事件

    • 就必须要在内部用 $emit('事件名') 写这个事件名才能触发

  • 所以,来到 BaseButton这个组件内部,给按钮加一个点击事件,点击事件就通知父组件的事件触发

    <button @click="$emit('click')" class="base-button" type="button">
    

emit结合props

接下来咱们把propsemit结合起来使用

  • 因为子里通过$emit可以给父传递数据,那么当父的数据一旦发生改变,通过props又能流入到子

410abfc8-6e2f-4ae1-909c-1bf5b9461e10.png

  • 小结
    • 子不能直接修改父的props数据
    • 但是子可以通过 $emit 通知父组件,让父组件改掉props的值,就相当于改了

BaseInputNum组件

咱们通过计数器案例,来巩固propsemit的应用

  • 把第一天写的计数器抽取到一个.vue文件,这个.vue文件名叫 BaseInputNum

  • 最终代码如下

    <template>
      <div class="my-input-number">
        <!-- 递减 -->
        <span
          @click="sub"
          role="button"
          class="my-input-number__decrease"
          :class="{ 'is-disabled': num == 0 }"
        >
          -
        </span>
        <!-- 累加 -->
        <span
          @click="add"
          role="button"
          class="my-input-number__increase"
          :class="{ 'is-disabled': num == 10 }"
        >
          +
        </span>
        <div class="my-input">
          <!-- 数字显示区域 -->
          <span class="my-input__inner">{{ num }}</span>
        </div>
      </div>
    </template>
    
    <script>
    export default {
      data() {
        return {
          num: 0,
        };
      },
      methods: {
        // +号的点击事件
        add() {
          // 小于10才允许++
          if (this.num < 10) {
            this.num++;
          }
        },
    
        // -号的点击事件
        sub() {
          // 大于0才允许--
          if (this.num > 0) {
            this.num--;
          }
        },
      },
    };
    </script>
    
    <style>
    .my-input-number {
      position: relative;
      display: inline-block;
      width: 180px;
      line-height: 38px;
    }
    .my-input-number span {
      -moz-user-select: none;
      -webkit-user-select: none;
      -ms-user-select: none;
    }
    .my-input-number .my-input {
      display: block;
      position: relative;
      font-size: 14px;
      width: 100%;
    }
    .my-input-number .my-input__inner {
      -webkit-appearance: none;
      background-color: #fff;
      background-image: none;
      border-radius: 4px;
      border: 1px solid #dcdfe6;
      box-sizing: border-box;
      color: #606266;
      display: inline-block;
      font-size: inherit;
      height: 40px;
      line-height: 40px;
      outline: none;
      padding: 0 15px;
      transition: border-color 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);
      width: 100%;
      padding-left: 50px;
      padding-right: 50px;
      text-align: center;
    }
    .my-input-number .my-input-number__decrease,
    .my-input-number .my-input-number__increase {
      position: absolute;
      z-index: 1;
      top: 1px;
      width: 40px;
      height: auto;
      text-align: center;
      background: #f5f7fa;
      color: #606266;
      cursor: pointer;
      font-size: 13px;
    }
    .my-input-number .my-input-number__decrease {
      left: 1px;
      border-radius: 4px 0 0 4px;
      border-right: 1px solid #dcdfe6;
    }
    .my-input-number .my-input-number__increase {
      right: 1px;
      border-radius: 0 4px 4px 0;
      border-left: 1px solid #dcdfe6;
    }
    .my-input-number .my-input-number__decrease.is-disabled,
    .my-input-number .my-input-number__increase.is-disabled {
      color: #c0c4cc;
      cursor: not-allowed;
    }
    </style>
    
  • 步骤:

    • 为了让父里的数据改变后能影响到子,所以子里的num,不应该是自己独立的数据(声明在data中数据),而应该是由 props 传递过来的,所以先把data中的num删了,再写一个props

      props: {
          
          num: {
              type: Number,
              required: true
          }
      }
      
    • 但此时点+和点- 都会报错,因为之前写的都是 this.num++ 或者 this.num--,这样就破坏了单向数据流,为了不破坏单向数据流,该通知父组件自己来改值

          // +号的点击事件
          add() {
            // 小于10才允许++
            if (this.num < 10) {
              // 下面这句话没用了,此时num是props传过来的数据
              // 如果直接改了会破坏单向数据流
              // this.num++;
              // 通知父组件去+和-
              this.$emit('changeNum', this.num + 1)
            }
          },
              
              // -号的点击事件
          sub() {
            // 大于0才允许--
            if (this.num > 0) {
              // this.num--;
              this.$emit('changeNum', this.num - 1)
            }
          },
      
    • 父里接收此通知,并拿到参数赋值给父自己的num,那么父的num变了,父的num变了后,自动流入到子,子的界面也会跟着变

         <base-input-num :num="num" @changeNum="changeNum"/>
      
      changeNum (val) {
          
          this.num = val
      }
      
  • 图解

35f16d12-98c6-471a-a642-49da20551faf.png

$event关键字

如果要把简短的逻辑提取到行内,需要认识一个关键字$event

传送门:使用事件抛出一个值

  • 在之前 原生标签 时,$event代表 事件对象
  • 现在,对于组件而言,$event代表这个子组件传递过来的值

BaseInputNum使用调优

结合上一步的$event关键字,提取父组件使用的逻辑到行内

<base-input-num :num="num" @changeNum="num = $event"/>

组件上使用v-model(数据流转图)

表单元素上可以通过v-model便捷的实现双向数据绑定,组件上也可以哦

传送门:在组件上使用v-model

  • v-model用在表单元素

  • 但实际上v-model也可以用在组件,要满足一定条件就能用

  • 因为:

    • v-model的本质只是一个语法糖

    • 它相当于帮你生成父传子的代码,以及帮你生成子传父的代码

    • 只不过父传子时,props默认只生成value属性的, 子传父事件名只生成input

    • 所以如果你的代码如下

      <组件 v-model="xx" ></组件>
      
      • 它会生成
      <组件 :value="xx" @input="xx = $event"></组件>
      
    • 所以如果希望,用组件时能用v-model,那要保证子组件里的props要写成value,子传父的事件名要写成input

BaseInputNum组件 - 实现v-model

接下来咱们来实现BaseInput组件

  • 把props里的num改名为value,并且把用到它的地方都改了

  • 把子传父时的$emit,事件名要从 changeNum 改成 input

  • 最后父组件里可以用v-model

    <base-input-num v-model="num"/>
    
  • 最终它相当于生成了

    <base-input-num :value="num" @input="num = $event"/>
    

Vue-CLI中启用less

使用css预处理器可以更好的编写样式,Vue-CLI中默认并没有启用,咱们今天首先把这个弄了

传送门:预处理器

  • 脚手架创建项目时如果选的是默认配置,是不支持less的,要支持less还得下载less以及less-loader

    npm i less less-loader
    
  • 如何在某个组件的代码中使用less语法?

    <style lang="less">
        /* 这个样式使用less的语法 */
    </style>
    
  • 或者直接写一个 .less的文件,在 main.js里导入

  • 浏览器不认识,但是我们的脚手架打包时会自动把它翻译成css

  • 所以以前的vscode插件:easy less禁用或者卸载

style中的样式是全局样式

组件style标签中的样式是全局样式哦

  • 不管是在哪个组件里写的style,但凡这个组件导入了,这个组件里的样式都是全局的

  • 所以啊,很容易造成样式冲突

Scoped CSS

除了上一节分析的解决方案意外,在Vue中还可以通过Scoped CSS 来解决哦,直译过来,就是范围样式

传送门:Scoped CSS

  • 解决办法就是:

    • 给组件的style里写一个 scoped
    • 那就代表这个style里写的样式,只能给当前组件使用,就不冲突了
  • 加了scoped后的原理

    • 会让当前组件的所有标签,具备一个行内属性: data-v-hash值
    • 而且会把你写的样式变成 属性选择器,那就代表既要满足之前的选择器又要它满足行内有data-v-hash值的属性,所以这样子就保证了只会让当前组件生效

总结 和 作业

今天的重点内容,和作业

总结:

  1. slot的作用?

    • 可以让组件内某个html结构不写死
  2. 具名插槽<slot name="top"/>如何传递内容?

    • 推荐语法

      <template v-slot:top></template> ,或者 <template #top></template>

    • 废弃语法

      <template slot="top"></template>

  3. props推荐的写法是什么?

    • 对象
  4. 哪个单词是必传?

    • required
  5. 哪个单词是限制类型?

    • type
  6. 哪个单词是默认值?

    • default
      • 基本类型直接写值
      • 复杂类型要写一个函数,在函数里return
  7. 哪个单词是校验?

    • validate
      • return true代表通过
      • return false代表校验不通过
  8. 单向数据流:父组件中数据的改变会传递给子组件,但是反过来却不行,不能修改是指不能修改栈,堆可以

  9. <SonCom @numChange="func">,需要SonCom组件内部实现什么?

    • $emit('numChange')
  10. $event用在内联语句时:

  11. dom元素:事件对象

  12. 组件: 传递过来的值

  13. <SonCom v-model="msg">中的v-model等同于

    • :value="msg" @input="msg = $event"
  14. Vue-CLI中编写less需要:

    1. 安装:npm install -D less-loader less
    2. <style ></style>写成什么样
  15. style标签中的样式默认是什么样式?

    • 全局
  16. [data-v-哈希值]需要给style添加什么属性?

    • scoped

作业:

f661ff7f-e3c5-4429-985c-1aee0a24ec80.gif

  1. 基于提供的模板完成BaseSwitch组件

    1. 需求:
     <BaseSwitch v-model="isChecked" />
    <script>
    
    import BaseSwitch from './components/BaseSwitch.vue'
    export default {
      name: 'App',
      data(){
        return {
          isChecked:true
        }
      },
      components: {
        BaseSwitch,
      },
    }
    </script>
    
  2. 基于提供的模板完成BaseCheckBox组件

    1. 需求:

       <BaseCheckBox v-model="isChecked" />
      <BaseCheckBox v-model="isChecked" >文本</BaseCheckBox>
      <script>
      
      import BaseCheckBox from './components/BaseCheckBox.vue'
      export default {
        name: 'App',
        data(){
          return {
            isChecked:true
          }
        },
        components: {
          BaseCheckBox,
        },
      }
      </script>
      
  3. 说明:

    1. 模板中的默认逻辑是为了保证组件目前的切换效果
    2. 可以根据需求进行删减

今日单词

单词解释说明
slot插槽
v-slot插槽<组件 v-slot:插槽名>

</组件>简写为
<组件 #插槽名>

</组件>
props属性在子里写props,props推荐对象形式,type限制传递类型;不推荐数组形式。
required写了required,又写default,还是需要自己传参。
defaultprops对象中default写默认值。写了default,不需要再写default。
validator数据校验props里可使用validator验证数据
propF: {
validator: function (value) {
// 这个值必须匹配下列字符串中的一个
return ['success', 'warning', 'danger'].indexOf(value) !== -1
}
}
$emit子里传值$emit('自定义的事件名', 传递的数据);父里监听<子组件 @自定义的事件名=”函数“ />
$event$event在原生标签代表 事件对象;在组件代表子组件传递过来的值
v-model双向绑定如果希望组件时能用v-model,那要保证子组件里的props要声明成value,子传父的事件名要写成input<组件 v-model="xx" ></组件>会生成<组件 :value="xx" @input="xx = $event"></组件>
less-loader脚手架使用less,安装命令npm i less less-loader;安装后,把vscode插件easy less禁用或卸载
scoped域内的解决组件内的样式是全局样式的问题。<style scoped></style>。作用把样式变成选择器[data-v-hash]。可搭配深度作用选择器::v-deep /deep/ >>>使用