前端框架VUE学习文档

前端框架学习

(一)Vue实现

1.1 简介

  • Vue 是一套用于构建用户界面的渐进式 JavaScript框架。

  • 渐进式框架:表示我们可以在项目中一点点来引入和使用Vue,而不一定需要全部使用Vue来开发整个项目

  • vue的两个特性:

    • 声明式渲染:Vue 基于标准 HTML 拓展了一套模板语法,使得我们可以声明式地描述最终输出的 HTML 和 JavaScript 状态之间的关系。
    • 响应性:Vue 会自动跟踪 JavaScript 状态并在其发生变化时响应式地更新 DOM。
  • 第一个vue程序:

    • 步骤:

      • 1.导入开发版本的vue.js

            <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
        
      • 2.创建vue实例对象,设置el属性和data属性。

      • 使用简洁的模板语法把数据渲染到页面上

        <body>
          <div id="app">
            {{message}}
          </div>
          <script>
            new Vue({
              el: '#app',
              data: {
                message: "hello world"
              }
            })
          </script>
        </body>
        

1.2 引入vue的方式:

1.2.1 CDN引入

在页面中通过CDN的方式来引入

<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
1.2.2 手动引入

下载Vue的JavaScript文件,并且自己手动引入

<script src="../js/vue.js"></script>
1.2.3 npm包管理安装使用

通过npm包管理工具安装使用它

1.2.4 Vue CLI创建项目使用

直接通过Vue CLI创建项目,并且使用它;

1.3 基础语法

1.3.1 模板语法
  • 概念:Vue模板语法是一种声明式的标记语言,用于将组件的数据渲染进DOM。

  • Vue的响应式系统是Vue框架的核心特性之一。当使用Vue模板语法绑定数据时,Vue会自动追踪依赖,并在数据变化时更新DOM。

  • 基础语法详解:

    • 插值表达式

      • 插值表达式是Vue模板中最基本的数据绑定方式。它允许将JavaScript表达式的值嵌入到模板中

        <!-- 基本文本插值 -->
        <span>Message: {{ message }}</span>
        
        <!-- 表达式插值 -->
        <span>Count: {{ count + 1 }}</span>
        
    • 指令

      • 指令是Vue模板中的特殊标记,用于告诉Vue应该如何响应数据的变化。
1.3.2 el挂载点
  • el是用来设置Vue实例挂载(管理的元素)
  • Vue会管理el选项命中的元素及内部的后代元素
  • 可以使用其他选择器,但建议使用id选择器
    可以使用其他的双标签,但不建议使用html和body标签
1.3.3 data数据对象
  • vue中用到的数据定义在data中

  • data可以写复杂数据,渲染复杂数据时,遵守js语法就可以了

  <div id="app">
    <!-- {{message}} -->
    这是介绍:{{school.name+"在"+school.add+" 校区分布在"+campus[0]+campus[1]+campus[2]}}
    <!-- 这是介绍:黑马程序员在湖南长沙 校区分布在北京校区上海校区长沙校区 -->
  </div>
  <script>
    new Vue({
      el: '#app',
      data: {
        message: "hello world",//字符串
        school: {

          name: '黑马程序员',
          add: '湖南长沙'
        },
        campus: ["北京校区", "上海校区", "长沙校区"]
      }
    })
  </script>
1.3.4 vue-本地应用(vue指令)

指令:带有v-前缀的特殊标签属性

(1)内容绑定、事件绑定(v-text、v-html、v-on)
  • v-text 设置标签文本值:v-text 可以将 data 中的数据通过 {{}} 插值表达式 设置到 html 标签的内容中,并且默认是替换标签内的全部内容。另外, v-text 中也支持写表达式,例如通过 “+” 进行字符串或 data 的拼接.

    <span v-text="message+school.name">你好</span>
    
  • v-html 设置标签的 innerHTML:v-html指令可以将内容中的 html 解析成标签,而 v-text 只能解析成文本.

        <div v-html="htmlStr"></div>
    
        <div v-text="htmlStr"></div>
        <!-- 百度 
         <a href="https://www.baidu.com">百度</a> -->
    
  • v-on 为元素绑定事件

    v-on 指令就是为元素绑定事件的(注册事件),也可以将 v-on 简写为 @. 绑定的方法定义在 methods 属性中,方法内部必须通过 this 关键字访问到定义在 data 中的数据.

    v-on:click="方法":点击事件.
    v-on:dblclick="方法":双击事件.
    v-on:monseenter="方法":鼠标移入事件.
    

    语法:

    (1)v-on:“事件名”=“内联语句”

      <div id="count">
    
        <button v-on:mouseenter="count--">-</button>
        <span>{{count}}</span>
        <button @mouseenter="count++">+</button>
      </div>
      <script>
    
        new Vue({
          el: "#count",
          data: {
            count: 100
          }
        })
      </script>
    

    (2)v-on:“事件”=“methods中的函数名”.

    在methods中是等同的。

     fn(){},
     fn:function(){}
    

      <div id="app">
        <button type="button" @click="counter">计数器+1</button>
        <button type="button" v-on:click="counter">计数器+1</button>
        <div>计数器的数量为{{count}}</div>
      </div>
    <script>
        new Vue({
          el: "#app",
          data: {
            count: 0,
          },
          methods: {
            counter: function () {
              this.count += 1;
            }
          }
    </script>
    

(2)显示切换、属性绑定(v-show、v-if 、v-bind )
  • v-show

    • 作用: 控制元素显示隐藏
    • 语法: v-show = “表达式” 表达式值为 true 显示, false 隐藏
    • 原理: 切换 display:none 控制显示隐藏
    • 场景:频繁切换显示隐藏的场景
  • v-if

    • 作用: 控制元素显示隐藏(条件渲染)

    • 语法: v-if= “表达式” 表达式值 true显示, false 隐藏

    • 原理: 基于条件判断,是否创建 或 移除元素节点

    • 场景: 要么显示,要么隐藏,不频繁切换的场景

    • v-else 和 v-else-if

      1. 作用:辅助v-if进行判断渲染

      2. 语法:v-else v-else-if=“表达式”

      3. 需要紧接着v-if使用

        <body>
        
          <div id="app">
            <p v-if="gender">性别:♂ 男</p>
            <p v-else>性别:♀ 女</p>
            <hr>
            <p v-if="score>=90">成绩评定A:奖励电脑一台</p>
            <p v-else-if="score>=80">成绩评定B:奖励周末郊游</p>
            <p v-else-if="score>=70">成绩评定C:奖励零食礼包</p>
            <p v-else>成绩评定D:惩罚一周不能玩手机</p>
          </div>
        
          <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
          <script>
        
            const app = new Vue({
              el: '#app',
              data: {
                gender: 2,
                score: 95
              }
            })
          </script>
        </body>
        
  • v-bind

    1. **作用:**动态设置html的标签属性 比如:src、url、title
    2. 语法:**v-bind:**属性名=“表达式”
    3. **v-bind:**可以简写成 => :

    比如,有一个图片,它的 src 属性值,是一个图片地址。这个地址在数据 data 中存储。

    则可以这样设置属性值:

    • <img v-bind:src="url" />
    • <img :src="url" /> (v-bind可以省略)

(3)列表循环、表单元素绑定(v-for 、v-model )
  • v-for:Vue 提供了 v-for 列表渲染指令,用来辅助开发者基于一个数组来循环渲染一个列表结构。

    • v-for 指令需要使用 (item, index) in arr 形式的特殊语法,其中:
      • item 是数组中的每一项
      • index 是每一项的索引,不需要可以省略
      • arr 是被遍历的数组

    此语法也可以遍历对象和数字

  <div id="app">
    <h2>我的水果店</h2>
    <ul>
      <li v-for="(item,index) in list">水果{{item}}在数组的第{{index}}索引上</li>
      <!-- 如果用不上index 可以省略index 写成:item in list -->
    </ul>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  <script>

    new Vue({
      el: "#app",
      data: {
        list: ['苹果', '香蕉', '菠萝']
      }
    })
  </script>

v-for中的key
//
语法:key属性=“唯一值”

作用:给列表项添加的唯一标识。便于Vue进行列表项的正确排序复用

**为什么加key:**Vue 的默认行为会尝试原地修改元素(就地复用

  • v-model

    • 作用:给表单元素使用,双向数据绑定,可以快速获取或设置表单元素。
    • 可以让数据和视图,形成双向数据绑定
      • 数据变化,视图自动更新
      • 视图变化,数据自动更新

    作用:表单元素(input、radio、select)使用,双向绑定数据,可以快速 获取设置 表单元素内容

    **语法:**v-model=“变量”

1.3.5 指令修饰符

所谓指令修饰符就是通过“.”指明一些指令后缀 不同的后缀封装了不同的处理操作 —> 简化代码。

(1)按键修饰符
  • @keyup.enter —>当点击enter键的时候才触发
 <input type="text" placeholder="请输入任务" v-model="newItem" @keyup.enter="addTask">
//在键盘输入回车时,触发addTask
(2)v-model修饰符
  • v-model.trim —>去除首位空格

    <input type="text" placeholder="请输入任务" v-model.trim="newItem" @keyup.enter="addTask">
    

  • v-model.number —>转数字

(3)事件修饰符
事件冒泡:当事件在DOM树中传播时,首先会在事件发生的元素(即事件的目标元素)上触发,然后逐级向上传播到DOM树的根节点(在HTML文档中通常是<html>元素),这个过程称为事件冒泡。
阻止冒泡:event.stopPropagation
默认行为:默认行为是指浏览器对特定事件做出的标准响应。例如,点击链接(<a>元素)的默认行为是导航到新页面,提交表单(<form>元素)的默认行为是将数据发送到服务器。
阻止默认行为:event.preventDefault()
  • 阻止冒泡:@事件名.stop

      <h3>阻止冒泡</h3>
      <div id="app">
        <div class="father" @click="fatherFn">父亲
          <div class="son" @click.stop="sonFn"> 儿子</div>
        </div>
      </div>
    
      <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
      <script>
        new Vue({
          el: "#app",
          data: {},
          methods: {
            fatherFn() {
    
              alert("父亲被点击了")
            },
            sonFn() {
    
              alert("儿子被点击了")
            },
          }
        })
    
  • 事件名.prevent —>阻止默认行为

      <a @click.prevent href="http://www.baidu.com">点击就会跳转</a>
    

  • 事件名.stop.prevent —>可以连用 即阻止事件冒泡也阻止默认行为

1.3.6 v-bind对样式控制的增强-操作class

为了方便开发者进行样式控制, Vue 扩展了 v-bind 的语法,可以针对 class 类名style 行内样式 进行控制 。

(1)语法
<div> :class = "对象/数组">这是一个div</div>
(2)对象语法

当class动态绑定的是对象时,键就是类名,值就是布尔值,如果值是true,就有这个类,否则没有这个类

<div class="box" :class="{类名1:布尔值,类名2:布尔值}"></div>
   适用场景:一个类名,来回切换
案例:tab导航高亮
  <style>
    * {
      margin: 0;
      padding: 0;
    }

    ul {
      display: flex;
      border-bottom: 2px solid red;
      padding: 0 10px;
    }

    li {
      width: 100px;
      height: 50px;
      line-height: 50px;
      list-style: none;
      text-align: center;
    }

    li a {
      display: block;
      text-decoration: none;
      font-weight: bold;
      color: black;
    }

    li a.active {
      color: #fff;
      background-color: #e01222;
    }
  </style>
</head>

<body>

  <!-- 导航tab高亮 -->

  <div id="app">

    <ul>
      <li v-for="(item,index) in list" :key="item.id" @click="activeIndex=index">
        <a :class="{active: index===activeIndex}" href="#">{{item.name}}</a>
      </li>
    </ul>
  </div>
  <!-- 
  需求:基于数据动态渲染tab
  准备下表记录高亮的是哪一个tab
  基于下标,动态控制class类名
  -->
  <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  <script>
    new Vue({
      el: "#app",
      data: {
        list: [
          {
            id: 1, name: '京东秒杀'
          },
          {
            id: 2, name: "每日特价"
          },
          {
            id: 3, name: "品类秒杀"
          }
        ],
        activeIndex: 1
      },
    })
  </script>

</body>
(3)数组对象

当class动态绑定的是数组时 → 数组中所有的类,都会添加到盒子上,本质就是一个 class 列表

<div class="box" :class="[类名1, 类名2, 类名3 ]"></div>
   使用场景:批量添加或删除类
案例:tab导航高亮
  <style>
    * {
      margin: 0;
      padding: 0;
    }

    ul {
      display: flex;
      border-bottom: 2px solid red;
      padding: 0 10px;
    }

    li {
      width: 100px;
      height: 50px;
      line-height: 50px;
      list-style: none;
      text-align: center;
    }

    li a {
      display: block;
      text-decoration: none;
      font-weight: bold;
      color: black;
    }

    li a.active {
      color: #fff;
      background-color: #e01222;
    }
  </style>
</head>

<body>

  <!-- 导航tab高亮 -->

  <div id="app">

    <ul>
      <li v-for="(item,index) in list" :key="item.id" @click="activeIndex=index">
        <a :class="{active: index===activeIndex}" href="#">{{item.name}}</a>
      </li>
    </ul>
  </div>
  <!-- 
  需求:基于数据动态渲染tab
  准备下表记录高亮的是哪一个tab
  基于下标,动态控制class类名
  -->
  <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  <script>
    new Vue({
      el: "#app",
      data: {
        list: [
          {
            id: 1, name: '京东秒杀'
          },
          {
            id: 2, name: "每日特价"
          },
          {
            id: 3, name: "品类秒杀"
          }
        ],
        activeIndex: 1
      },
    })
  </script>

</body>
1.3.7 v-bind对样式控制的增强-操作style
(1)语法
:style="样式对象"
<div class="box" :style="{ CSS属性名1: CSS属性值, CSS属性名2: CSS属性值 }"></div>
注意:js里面不支持带-的属性写法:
   <div id="app">
    <div class="box" :style="{ width:'400px',height:'200px',backgroundColor:'green'}"></div>
  </div>(要把background-color特殊属性用引号带起来)或者使用驼峰:
请注:里面的对象键值不要用双引号,一定要单引号
适用场景:某个具体属性的动态设置
(2)进度条案例
案例:进度条
<style>
  .progress {
    height: 25px;
    width: 400px;
    border-radius: 15px;
    background-color: #272425;
    border: 3px solid #272425;
    box-sizing: border-box;
    margin-bottom: 30px;
  }

  .inner {
    width: 50%;
    height: 20px;
    border-radius: 10px;
    text-align: right;
    position: relative;
    background-color: #409eff;
    background-size: 20px 20px;
    box-sizing: border-box;
    transition: all 1s;
  }

  .inner span {
    position: absolute;
    right: -20px;
    bottom: -25px;
  }
</style>

<body>
  <div id="app">
    <div class="progress">
      <div class="inner" :style="{width: percent+'%'}">
        <span>{{percent}}%</span>
      </div>
    </div>
    <button @click="percent=25">设置25%</button>
    <button @click="percent=50">设置50%</button>
    <button @click="percent=75">设置75%</button>
    <button @click="percent=100">设置100%</button>
  </div>


  <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>

  <script>
    new Vue({
      el: "#app",
      data: {

        percent: 0
      }

    })
  </script>
1.3.8 v-model 应用于其他表单元素

前面演示的为input输入框,其他表单元素:

常见的表单元素都可以用 v-model 绑定关联 → 快速 获取设置 表单元素的值

它会根据 控件类型 自动选取 正确的方法 来更新元素

输入框  input:text   ——> value
文本域  textarea	 ——> value
复选框  input:checkbox  ——> checked
单选框  input:radio   ——> checked
下拉菜单 select    ——> value
...
<body>

  <div id="app">
    <h3>小黑学习网</h3>

    <label for="name">姓名</label>
    <input type="text" id="name" v-model="username">
    <br><br>
    <label for="single">是否单身</label>
    <input type="checkbox" id="single" v-model="isSingle">
    <br><br>
    <!-- <label for="sex">性别</label> -->
    <!-- 
      前置理解:
        1. name:  给单选框加上 name 属性 可以分组 → 同一组互相会互斥
        2. value: 给单选框加上 value 属性,用于提交给后台的数据
      结合 Vue 使用 → v-model
    -->
    性别

    <input v-model="gender" type="radio" name="gender" value="1"><input v-model="gender" type="radio" name="gender" value="2"><br><br>


    <!-- 
      前置理解:
        1. option 需要设置 value 值,提交给后台
        2. select 的 value 值,关联了选中的 option 的 value 值
      结合 Vue 使用 → v-model
    -->

    <label for="city">所在城市</label>
    <select v-model="city" name="city" id="city">
      <option value="北京">北京</option>
      <option value="上海">上海</option>
      <option value="成都">成都</option>
      <option value="南京">南京</option>
    </select>
    <br><br>
    自我描述:
    <br>
    <textarea v-model="area"></textarea>
    <button>立即注册</button>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  <script>

    new Vue({
      el: "#app",
      data: {
        username: '杨淑琦',
        isSingle: true,
        gender: 2,//v-model会绑定到value里面
        city: "成都",
        area: "这是我的自我介绍"

      }
    })
  </script>
1.3.9 计算属性
(1)概念语法:
  • 概念:基于现有的数据,计算出来的新属性,依赖的数据变化,那么自动重新计算

  • 语法:

    • 声明在computed配置项中,一个计算属性对应一个函数

    • 使用和其他普通属性一样使用

          new Vue({
            el:"",
            data:{
      
            },
            computed:{
              计算属性名(){
                基于现有数据,编写求值逻辑
                return 结果
              }
            }
          })
      在使用中:{{计算属性名}}
      
示例:
<body>

  <div id="app">

    <table>
      <tr>
        <th>名字</th>
        <th>数量</th>
      </tr>
      <tr v-for="(item,index) in list" :key="item.id">
        <td>{{item.name}}</td>
        <td>{{item.num}}个</td>
      </tr>
    </table>
    <span>礼物总数:{{total}}个</span>
  </div>

  <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  <script>
    new Vue({
      el: "#app",
      data: {
        list: [
          {
            id: 1, name: '篮球', num: 4
          },
          { id: 2, name: '玩具', num: 2 },
          { id: 3, name: '铅笔', num: 5 }
        ]

      },
      computed: {
        total() {
          let number = 0;
          // 计算总数
          return this.list.reduce((number, item) => number + item.num, 0)
        }

      }

    })
  </script>
(2)computed计算属性和method方法:
  • computed计算属性

    • 作用:封装了一段对于数据的处理,求得一个结果
    • 语法:
      • 写在computed配置项
      • 作为属性,直接使用:
        • js中使用计算属性: this.计算属性
        • 模板中使用计算属性:{{计算属性}}
  • methods方法

    • 作用:给Vue实例提供一个方法,调用以处理业务逻辑
    • 语法:
      • 写在methods配置项中
      • 作为方法调用
        • js中调用:this.方法名()
        • 模板中调用 {{方法名()}} 或者 @事件名=“方法名”
  • 计算属性优势

    缓存特性(提升性能)

    计算属性会对计算出来的结果缓存,再次使用直接读取缓存,

    依赖项变化了,会自动重新计算 → 并再次缓存

  • 对比总结

    1.computed有缓存特性,methods没有缓存

    2.当一个结果依赖其他多个值时,推荐使用计算属性

    3.当处理业务逻辑时,推荐使用methods方法,比如事件的处理函数

(3)计算属性完整写法

既然计算属性为属性,那么它既可以用来获取,也可以用来修改咯。

计算属性默认的简写,只能读取访问,不能修改。

如果要 “修改” → 需要写计算属性的完整写法

在这里插入图片描述

1.3.9 watch 侦听器(监视器)

作用:监视数据变化,执行一些业务逻辑或异步操作。

需求:输入内容,实时翻译。

(1)语法:
  • 简单写法:简单类型数据,直接监视
  • 完整写法:添加额外配置
(2)简单写法

    data: { 
      words: '苹果',
      obj: {
        words: '苹果'
      }
    },
    
    watch: {
      // 该方法会在数据变化时,触发执行
      数据属性名 (newValue, oldValue) {
        一些业务逻辑 或 异步操作。 
      },
      '对象.属性名' (newValue, oldValue) {
        一些业务逻辑 或 异步操作。 
      }
    }



(3)防抖:延迟执行

简介:干啥事先等一等,延迟一会,一段时间内没有再次触发,才执行。

案例:实时翻译


<scropt>
new Vue({
      el: "#app",
      data: {
        obj: {
          words: ''
        },
        language: 'german',
        myRes: '',//存放翻译的结果
        // timer: null //延时器 可省略在data里面写入

      },
      // 监视
      watch: {
        // 此方法会在数据变化时,进行调用 
        // timer 可以不用存在data里面  直接写下面的this.timer也可以,相当于直接给对象加了timer属性
        'obj.words'(newValue, oldValue) {
          // 加入一个延时器 都会侦听
          clearTimeout(this.timer)
          this.timer = setTimeout(async () => {
            //只有这个setTimeOut出现的问题:就是你只要输入了就会有效,只不过只是延迟了翻译而已
            // 我需要的是:停稳了才执行,如果中间有打断的,那么要清空之前的计时器
            const res = await axios({
              url: 'https://applet-base-api-t.itheima.net/api/translate',
              params: {
                words: this.obj.words,
                lang: this.language
              }
            })
            this.myRes = res.data.data
            console.log(res.data.data);
          }, 300)
        }
      }
    })
  </script>
(4)完整写法

完整写法:添加额外配置。

  1. deep:true 对复杂类型进行深度监听

  2. immdiate:true 初始化 立刻执行一次 (是否需要立即执行一个handler)

    data: {
      obj: {
        words: '苹果',
        lang: 'italy'
      },
    },
    
    watch: {// watch 完整写法
      对象: {
        deep: true, // 深度监视
        immdiate:true,//立即执行handler函数
        handler (newValue) {
          console.log(newValue)
        }
      }
    }
    

案例:输入内容,修改语言,能实时翻译

(一个结果,多个条件 把条件数据写在对象当中)

 <script>
    new Vue({
      el: "#app",
      data: {
        obj: {
          words: '',
          language: 'german'
        },
        myRes: '',//存放翻译的结果
      },
      watch: {
        obj: {
          deep: true,
          immediate: true,//一进入页面 立即执行 handel
          handler(newValue) {
            console.log(newValue);
            clearTimeout(this.timer)
            this.timer = setTimeout(() => {
              axios({
                // method:'post',
                url: 'https://applet-base-api-t.itheima.net/api/translate',
                params: newValue
                // words: this.obj.words,
                // lang: this.obj.language
              }).then(result => {
                // console.log(result);
                this.myRes = result.data.data
                console.log(this.obj.language);
              })
            }, 300)

          }
        }


      }

    })
  </script>
(5)两者写法的对比
 //简单写法 
  watch: {
      // 该方法会在数据变化时,触发执行
      数据属性名 (newValue, oldValue) {
        一些业务逻辑 或 异步操作。 
      },
      '对象.属性名' (newValue, oldValue) {
        一些业务逻辑 或 异步操作。 
      }
    }
    
    //完整写法:
    watch: {// watch 完整写法
  对象: {//对对象里面的所有进行监视
    deep: true, // 深度监视
    immdiate:true,//立即执行handler函数
    handler (newValue) {
      console.log(newValue)
    }
  }
}

1.4 生命周期

什么时候可以发送初始化渲染请求?(越早越好)什么时候可以开始操作dom?(至少dom得渲染出来)

Vue生命周期:就是一个Vue实例从创建 到 销毁 的整个过程.

1.4.1 生命周期阶段

生命周期四个阶段:① 创建 ② 挂载 ③ 更新 ④ 销毁

(1)创建阶段:创建响应式数据
(2)挂载阶段:渲染模板
(3)更新阶段:修改数据,更新视图
(4)销毁阶段:销毁Vue实例

在这里插入图片描述

1.4.2 生命周期函数(钩子函数)

Vue生命周期过程中,会自动运行一些函数,被称为【生命周期钩子】→ 让开发者可以在【特定阶段】运行自己的代码

生命周期有四个阶段,钩子函数有八个,每个阶段的前后都会有一个函数。
在这里插入图片描述

重要俩个:
(1)created(发送初始化渲染请求,beforeCreate数据还没准备好呢)
(2)mounted (beferMount阶段dom还没有准备好,所以操作dom在mounted阶段)

<body>
  <div id="app">

    <h2>{{title}}</h2>
    <button @click="count--">-</button>
    <span class="num">{{count}}</span>
    <button class="btn" @click="count++">+</button>

  </div>

  <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  <script>

    new Vue({
      el: "#app",
      data: {
        count: 100,
        title: '计数器'
      },
      // 1.创建阶段(准备数据)

      beforeCreate() {

        console.log("1.1准备数据之前" + this.count);

      },
      created() {

        console.log("1.2 数据准备好了" + " " + this.count + this.title);
      },

      // 2.挂载阶段(渲染模板)
      beforeMount() {
        const num = document.querySelector('.num').innerText

        console.log("2.1 在渲染之前" + num);
        // 在渲染之前{{count}}
      },
      mounted() {
        const num = document.querySelector('.num').innerText
        console.log("2.2 模板渲染完之后" + num);
        //  模板渲染完之后100
      },
      //可以操作dom了

      // 3.更新阶段
      beforeUpdate() {
        const num = document.querySelector('.num').innerText
        console.log("数据还没被更新,拿到的数据为原数据" + num);

      },
      updated() {
        const num = document.querySelector('.num').innerText

        console.log("数据更新了拿到的数据为新数据" + num);
      },
      // 4.销毁阶段
      beforeDestroy() {


        console.log("销毁实例之前释放资源");
      },
      destroyed() {

?        console.log("销毁实例");
      }
    })
  </script>
</body>
(1)created应用

created:响应式数据准备好了,可以开始发送初始化渲染请求

 // 接口地址:http://hmajax.itheima.net/api/news
  // 请求方式:get
  const app = new Vue({
    el: '#app',
    data: {

      list: []
    },
    async created() {
      // 1.发送请求。获取数据
      const res = await axios.get('http://hmajax.itheima.net/api/news')
      console.log(res);
      // 2.将数据更新给data里面的list
      this.list = res.data.data
      console.log(this.list);
    },
  })
(2)mounted应用
//一进入页面,立刻能获取焦点(焦点-操作dom)
  const app = new Vue({
      el: '#app',
      data: {
        words: ''
      },
      // 核心思路:
      // 1. 等input框渲染出来 ---渲染之后使用:mounted 钩子 
      // 2. 让input框获取焦点 inp.focus()
      mounted() {
        //找到input
        document.getElementById('inp').focus()
      }
    })
(3)案例的总结
  • 关于echarts

    • 1.引入文件

    • 2.为图表准备一定宽高的容器盒子

    • 3.准备图表。

      this.myChart = echarts.init(document.getElementById('main'))
      
    • 4.指定图表的配置项和数据 使用option={}

      1. 使用刚指定的配置项和数据显示图表

         
        this.myChart.setOption(option)
        
        
    • 异步数据如何同步到图表?

      在图表初始化后不管任何时候只要通过工具异步获取数据后通过 setOption 填入数据和配置项就行。
                // 更新图表
                // { value: 1048, name: '防晒霜' },
                // { value: 735, name: '球鞋' },
                this.myChart.setOption({
                  series: [
                    {
                      data:
      
                        this.list.map(item => ({
                          value: item.price,
                          name: item.name
                        }))
                    }
                  ]
                })
      

      在这里插入图片描述

1.5 工程化开发和脚手架Vue CLi

1.5.1 开发vue的两种方式:
  • 核心包传统开发模式:基于html / css / js 文件,直接引入核心包,开发 Vue。

  • 工程化开发模式:基于构建工具(例如:webpack)的环境中开发Vue。

在这里插入图片描述

工程化开发模式优点:

 提高编码效率,比如使用JS新语法、Less/Sass、Typescript等通过webpack都可以编译成浏览器识别的ES3/ES5/CSS等

工程化开发模式问题:

  • webpack配置不简单
  • 雷同的基础配置
  • 缺乏统一的标准

为了解决以上问题,所以我们需要一个工具,生成标准化的配置

1.5.2 Vue CLI脚手架
  • Vue CLI 是Vue官方提供的一个全局命令工具可以帮助我们快速创建一个开发Vue项目的标准化基础架子。【集成了webpack配置】

  • 好处:

    • 开箱即用,零配置
    • 内置babel等工具
    • 标准化的webpack配置
  • 使用步骤:

    • 全局安装(只需安装一次即可) yarn global add @vue/cli 或者 npm i @vue/cli -g
    • 查看vue/cli版本: vue --version
    • 创建项目架子:vue create project-name(项目名不能使用中文)
    • 启动项目:yarn serve 或者 npm run serve(命令不固定,找package.json)
      在这里插入图片描述
1.5.3 组件化开发

组件化:一个页面可以拆分成一个个组件,每个组件有着自己独立的结构、样式、行为。

​ 好处:便于维护,利于复用 → 提升开发效率。

如:下面这个页面,可以把所有的代码都写在一个页面中,但是这样显得代码比较混乱,难易维护。咱们可以按模块进行组件划分
在这里插入图片描述

组件分类:普通组件、根组件。

1.5.4 根组件
(1)介绍

根组件:App.vue整个应用最上层的组件,包裹所有普通小组件.
在这里插入图片描述

(2)组件的组成:
  • 三部分构成(结构、行为和样式)

    • template:结构 (有且只能一个根元素)

    • script: js逻辑 export default{}

    • style: 样式 (可支持less,需要装包)

      • 让组件支持less

        (1) style标签,lang=“less” 开启less功能

        (2) 装包(两个 less和less-loader): yarn add less less-loader -D 或者npm i less less-loader -D

    <template>
      <div class="box" @click="fn"></div>
      <!-- //只能有一个根元素 -->
    </template>
    <script>
    // 导出的是当前组件的配置项
    // 可以提供data(特殊) methods,computed,watch 生命周期,八大钩子
    
    export default{
    methods:{
      fn(){
        alert('点击了!')
      }
    }
      
    }
    </script>
    
    <style>
    .box{
      width: 400px;
      height: 400px;
      background-color: pink;
    }
    </style>
    
    

1.5.5 普通组件的注册使用
  • 注册的两种方式:
    • 1.全局注册:所有的组件内都能使用
    • 2.局部注册:只能在注册的组件内使用
      • (1)创建.vue文件
      • (2)在使用的组件内导入并注册
(1)局部注册:

组件名规范 —> 大驼峰命名法, 如 HmHeader

使用方式:当成html标签使用即可 <组件名></组件名>

例如:

import 组件对象 from ./vue文件路径
比如import HmHeader from './components/HmHeader'
export default{
components:{
  '组件名':组件对象,
  HmHeader:HmHeader,
  HmHeader
}
}
(2)全局注册:

全局注册的组件,在项目的任何组件中都能使用.

  • 使用步骤:

    • 创建vue组件

    • 在main.js中全局注册

      // 导入需要全局注册的组件
      import HmButton from './components/HmButton'
      Vue.component('HmButton', HmButton)
      
    • 使用:当成HTML标签直接使用

      <组件名></组件名>

1.5.6 scoped样式冲突
(1)组件注意点
  • 组件三大组成成分
    • 结构template:只有一个根元素
    • 样式style:默认是全局样式,影响所有组件。局部样式:scoped下样式,只作用于当前组件
    • 逻辑script:el是根实例独有的,data是一个函数,其他配置项是一样的
(2)scoped 样式冲突
  • 写在组件中的样式会 全局生效 → 因此很容易造成多个组件之间的样式冲突问题。
    • 全局样式: 默认组件中的样式会作用到全局,任何一个组件中都会受到此样式的影响
    • 局部样式: 可以给组件加上scoped 属性,可以让样式只作用于当前组件
<template>
  <div class="base-one">
    BaseOne
  </div>
</template>

<script>
export default {

}
</script>
<style scoped>
</style>
(3)scoped原理
  • 当前组件模板的所有元素,都会被加上一个自定义属性。

    • 最终效果: 必须是当前组件的元素, 才会有这个自定义属性, 才会被这个样式作用到

    • 当前组件内标签都被添加data-v-hash值 的属性

    • css选择器都被添加 [data-v-hash值] 的属性选择器
      在这里插入图片描述

1.5.7 data是一个函数

一个组件的data是一个函数,保证每个组件实例,维护独立的一份数据对象。

每次创建新的组件实例,都会新执行一次data 函数,得到一个新对象。

<template>
  <div class="base-count">
    <button @click="count--">-</button>
    <span>{{ count }}</span>
    <button @click="count++">+</button>
  </div>
</template>

<script>
export default {
  data(){
    return {
      count:999
    }
  }

}
</script>

<style>

</style>
1.5.8 组件通信
(1)概念:
  • 组件通信,就是指组件与组件之间的数据传递
    • 组件的数据是独立的,无法直接访问其他组件的数据。
    • 想使用其他组件的数据,就需要组件通信
    • 组件之间有什么关系呢?对应的通信逻辑有哪些?
(2)组件关系与通信逻辑
  • 组件关系分类:

    • 父子关系

    • 非父子关系

      在这里插入图片描述

(2.1)父子通信逻辑-父传子数据
  1. 父组件通过 props 将数据传递给子组件
  2. 子组件利用 $emit 通知父组件修改更新
    在这里插入图片描述
    在这里插入图片描述
  • 步骤
    • 在使用子组件的时候,以添加属性的方式来传值。
    • 子内部通过props接收
    • 子组件的模板中直接使用props接收到的值。
    • 注意:使用props: props:[‘title’] 数组包起来,变量放引号。
(2.2)父子通信逻辑-子通知父修改

子组件利用 $emit 通知父组件,进行修改更新
在这里插入图片描述

  • 步骤:
    • $emit触发事件,给父组件发送消息通知
    • 父组件监听$emit触发的事件
    • 提供处理函数,在函数的形参中获取传过来的参数
(3)Prop详解
  • 概念:组件上 注册的一些 自定义属性。向子组件传递数据
  • 特点:
    • 可以 传递 任意数量 的prop
    • 可以 传递 任意类型 的prop
(4)props校验

为组件的 prop 指定验证要求,不符合要求,控制台就会有错误提示 → 帮助开发者,快速发现错误

  • 语法:

    • 类型校验

      在这里插入图片描述

    • 非空校验

    • 默认值

    • 自定义校验

(5)props校验完整写法

不局限于类型的校验

props: {
  校验的属性名: {
    type: 类型,  // Number String Boolean ...
    required: true, // 是否必填
    default: 默认值, // 默认值
    validator (value) {
      // 自定义校验逻辑
      return 是否通过校验
    }
  }
},

示例:

<script>
export default {
  // 完整写法(类型、默认值、非空、自定义校验)
  props: {
    w: {
      type: Number,
      //required: true,
      default: 0,
      //注意:default和required一般不同时写(因为当时必填项时,肯定是有值的)
      validator(val) {
        // console.log(val)
        if (val >= 100 || val <= 0) {
          console.error('传入的范围必须是0-100之间')
          return false
        } else {
          return true
        }
      },
    },
  },
}
</script>
(6)prop和data、单向数据流

都可以给组件提供数据,data 的数据是自己的 → 随便改 。prop 的数据是外部的 → 不能直接改,要遵循 单向数据流

  • 单向数据流:父级props 的数据更新,会向下流动,影响子组件。这个数据流动是单向的
(7)小黑记事本案例总结:
  • 持久化存储。将数据保存到本地。watch深度监视list的变化,一旦变化,本地存储。一进入页面,优先读取。

      data () {
        return {
            
          list:JSON.parse( localStorage.getItem('list')) ||
          [{
            id:1,name:'打篮球'
          },{id:2,name:'写作业'},
          {id:3,name:'学前端'}
        ]
        }
      },
    watch:{
        list:{
          // 深度监视:
          deep:true,
          immediate:true,
          handler(newValue){
            // 一旦变化,立即执行 将数组转为json字符串存储
            localStorage.setItem('list',JSON.stringify(newValue))
          }
        }
      },
    
  • 总结:

  • (1)拆分基础组件-

    • 新建组件

    • 拆分组件结构

    • 导入、注册、使用

      导入:import
      注册:
      	全局:在main.js。注册:Vue.component
      	局部:在需要的组件注册。注册:在script里面compontens:{}
      使用:<组件名></组件名>
      
  • (2)渲染实现任务

    • 提供数据(公告父组件)
      • 父传子:
        • 在使用的子组件上添加属性 : 子组件使用的属性名=“父组件传的数据”,
        • 子组件接收,在script里面,使用props属性
        • 子组件使用,同vue里面的使用
      • 子通知父:
        • 在子组件定义事件,使用this.$emit(‘事件名’,参数)
        • 把事件传给父。在父组件里面使用的子组件里面添加 @子组件定义的事件名=“在父组件实现的事件名”
        • 父组件在methods里面实现相应逻辑
  • 对于数组的一些方法:

    • 通过id删除数组
      this.list=this.list.filter(item=>item.id!==id)
    
    • unshift添加数组元素

            this.list.unshift({
              id:+new Date(),
              name:value
            })
      

      其余笔记,正持续更新~一枚萌新正持续成长中!

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值