Vue学习笔记(持续更新)

第一章、快速入门

  • Vue是什么

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

      1. 渐进式: Vue可以自底向上逐层的应用
        • 简单应用:只需要一个轻量小巧的核心库
        • 复杂应用:可以引入各式各样的Vue插件
  • Vue的特点

    1. 采用组件化模式,提高代码复用率,且让代码更好维护

    2. 声明式编码,让编码人员无需直接操作*DOM*,提高开发效率

    3. 使用虚拟DOM加优秀的Diff算法,尽量的复用*DOM*节点

  • Vue.js安装

    1. CDN引入

      <script src="https://unpkg.com/vue@next"></script>
      
    2. 本地引入

      1. 下载

        官网下载**Vue.js文件,同<script>**标签引入到HTML内

    3. NPM安装

      $ npm install vue@next
      
    4. *Vue*版本

      开发版本:包含了完整的警告和调试模式

      生产版本:删除了警告

  • Vue.js入门案例

    • 响应式

      <!DOCTYPE html>
      <html lang="en">
      <head>
          <meta charset="UTF-8">
          <title>响应式</title>
      </head>
      <body>
      <div id="app">
          <h1>{{aa}}</h1>
      </div>
      <!--引用本地Vue.js-->
      <script src="vue.global.js"></script>
      <script>
          //实例化对象
          const HelloVue = {
              //通过data定义值
              data() {
                  //返回一个值
                  return {
                      aa: "你好.Vue.js"
                  }
              }
          };
          //创建Vue对象,接管ID为App<DIV>标签
          const app = Vue.createApp(HelloVue).mount('#app')
      </script>
      </body>
      </html>
      
    • 命令式

      <!DOCTYPE html>
      <html lang="en">
      <head>
          <meta charset="UTF-8">
          <title>命令式</title>
      </head>
      <body>
      <div id="app"></div>
      <script>
          //获取DIV的ID
          const app = document.getElementById('app')
          // 添加一个H1标签
          let h1E = document.createElement('h1')
          //给H1标签添加内容
          app.appendChild(h1E)
          //给H1标签innerText属性赋值
          h1E.innerText = "你好,Vue.js"
      </script>
      </body>
      </html>
      
    • 创建列表

      <!DOCTYPE html>
      <html lang="en">
      <head>
          <meta charset="UTF-8">
          <title>相应式</title>
      </head>
      <body>
      <div id="app">
          <ul>
              <li>{{colleges [0]}}</li>
              <li>{{colleges [1]}}</li>
              <li>{{colleges [2]}}</li>
              <li>{{colleges [3]}}</li>
          </ul>
         <ul>
             <li v-for="college in colleges">{{college}}</li>
         </ul>
      </div>
      <!--引用本地Vue.js-->
      <script src="vue.global.js"></script>
      <script>
          //实例化对象
          const ListApp = {
              //通过data定义值
              data() {
                  //返回一个对象
                  return {
                      colleges: ['1', '2', '3', '4']
                  }
              }
          };
          //创建Vue对象,接管ID为App<DIV>标签
          const app = Vue.createApp(ListApp).mount('#app')
      </script>
      </body>
      </html>
      
    • 通过输入框修改*A标签URL*

      <!DOCTYPE html>
      <html lang="en">
      <head>
          <meta charset="UTF-8">
          <title>相应式</title>
      </head>
      <body>
      <div id="app">
          <a v-bind:href="msg2">{{msg2}}</a>
          <br>
          <input v-model="msg1" v-on:keyup.enter="fun" v-on:blur.native.capture="fun" placeholder="请在这里网址回车结结束">
      </div>
      <!--引用本地Vue.js-->
      <script src="vue.global.js"></script>
      <script>
          const app = Vue.createApp({
              data() {
                  return {
                      msg1: "",
                      msg2: "网址"
                  }
              },
              methods: {
                  fun() {
                      this.msg2 = "https://" + this.msg1
                  }
              }
          }).mount('#app')
      </script>
      </body>
      </html>
      
  • MVCMVPMVVM

    1. MVC

      1. 概念
        1. M是值业务模型,V是值用户界面,C则是控制器
          1. MModel模型,数据层,负责数据的处理和获取的数据接口层
          2. VView视图,试图层,是指用户看到并与之交互的界面。比如由HTML元素组成的网页界面,或者软件的客户端界面
          3. Ccontroller控制器,控制器层,它是ModelView之间的胶水或者说是中间人
        2. MVC各部分之间通信的方式
          1. View传送指令到controller
          2. controller完成业务逻辑后,要求Model改变状态
          3. Model将新的数据发送到View,用户得到反馈
          4. 所有通信都是单向的
      2. 好处
        1. 耦合性低
        2. 重用性高
        3. 部署快,生命周期成本低
        4. 可维护性高
      3. 存在问题
        1. 不适合小型、中等规模的 应用程序
        2. 试图与控制器之间过于紧密链接并且降低了试图对模型数据的访问
    2. MVP

      1. 概念

        MVP模式将controller改名为Presenter(广播),同时改变了通信方向

      2. 特点
        1. 各部分之间通信都是双向的
        2. 视图和模型不发生联系,都是通过表现传递
        3. View非常薄,不部署任何业务逻辑,称为被动视图,即没有任何主动性,而Presenter非常薄,所有逻辑都在这里
      3. 适应性

        MVP适用于事件驱动的应用架构中,如asp.net web formWindows forms应用。

    3. MVVM

      1. MVVM模式将Presenter层替换成为ViewModel,其他与MVP模式基本一致
      2. 它和MVP的区别是,采用双向绑定,试图层的变动,自动反应在ViewModel,反之亦然。AngularVueReact采用这种方式
      3. MVVM模式中,一个ViewModel和一个View匹配,完全和View绑定,所有View中的修改变化,都会更新到ViewModel中,同时ViewModel的任何变化都会同步到View上显示
  • Vue中对MVVM的运用

    1. 概念

      1. View
        1. 视图层
        2. 前端中主要是指 DOM
        3. 适用于用户展示各种页面信息
      2. Model
        1. 数据层
        2. 可以是固定的数据,也可以是来自网络请求的数据
        3. 用于给用户展示各种页面信息
      3. ViewModel
        1. 试图模型层
        2. ViewModel 沟通的桥梁
        3. 内部实现了
          1. 数据绑定

            Model 中数据改变能实时反映到 *View*中

          2. DOM 监听

            监听 DOM 中的事件触发,根据业务需求改变 Model 中对应的数据

第二章、基础语法

  1. 双括号语法

    1. 概念

      Mustache 语法

    2. 使用

      可以是实例中的变量,可以是简单表达式

  2. 常用指令

    1. 插值语法

      1. V-Text
        • 预期:String
        • 详细:更新元素的 textContent 。如果要更新部分的 textContent
        • 实例:
          <span v-text="msg"></span>
          <!-- 等价于 -->
          <span>{{msg}}</span>
          
      2. V-Html
        • 预期:String
        • 详细:

          ​ 更新元素的 innerHTML注意:内容按普通 HTML 插入 - 不会作为 Vue 模板进行编译。如果试图使用 v-html 组合模板,可以重新考虑是否通过使用组件来替代。

          ​ 在网站上动态渲染任意 HTML 是非常危险的,因为容易导致 XSS 攻击。只在可信内容上使用 v-html永不用在用户提交的内容上。

          ​ 在单文件组件里,scoped 的样式不会应用在*v-html内部,因为那部分 HTML 没有被 Vue 的模板编译器处理。如果你希望针对v-html*的内容设置带作用域的 CSS,你可以替换为 CSS modules 或用一个额外的全局 <style> 元素手动设置类似 BEM 的作用域策略。

        • 实例:
          <div v-html="html"></div>
          
      3. V-Pre
        • 预期:String
        • 详细:

          跳过这个元素和它的子元素的编译过程。可以用来显示原始 Mustache 标签。跳过大量没有指令的节点会加快编译。

        • 实例:
          <span v-pre>{{ this will not be compiled }}</span>
          
      4. V-Cloak
        • 不需要表达式
        • 用法:

          这个指令保持在元素上直到关联组件实例结束编译。和 CSS 规则如 [v-cloak] { display: none } 一起用时,这个指令可以隐藏未编译的 Mustache 标签直到组件实例准备完毕。

        • 实例:

          <div> 不会显示,直到编译结束。

          [v-cloak] {
            display: none;
          }
          <div v-cloak>
            {{ message }}
          </div>
          
      5. V-Once

        • 不需要表达式
        • 详细:

          只渲染元素和组件一次。随后的重新渲染,元素/组件及其所有的子节点将被视为静态内容并跳过。这可以用于优化更新性能。

        • 实例:
          <!-- 单个元素 -->
          <span v-once>This will never change: {{msg}}</span>
          <!-- 有子元素 -->
          <div v-once>
            <h1>comment</h1>
            <p>{{msg}}</p>
          </div>
          <!-- 组件 -->
          <my-component v-once :comment="msg"></my-component>
          <!-- `v-for` 指令 -->
          <ul>
            <li v-for="i in list" v-once>{{i}}</li>
          </ul>
          
    2. 条件和循环

      1. V-show
        1. 预期:any
        2. 用法:

          根据表达式的真假值,切换元素的 display CSS property。当条件变化时该指令触发过渡效果。

      2. V-if
        1. 预期:any
        2. 用法:

          根据表达式的真假值来有条件地渲染元素。在切换时元素及它的数据绑定 / 组件被销毁并重建。如果元素是 <template>,将提取它的内容作为条件块。

          当条件变化时该指令触发过渡效果。

          当和*v-for*一起使用时, v-if 的优先级比 v-for 更高。

      3. V-showV-if区别

        V-if 是"真正"的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地销毁和重建。

        V-show 不管初始条件是什么,元素总是会被渲染,并且只是简单基于 CSS 进行切换。

        V-show HTML 展示,你在输入框输入内容也会存在就算是不停切换依旧会存在,V-if 不会HTML 显示,在输入框内输入的内容在切换后就不存在了,如果需要频繁的切换使用 V-show 效果最好。

        • 实例:V-showV-if 综合案例
          <!DOCTYPE html>
          <html lang="en">
          <head>
              <meta charset="UTF-8">
              <title>V-if和V-show</title>
          </head>
          <body>
          <div id="app">
              <div v-if="flag">要下雨</div>
              <div v-else>不下雨</div>
              <div v-show="flag">要去</div>
              <div v-show="!flag">不去</div>
              <button v-on:click="getFlag()">切换</button>
          </div>
          <script src="vue.global.js"></script>
          <script>
              const app = Vue.createApp({
                  data() {
                      return {
                          flag: true,
                      }
                  },
                  computed: {},
                  methods: {
                      getFlag() {
                          return this.flag = !this.flag
                      }
                  }
              }).mount('#app')
          </script>
          </body>
          </html>
          
          <!--登录案例-->
          <!DOCTYPE html>
          <html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml">
          <head>
              <meta charset="UTF-8">
              <title>V-if和V-show综合案例</title>
          </head>
          <body>
          <div id="app">
              <label v-show="flag">
                  手机:
                  <input type="text" placeholder="请输入手机号" v-model="name">
              </label>
              <label v-show="!flag">
                  邮箱:
                  <input type="text" placeholder="请输入邮箱" v-model="name">
              </label>
              <label>
                  <br>
                  密码:
                  <input type="password" placeholder="请输入密码" v-model="password">
              </label>
              <br>
              <button v-on:click="getFlag()">切换登录模式</button>
              <button v-on:click="login()">登录</button>
          </div>
          <script src="vue.global.js"></script>
          <script>
              const app = Vue.createApp({
                  data() {
                      return {
                          flag: true,
                          name: '',
                          password: ''
                      }
                  },
                  computed: {},
                  methods: {
                      getFlag() {
                          return this.flag = !this.flag
                      },
                      login() {
                          if (this.flag === true) {
                              if (this.name === '123' || this.password === '123') {
                                  return alert("登录成功")
                              }
                              return alert("登录失败")
                          }
                          if (this.flag === false) {
                              if (this.name === '456' || this.password === '123') {
                                  return alert("登录成功")
                              }
                              return alert("登录失败")
                          }
                      }
                  }
              }).mount('#app')
          </script>
          </body>
          </html>
          
      4. V-else
        1. 不需要表达式
        2. 限制:前一兄弟元素必须有 v-ifv-else-if
      5. V-else-if
        1. 预期:any
        2. 限制:前一兄弟元素必须有 v-ifv-else-if
      6. V-for
        1. 预期:Array Object number string Iterable
        2. 为什么要绑定*Key*

          Key是给每个vnode的唯一id,可以依靠 Key,更准确、更快的拿到 oldVnode中对应的vnode 节点,方便插入数据后数据错位

        3. 用法:

          基于源数据多次渲染元素或模板块。此指令之值,必须使用特定语法 alias in expression,为当前遍历的元素提供别名:

          <div v-for="item in items">
            {{ item.text }}
          </div>
          

          另外也可以为数组索引指定别名 (或者用于对象的键):

          <div v-for="(item, index) in items"></div>
          <div v-for="(value, key) in object"></div>
          <div v-for="(value, name, index) in object"></div>
          

          v-for 的默认行为会尝试原地修改元素而不是移动它们。要强制其重新排序元素,你需要用特殊*attribut* *key*来提供一个排序提示:

          <div v-for="item in items" :key="item.id">
            {{ item.text }}
          </div>
          

          v-for 也可以在实现了可迭代协议的值上使用,包括原生的 MapSet

          v-for 的详细用法可以通过以下链接查看教程详细说明。

        4. 实例:
          <!DOCTYPE html>
          <html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml">
          <head>
              <meta charset="UTF-8">
              <title>V-for遍历数组</title>
          </head>
          <body>
          <div id="app">
              <h1>简单遍历</h1>
              <ul>
                  <li v-for="arrs in arr ">数组里的内容:{{arrs}}</li>
              </ul>
              <h1>带索引遍历</h1>
              <ul>
                  <li v-for="(arrs,index) in arr ">数组里的内容:{{arrs}}。下标:{{index}}</li>
              </ul>
              <h1>遍历数组里的对象</h1>
              <ul>
                  <li v-for="(arrClasss,index) in arrClass ">
                      数组里的内容:{{arrClasss}}。姓名:{{arrClasss.name}}。年龄:{{arrClasss.age}}岁。地址:{{arrClasss.address}}。下标:{{index}}
                  </li>
              </ul>
              <h1>遍历对象</h1>
              <ul>
                  <li v-for="itme in person ">
                      数组里的内容:{{itme}}。
                  </li>
              </ul>
              <h1>遍历对象带键值对的</h1>
              <ul>
                  <li v-for="(itme ,key) in person ">
                      键:{{key}}。值:{{itme}}。
                  </li>
              </ul>
              <h1>遍历对象带键值对和索引的</h1>
              <ul>
                  <li v-for="(itme ,key, index) in person">
                      键:{{key}}。值:{{itme}}。索引:{{index}}
                  </li>
              </ul>
          </div>
          <script src="vue.global.js"></script>
          <script>
              const app = Vue.createApp({
                  data() {
                      return {
                          arr: ['一', '二', '三', '四', '五'],
                          arrClass: [
                              {name: "张三", age: "12", address: "上海"},
                              {name: "李四", age: "13", address: "北京"},
                              {name: "王五", age: "14", address: "深圳"},
                              {name: "赵六", age: "15", address: "广州"},
                              {name: "周七", age: "16", address: "香港"},
                          ],
                          person: {
                              name: "祈求者",
                              age: "五万岁",
                              address: ["夜魇", "天辉"]
                          }
                      }
                  },
                  computed: {},
                  methods: {}
              }).mount('#app')
          </script>
          </body>
          </html>
          
      7. V-ifV-for的优先级对比
        • 概览

          非兼容:两者作用于同一个元素上时,v-if 会拥有比 v-for 更高的优先级

        • 介绍

          Vue.js中使用最多的两个指令就是v-ifv-for,因此开发者们可能会想要同时使用它们。

        • 语法
          1. 2.0

            2.x 版本中在一个元素上同时使用 v-ifv-for 时,v-for 会优先作用。

          2. 3.0

            3.x 版本中 v-if 总是优先于 v-for 生效。

    3. 绑定属性

      1. V-bind
        1. 缩写::
        2. 预期:any (with argument) Object (without argument)
        3. 参数:attrOrProp (optional)
        4. 修饰符:
          • .prop - 作为一个 DOM property 绑定而不是作为 attribute 绑定。
          • .camel - (2.1.0+) 将 kebab-case attribute 名转换为 camelCase。(从 2.1.0 开始支持)
          • .sync (2.3.0+) 语法糖,会扩展成一个更新父组件绑定值的 v-on 侦听器。
        5. 用法:

          动态地绑定一个或多个 attribute,或一个组件 prop 到表达式。

          在绑定 classstyle attribute 时,支持其它类型的值,如数组或对象。可以通过下面的教程链接查看详情。

          在绑定 prop 时,prop 必须在子组件中声明。可以用修饰符指定不同的绑定类型。

          没有参数时,可以绑定到一个包含键值对的对象。注意此时 classstyle 绑定不支持数组和对象。

        6. 实例:
          <!-- 绑定一个 attribute -->
          <img v-bind:src="imageSrc">
          
          <!-- 动态 attribute 名 (2.6.0+) -->
          <button v-bind:[key]="value"></button>
          
          <!-- 缩写 -->
          <img :src="imageSrc">
          
          <!-- 动态 attribute 名缩写 (2.6.0+) -->
          <button :[key]="value"></button>
          
          <!-- 内联字符串拼接 -->
          <img :src="'/path/to/images/' + fileName">
          
          <!-- class 绑定 -->
          <div :class="{ red: isRed }"></div>
          <div :class="[classA, classB]"></div>
          <div :class="[classA, { classB: isB, classC: isC }]">
          
          <!-- style 绑定 -->
          <div :style="{ fontSize: size + 'px' }"></div>
          <div :style="[styleObjectA, styleObjectB]"></div>
          
          <!-- 绑定一个全是 attribute 的对象 -->
          <div v-bind="{ id: someProp, 'other-attr': otherProp }"></div>
          
          <!-- 通过 prop 修饰符绑定 DOM attribute -->
          <div v-bind:text-content.prop="text"></div>
          
          <!-- prop 绑定。“prop”必须在 my-component 中声明。-->
          <my-component :prop="someThing"></my-component>
          
          <!-- 通过 $props 将父组件的 props 一起传给子组件 -->
          <child-component v-bind="$props"></child-component>
          
          <!-- XLink -->
          <svg><a :xlink:special="foo"></a></svg>
              
          <!-- .camel 修饰符允许在使用 DOM 模板时将 v-bind property 名称驼峰化,例如 SVG 的 viewBox property: -->
          <svg :view-box.camel="viewBox"></svg>
          <!-- 在使用字符串模板或通过 vue-loader/vueify 编译时,无需使用 .camel。-->
          
          <!DOCTYPE html>
          <html lang="en">
          <head>
              <meta charset="UTF-8">
              <title>切换Class</title>
              <style>
                  .mydiv {
          
                      color: black;
                  }
          
                  .red {
                      font-size: 60px;
                  }
          
                  .yellow {
                      border: red solid 1px;
                  }
          
                  .blue {
                      text-decoration: underline;
                  }
          
              </style>
          </head>
          <body>
          <div id="app">
              <!--    用对象是之间前面的变量是CSS的变量名-->
              <P v-bind:class="{mydiv:temp,red:temp,yellow:temp,blue:temp}">sadasdsd</P>
              <!--    数组的里面的是CSS样式重新定义的变量名-->
              <P v-bind:class="ks">sadasdsd</P>
              <!--    调用函数-->
              <P v-bind:class="ks">sadasdsd</P>
              <button v-on:click="chengge">点我</button>
          </div>
          <!--引用本地Vue.js-->
          <script src="vue.global.js"></script>
          <script>
              const app = Vue.createApp({
                  data() {
                      return {
                          temp: true,
                          ks: ['mydiv', 'red', 'yellow', 'blue']
                      }
                  },
                  methods: {
                      chengge() {
                          this.temp = !this.temp
                      },
                      CSS() {
                          return cs = ['mydiv', 'red', 'yellow', 'blue']
                      }
                  }
              }).mount('#app')
          </script>
          </body>
          </html>
          
      2. V-On
        1. 缩写:@
        2. 预期:Function Inline Statement Object
        3. 参数:event
        4. 修饰符:
          1. 事件修饰符
            • .stop - 调用 event.stopPropagation()
            • .prevent - 调用 event.preventDefault()
          2. 按键修饰符
            • .capture - 添加事件侦听器时使用*capture*模式。
            • .self - 只当事件是从侦听器绑定的元素本身触发时才触发回调。
            • .{keyAlias} - 仅当事件是从特定键触发时才触发回调。
            • .once - 只触发一次回调。
            • .left - 只当点击鼠标左键时触发。
            • .right - 只当点击鼠标右键时触发。
            • .middle - 只当点击鼠标中键时触发。
            • .passive - { passive: true } 模式添加侦听器
        5. 用法:

          绑定事件监听器。事件类型由参数指定。表达式可以是一个方法的名字或一个内联语句,如果没有修饰符也可以省略。

          用在普通元素上时,只能监听原生 DOM 事件。用在自定义元素组件上时,也可以监听子组件触发的自定义事件

          监听原生 DOM 事件时,方法以事件为唯一的参数。如果使用内联语句,语句可以访问一个 $event property:v-on:click="handle('ok', $event)"

          v-on 同样支持不带参数绑定一个事件/监听器键值对的对象。注意当使用对象语法时,是不支持任何修饰器的。

        6. 实例:
          <!-- 方法处理器 -->
          <button v-on:click="doThis"></button>
          
          <!-- 动态事件 -->
          <button v-on:[event]="doThis"></button>
          
          <!-- 内联语句 -->
          <button v-on:click="doThat('hello', $event)"></button>
          
          <!-- 缩写 -->
          <button @click="doThis"></button>
          
          <!-- 动态事件缩写 -->
          <button @[event]="doThis"></button>
          
          <!-- 停止冒泡 -->
          <button @click.stop="doThis"></button>
          
          <!-- 阻止默认行为 -->
          <button @click.prevent="doThis"></button>
          
          <!-- 阻止默认行为,没有表达式 -->
          <form @submit.prevent></form>
          
          <!-- 串联修饰符 -->
          <button @click.stop.prevent="doThis"></button>
          
          <!-- 键修饰符,键别名 -->
          <input @keyup.enter="onEnter" />
          
          <!-- 点击回调只会触发一次 -->
          <button v-on:click.once="doThis"></button>
          
          <!-- 对象语法 -->
          <button v-on="{ mousedown: doThis, mouseup: doThat }"></button>
          
          <!-- 在子组件上监听自定义事件 (当子组件触发“my-event”时将调用事件处理器): -->
          
          <my-component @my-event="handleThis"></my-component>
          
          <!-- 内联语句 -->
          <my-component @my-event="handleThis(123, $event)"></my-component>
          
          <!DOCTYPE html>
          <html lang="en">
          <head>
              <meta charset="UTF-8">
              <title>V-on</title>
          </head>
          <body>
          <div id="app">
              <h1>运输结果:{{sum}}</h1>
              <button @click="add">+</button>
              <button @click="sub">-</button>
              <h1>传递参数</h1>
              <button @click="getClick1()">不带参数</button>
              <button @click="getClick2">不带参数</button>
              <button @click="getClick3(123,'asd','阿斯顿',sum)">带参数</button>
              <!--    传递事件的时候需要使用$ 参数放在钱事件在最后-->
              <button @click="getClick4(123,'asd','阿斯顿',sum,$event)">带参数需要事件对象</button>
          </div>
          <!--引用本地Vue.js-->
          <script src="vue.global.js"></script>
          <script>
              const app = Vue.createApp({
                  data() {
                      return {
                          sum: 0
                      }
                  },
                  methods: {
                      add() {
                          this.sum++;
                      },
                      sub() {
                          this.sum--;
                          if (this.sum < 0) {
                              return this.sum = 0
                          }
                      },
                      getClick1(aaa) {
                          //空对象
                          console.log(aaa);
                      },
                      getClick2(aaa) {
                          //默认的事件对象
                          console.log(aaa);
                      },
                      getClick3(aaa, bbb, ccc, ddd) {
                          //默认的事件对象
                          console.log(aaa, bbb, ccc, ddd);
                      },
                      getClick4(aaa, bbb, ccc, ddd, event) {
                          //默认的事件对象
                          console.log(aaa, bbb, ccc, ddd, event);
                      }
                  }
              }).mount('#app')
          </script>
          </body>
          </html>
          
    4. 表单绑定

      • V-model
        1. 预期:随表单控件类型不同而不同。
        2. 限制于:
          • <input>
          • <select>
          • <textarea>
          • components
        3. 修饰符:
          • .lazy - 监听 change 而不是 input 事件
          • .number - 输入字符串转为有效的数字
          • .trim- 输入首尾空格过滤
        4. 用法:
          <!DOCTYPE html>
          <html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml">
          <head>
              <meta charset="UTF-8">
              <title>V-model的实例</title>
          </head>
          <body>
          <div id="app">
              <h1>单选</h1>
              <label>
                  <input type="checkbox" v-model="flag">是否同意协议
              </label>
              <P>是否同意协议:{{flag ? "同意" : "不同意"}}</P>
              <button v-bind:disabled="!flag">下一步</button>
              <h1>多选</h1>
              <label>
                  <input type="checkbox" value="篮球" v-model="arr">篮球
                  <input type="checkbox" value="足球" v-model="arr">足球
                  <input type="checkbox" value="排球" v-model="arr">排球
                  <input type="checkbox" value="网球" v-model="arr">网球
                  <input type="checkbox" value="台球" v-model="arr">台球
              </label>
              <p>你选择的兴趣是:{{arr}}</p>
              <h1>动态的绑定</h1>
              <label v-for="index in textArr " v-bind:for="index">
                  <input type="checkbox" v-bind:value="index" v-bind:id="index" v-model="likes">{{index}}
                  <br>
              </label>
              <p>你选择的兴趣是:{{likes}}</p>
              <h1>下拉单选</h1>
              <p>选择所在的城市:{{getCity}}</p>
              <label>
                  <select name="getCity" v-model="getCity">
                      <option v-bind:value="index" v-bind:id="index" v-for="index in city">{{index}}</option>
                  </select>
              </label>
              <h1>下拉多选</h1>
              <p>选择所在的城市:{{getCitys}}</p>
              <label>
                  <select v-bind:name="getCitys" v-model="getCitys" multiple>
                      <option v-bind:value="index" v-bind:id="index" v-for="index in citys">{{index}}</option>
                  </select>
              </label>
              <h1>V-model修饰符</h1>
              <label>
                  <input v-model.lazy="smg">
                  <input v-model.number="num">
                  <input v-model.trim="name">
              </label>
              <p>{{smg}}</p>
              <br>
              <p>{{num}}是{{typeof num}}类型</p>
              <br>
              <P>过滤首位空格xxxx{{name}}xxxx</P>
          </div>
          <script src="vue.global.js"></script>
          <script>
              const app = Vue.createApp({
                  data() {
                      return {
                          flag: false,
                          arr: [],
                          textArr: ["祈求者", "丽娜", "露娜", "帕吉", "帕克"],
                          likes: [],
                          city: ["昆明", "大理", "玉溪"],
                          getCity: "昆明",
                          citys: ["昆明", "大理", "玉溪"],
                          getCitys: [],
                          smg: '',
                          num: 0,
                          name: ""
                      }
                  },
                  computed: {},
                  methods: {}
              }).mount('#app')
          </script>
          </body>
          </html>
          
        5. V-model的基本实现:

          通过单项绑定一个 Value ,然后通过事件监听,监听输入事件,让事件获取单项绑定的 value,实现 V-model 的效果

          <!DOCTYPE html>
          <html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml">
          <head>
              <meta charset="UTF-8">
              <title>V-model的底层实现</title>
          </head>
          <body>
          <div id="app">
              <label>
                  <input type="text" v-bind:value="msg" v-on:input="getMSG">
              </label>
              <h1>{{msg}}</h1>
          </div>
          <script src="vue.global.js"></script>
          <script>
              const app = Vue.createApp({
                  data() {
                      return {
                          msg: ''
                      }
                  },
                  computed: {},
                  methods: {
                      getMSG(event) {
                          //Vue event.target.value( ) 获取当前文本框的值(由事件触发时)
                          return this.msg = event.target.value
                      }
                  }
              }).mount('#app')
          </script>
          </body>
          </html>
          
    5. 自定义指令

      1. Vue2.0写法
        1. 用函数的方式自定义指令
          <!DOCTYPE html>
          <html lang="en">
          <head>
              <meta charset="UTF-8">
              <title>自定义组件</title>
          </head>
          <body>
          <div id="app">
              <span v-big="n"></span>
          </div>
          </body>
          <script src="js/vue3.js"></script>
          <script>
              const app = Vue.createApp({
                  data() {
                      return {
                          n: 1
                      }
                  },
                  directives: {
                      //element:真实的DOM元素
                      //binding:获取到值
                      //big函数何时被调用 。 1.指令和元素成功绑定时。2.指令所在的模板从新解析时
                      big(element, binding) {
                          element.innerText = binding.value
                      }
                  }
              }).mount('#app')
          </script>
          </html>
          
        2. 用对象的方式自定义指令
          <!DOCTYPE html>
          <html lang="en">
          <head>
              <meta charset="UTF-8">
              <title>自定义组件</title>
          </head>
          <body>
          <div id="app">
              <input v-abc:value="n">
              <button v-on:click="n++">{{n}}</button>
          </div>
          </body>
          <script src="js/vue2.js"></script>
          <script>
              new Vue({
                  data: {
                      n: 1
                  },
                  directives: {
                      abc: {
                          //指令与元素成功绑定时
                          bind(element, binding) {
                              //element:真实的DOM元素
                              //binding:获取到值
                              element.value = binding.value
                          },
                          //指令所在元素被插入页面时
                          inserted(element, binding) {
                              element.value = binding.value
                              element.focus()
                          },
                          //指令所在的模板从新解析时
                          update(element, binding) {
                              element.value = binding.value
                              element.focus()
                          },
                      }
                  }
              }).$mount('#app')
          </script>
          </html>
          
      2. Vue3.0写法

        除了默认设置的核心指令( v-modelv-show ), Vue 也允许注册自定义指令。

        下面我们注册一个全局指令*v-focus*, 该指令的功能是在页面加载时,元素获得焦点

        指令定义函数提供了几个钩子函数(可选):

        • created: 在绑定元素的属性或事件监听器被应用之前调用
        • beforeMount: 指令第一次绑定到元素并且在挂载父组件之前调用
        • mounted: 在绑定元素的父组件被挂载后调用
        • beforeUpdate: 在更新包含组件的 VNode 之前调用
        • updated: 在包含组件的 VNode 及其子组件的 VNode 更新后调用
        • beforeUnmount: 当指令与在绑定元素父组件卸载之前时,只调用一次
        • unmounted: 当指令与元素解除绑定且父组件已卸载时,只调用一次
        <!DOCTYPE html>
        <html lang="en">
        <head>
            <meta charset="UTF-8">
            <title>自定义组件</title>
        </head>
        <body>
        <div id="app">
            <p>页面载入时,input 元素自动获取焦点:</p>
            <input v-focus:value="num">
            <br>
            <span v-runoob="{ name: '曹李奶奶', url: 'www.baidu.com' }"></span>
            <br>
            <span v-abc="num"></span>
        </div>
        </body>
        <script src="js/vue3.js"></script>
        <script>
            const app = Vue.createApp({
                data() {
                    return {
                        num: 1
                    }
                },
                directives: {
                    //正常写法
                    focus: {
                        // 在绑定元素的 attribute 或事件监听器被应用之前调用
                        created(element, binding) {
                            //element:真实的DOM元素
                            //binding:获取到值
                            console.log("created" + 1)
                        },
                        // 在绑定元素的父组件挂载之前调用
                        beforeMount(element, binding) {
                            //element:真实的DOM元素
                            //binding:获取到值
                            console.log("beforeMount" + 2)
                        },
                        // 绑定元素的父组件被挂载时调用
                        mounted(element, binding) {
                            //element:真实的DOM元素
                            //binding:获取到值
                            element.value = binding.value
                            console.log("mounted" + 3)
                            element.focus()
                        },
                        // 在包含组件的 VNode 更新之前调用
                        beforeUpdate(element, binding) {
                            //element:真实的DOM元素
                            //binding:获取到值
                            console.log("beforeUpdate" + 4)
                        },
                        // 在包含组件的 VNode 及其子组件的 VNode 更新之后调用
                        updated(element, binding) {
                            //element:真实的DOM元素
                            //binding:获取到值
                            console.log("beforeUpdate" + 5)
                        },
                        // 在绑定元素的父组件卸载之前调用
                        beforeUnmount(element, binding) {
                            //element:真实的DOM元素
                            //binding:获取到值
                            console.log("beforeUpdate" + 6)
                        },
                        // 卸载绑定元素的父组件时调用
                        unmounted(element, binding) {
                            //element:真实的DOM元素
                            //binding:获取到值
                            console.log("beforeUpdate" + 7)
                        }
                    },
                    //接收对象
                    runoob: {
                        mounted(element, binding) {
                            console.log(binding.name);
                            console.log(binding.url);
                            var s = JSON.stringify
                            element.innerHTML = s(binding.value)
                        },
                    },
                    //函数写法
                    abc(element, binding) {
                        element.innerHTML = binding.value
                    },
                }
            }).mount('#app')
        </script>
        </html>
        
    6. 计算属性和函数的区别

      在多次调用情况下函数每次都重新执行,计算属性只执行一次并且把执行结果缓存在页面上,如果中途计算属性则全部计算属性都会被修改,所以计算属性只满足于展示并且多次出现一类的属性就使用计算属性,如果只是一次那就用函数

第三章、理解 VueMVVM 模型

  1. M

    模型(Model):对应这data中的数据

  2. V

    视图(View):模板

  3. VM

    视图模型(ViewModel): Vue 实例对象

  4. *MVVM*模型总结

    1. data 中所有的属性,最后都出现在 vm 身上。
    2. vm 身上所有的属性及 Vue 原型上所有属性,在 Vue 模板中都可以直接使用

第四章、数据代理

  1. 回顾 Object.defineProperty 方法

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>defineProperty方法</title>
    </head>
    <body>
    <script>
        let person = {
            name: "张三",
            sex: "男"
        }
        let numbers = 12;
    
        //Object.defineProperty 对添加数据进行限制
        Object.defineProperty(person, "age", {
            // value: 18,
            // enumerable: true,//控制属性是否可以枚举, 默认值是false
            // writable: true,//控制属性是否可以修改, 默认值是false
            // configurable: true,//控制属性是否可以删除, 默认值是false
            
            //当有数据被读取的时候就执行这个方法
            get() {
                console.log("数据被执行了")
                return numbers
            },
            //当被修改的时候就执行这个方法
            set(v) {
                console.log("数据被修改了")
                numbers = v
            }
        })
    </script>
    </body>
    </html>
    
  2. 数据代理

    通过一个对象代理另一个对象的中的属性读写

  3. Vue 中的数据代理

    Object.defineProperty 进行数据代理,实现 data 里面的数据进行动态的数据代理

    在这里插入图片描述

第五章、监视属性

通过handler这个方法去监听数据的更新和变化

  1. immediate 初始化监视属性
  2. deep 监视子项的变换
<!DOCTYPE html>
<html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml">

<head>
    <meta charset="UTF-8">
    <title>监视属性</title>
</head>

<body>
    <div id="app">
        <input type="text" name="" id="" v-model="aaa">
        <input type="text" name="" id="" v-model="bbb">
        <h1>{{fullName}}</h1>
        <br>
        <input type="text" v-model="arr.name">
        <button @click="arr.age++">{{arr.age}}</button>
    </div>
    <script src="vue.global.js"></script>
    <script>
        const app = Vue.createApp({
                data() {
                    return {
                        aaa: "1",
                        bbb: "2",
                        arr: {
                            name: "张三",
                            age: 15
                        }
                    }
                },
                computed: {
                    fullName: function () {
                        return this.aaa + this.bbb
                    }
                },
                // 页面开始渲染的时候监视属性(这里是官网里官网案例)
                created() {
                    this.$watch('aaa', {
                        //初始化监听handler的变换
                        immediate: true,
                        handler(newdata, olddata) {
                            console.log(newdata, olddata);
                        }
                    })
                    this.$watch('fullName', {
                        //初始化监听handler的变换
                        immediate: true,
                        handler(newdata, olddata) {
                            console.log(newdata, olddata);
                        }
                    })
                    this.$watch('arr', {
                        //初始化监听handler的变换
                        immediate: true,
                        // 监视子项的变化
                        deep: true,
                        handler(newdata, olddata) {
                            console.log(newdata, olddata);
                        }
                    })
                },
                // 在监视器里监视属性
                watch: {
                    aaa: {
                        //初始化监听handler的变换
                        immediate: true,
                        handler(newdata, olddata) {
                            console.log(newdata, olddata);
                        }
                    },
                    fullName: {
                        immediate: true,
                        handler(newdata, olddata) {
                            console.log(newdata, olddata);
                        }
                    },
                    arr: {
                        immediate: true,
                        // 监视子项的变化
                        deep: true,
                        handler(newdata, olddata) {
                            console.log(newdata, olddata);
                        }
                    },
                    'arr.name': {
                        immediate: true,
                        // 监视某个子项的变化
                        deep: true,
                        handler(newdata, olddata) {
                            console.log(newdata, olddata);
                        }
                    },
                    // 简写形式是不能配置immediate和deep的
                    aaa(newdata, olddata) {
                        console.log(newdata, olddata);
                    }
                }
            }).mount('#app')
            //这也是一种监听器,但只能监听一个,属性不能监听多,而且要写在实例化后面
            .$watch('arr', {
                //初始化监听handler的变换
                immediate: true,
                // 监视子项的变化
                deep: true,
                handler(newdata, olddata) {
                    console.log(newdata, olddata);
                }
            })
    </script>
</body>

</html>

第六章、全家API

  1. Vue.set

    • 参数

      • {Object | Array} target
      • {string | number} propertyName/index
      • {any} value
    • 返回值:设置的值。

    • 用法

      向响应式对象中添加一个 property ,并确保这个新 property 同样是响应式的,且触发视图更新。它必须用于向响应式对象上添加新 property ,因为 Vue 无法探测普通的新增 property (比如 this.myObject.newProperty = 'hi')

    • 案例

      <!DOCTYPE html>
      <html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml">
      
      <head>
          <meta charset="UTF-8">
          <title>vue.set方法</title>
      </head>
      
      <body>
          <div id="app">
              <h1>支持vue2.0使用</h1>
              <input type="text" name="" id="" v-model="aaa" placeholder="添加地址">
              <ul>
                  <li>{{arr.name}}--{{arr.age}}--{{arr.dz}}</li>
              </ul>
              <br>
              <button @click="txsx()">添加</button>
          </div>
          <script src="vue.js"></script>
          <script>
              const vm = new Vue({
                  data() {
                      return {
                          aaa: "",
                          arr: {
                              name: "张三",
                              age: 15
                          }
                      }
                  },
                  methods: {
                      txsx() {
                          this.$set(this.arr, 'dz', this.aaa);
                      }
                  }
              }).$mount('#app')
          </script>
      </body>
      
      </html>
      
    • 注意

      vue.set只支持vue2.0,*vue3.0*应该有类似的实现,会在添加

  2. 待修改

第七章、过滤器

Vue2 存在 Vue3 被移除了,不是很重要的,但是可以了解一下

<!DOCTYPE html>
<html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml">

<head>
    <meta charset="UTF-8">
    <title>过滤器</title>
</head>

<body>
<div id="app">
    <h1>{{time}}</h1>
    <h1>{{time | getLocalTime}}</h1>
</div>
<script src="js/vue2.js"></script>
<script>
    const vm = new Vue({
        data() {
            return {
                time: new Date().getTime()
            }
        },
        filters: {
            getLocalTime(nS) {
                console.log(nS)
                return new Date(parseInt(nS) * 1000).toLocaleString().replace(/:\d{1,2}$/, ' ');
            }
        }
    }).$mount('#app')
</script>
</body>

</html>

第八章、组件

  1. 传统方式编写应用

    • 在多个页面出现同样的业务要重复编写

    • Js 依赖关系混乱,不好维护[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XXA7K7rN-1648022314899)(E:\笔记\前端\图片\20220307102856.png)]

  2. 通过组件编写应用

    1. 什么是组件

      实现应用中局部功能代码资源集合

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0X6jY81E-1648022314900)(E:\笔记\前端\图片\ae84b51bd21c953827f744f915383f0.png)]

    2. 怎么实现 Vue 组件

      1. 非单文件组件
        • 一个文件包含多个组件
        • Vue2 写法
          <!DOCTYPE html>
          <html lang="en">
          
          <head>
              <meta charset="UTF-8">
              <meta http-equiv="X-UA-Compatible" content="IE=edge">
              <meta name="viewport" content="width=device-width, initial-scale=1.0">
              <title>组件</title>
              <script src="js/vue2.js"></script>
          </head>
          
          <body>
          <div id="app" style="border: solid 1px red">
              <hello></hello>
              <hr>
              <!--第三步:渲染组件-->
              <school></school>
              <hr>
              <!--第三步:渲染组件-->
              <student></student>
          </div>
          <hr>
          <div id="test" style="border: solid 1px black">
              <hello></hello>
          </div>
          </body>
          <script>
              // 第一步:定义组件school和student
              const school = Vue.extend({
                  template:
                      `
                          <div>
                               <h2>这是school组件</h2>
                               <h2>{{name}}</h2>
                               <h2>{{address}}</h2>
                               <button @click="schoolFunction">点我</button>
                          </div>
                      `
                  ,
                  methods: {
                      schoolFunction() {
                          alert(this.name)
                      }
                  },
                  data() {
                      return {
                          name: "家里蹲",
                          address: "世界尽头"
                      }
                  }
              })
              const student = Vue.extend({
                  template:
                      `
                          <div>
                               <h2>这是student组件</h2>
                               <h2>{{name}}</h2>
                               <h2>{{age}}</h2>
                               <button @click="studentFunction">点我</button>
                          </div>
                      `
                  ,
                  methods: {
                      studentFunction() {
                          this.age++
                      }
                  },
                  data() {
                      return {
                          name: "曹李赖赖",
                          age: 18
                      }
                  }
              })
              const hello = Vue.extend({
                  template:
                      `
                          <div>
                               <h2>这是全局组件</h2>
                               <h2>{{age}}</h2>
                               <button @click="helloFunction">点我</button>
                          </div>
                      `
                  ,
                  methods: {
                      helloFunction() {
                          this.age++
                      }
                  },
                  data() {
                      return {
                          age: 18
                      }
                  }
              })
              // 第二步:注册逐渐(全局的)
              Vue.component('hello', hello)
              // 创建vue实例
              new Vue({
                  el: '#app',
                  // 第二步:注册逐渐(局部)
                  components: {
                      school: school,
                      student: student
                  }
              })
              new Vue({
                  el: '#test',
              })
          </script>
          
          </html>
          
        • Vue3 写法
          
          
      2. 单文件组件

        一个文件包含一个组件,文件后缀为 .vue 的文件,明规则首字母大,只支持脚手架使用

      3. 组件之间嵌套
        • Vue2 写法
          <!DOCTYPE html>
          <html lang="en">
          
          <head>
              <meta charset="UTF-8">
              <meta http-equiv="X-UA-Compatible" content="IE=edge">
              <meta name="viewport" content="width=device-width, initial-scale=1.0">
              <title>组件</title>
              <script src="js/vue2.js"></script>
              <style>
                  * {
                      margin: 0;
                      padding: 0;
                  }
              </style>
          </head>
          
          <body>
          <div id="app" style="border: solid 5px red;">
              <app></app>
          </div>
          
          </body>
          <script>
              const student = Vue.extend({
                  template:
                      `
                          <div>
                               <h2>这是student组件</h2>
                               <h2>{{name}}</h2>
                               <h2>{{age}}</h2>
                               <button @click="studentFunction">点我</button>
                          </div>
                      `
                  ,
                  methods: {
                      studentFunction() {
                          this.age++
                      }
                  },
                  data() {
                      return {
                          name: "曹李赖赖",
                          age: 18
                      }
                  }
              })
              const school = Vue.extend({
                  template:
                      `
                          <div style="background-color:yellow">
                               <h2>这是school组件</h2>
                               <h2>{{name}}</h2>
                               <h2>{{address}}</h2>
                               <button @click="schoolFunction">点我</button>
                               <student style="border: solid 1px red;background-color:#732097"></student>
                          </div>
                      `
                  ,
                  components: {
                      student: student
                  },
                  methods: {
                      schoolFunction() {
                          alert(this.name)
                      }
                  },
                  data() {
                      return {
                          name: "家里蹲",
                          address: "世界尽头"
                      }
                  }
              })
              const hello = Vue.extend({
                  template:
                      `
                          <div style="background-color: aqua">
                               <h2>这是hello组件</h2>
                               <h2>{{age}}</h2>
                               <button @click="helloFunction">点我</button>
                          </div>
                      `
                  ,
                  methods: {
                      helloFunction() {
                          this.age++
                      }
                  },
                  data() {
                      return {
                          age: 18
                      }
                  }
              })
              const app = Vue.extend({
                  template:
                      `
                          <div style="border:solid 1px black;margin: 5px">
                               <school></school>
                               <hello></hello>
                               <button @click="schoolFunction">点我</button>
                          </div>
                      `
                  ,
                  components: {
                      school: school,
                      hello: hello
                  },
                  methods: {
                      schoolFunction() {
                          alert("我是app组件")
                      }
                  }
              })
              // 创建vue实例
              new Vue({
                  el: '#app',
                  // 可以通过template实现渲染
                  // template:
                  //     `
                  //     <app></app>
                  //     `,
                  // 注册逐渐(局部)
                  components: {
                      app
                  }
              })
          
          </script>
          
          </html>
          
        • Vue3 写法
          
          
      4. 组件的民命规则
        • 一个单词组成的首字母大写或者首字母小写: Datadata
        • 多个单词组成的使用横杠间隔或者首字母大写: my-dataMyData
      5. Vue.component

        • 组件的本质是一个 Vue.component 构造函数,并不是程序自定义的,是 Vue.extend 生成的
        • 我们只需要写 <组件名称> 或者 <组件名称></组件名称>Vue 解析是会帮我们创建组件的实例对象,即 Vue 把我们执行: new Vuecomponent(options)
        • 特别注意:每次调用 Vue.extend ,返回的都是一个全新的 Vuecomponent
        • 关于 this 指向:
          1. 组件配置中:

            *data函数、methods*中的函数、 watch 中的函数、 computed 中的函数,它们的 this 均是 Vuecomponent 实例对象

          2. .new Vue(options) 配置中:

            *data函数、methods*中的函数、 watch 中的函数、 computed 中的函数,它们的 this 均是 Vue 实例对象

        • Vue.component 的实例对象,以后简称 vc

第九章、脚手架 —— Vue_CLI

  1. 怎么搭建脚手架

    • 官方脚手架网址:https://cli.vuejs.org/zh/

    • 通过 CMD 指令查看电脑是否安装脚手架: vue -V (安装了会出现脚手架版本)

    • 安装脚手架:

      CMD 执行 npm install -g @vue/cli 这个指令

    • 创建项目:

      1. 切换创建项目的目录,这一步很重要,这就是你项目的所在位置
      2. 执行指令:vue create 加你要创建的项目名称
      3. 选择对应的指令创建项目(这里我选择vue2,回车即可[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IslGitlW-1648022314901)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220317142200253.png)]
      4. 项目创建完成,这里出现 Successfully ,就说明了创建完成了 在这里插入图片描述
      5. 启动项目
        1. 执行 cd 你的项目名称
        2. 执行 npm run scrve
        3. 复制 Local 后面的地址用浏览器的开
        4. 打开后页面就下面的样子
        5. 用浏览篇的控制台里的 vue 插件1看看组件是否是这样的

        注意:cmd 窗口不要关闭,不然项目就关闭了

        在这里插入图片描述 在这里插入图片描述 在这里插入图片描述

第十章、ref属性

  1. 被用来给元素组件注册应用信息(ID的替代者)

  2. 应用在 HTML 标签上获取的是真实的 DOM 元素,应用在组件标签上是组件实例对象2

    <template>
        <div id="app">
            <h1 v-text="msg" ref="title"></h1>
            <button ref="button" @click="showDOM()">提示信息</button>
            <test ref="Text"/>
        </div>
    </template>
    
    <script>
        
        import test from "./components/test.vue";
    
        export default {
            name: 'App',
            components: {test},
            data() {
                return {
                    msg: "你好啊!"
                }
            },
            methods: {
                showDOM() {
                    console.log(this.$refs.title)//真实的DOM元素
                    console.log(this.$refs.button)//真实的DOM元素
                    console.log(this.$refs.Text)//组件的实例对象(VC)
                }
            }
        }
    </script>
    
    <style>
        * {
            margin: 0;
            padding: 0;
        }
    </style>
    

第十一章、props配置

让组件接受外部穿过来的数据

  1. 传递数据

    <test name="张三" :age="15" :sex="1"/>
    
  2. 接受数据

    1. 只接收

      <template>
          <div>
              <span>{{msg}}</span>
              <br>
              <span>学生名字:{{name}}</span>
              <br>
              <span>学生性别:{{sex === 1 ? "男" : "女"}}</span>
              <br>
              <span>学生年龄:{{myAge}}</span>
              <br>
              <button @click="UpDataAge">常识修改信息(控制台会报错)</button>
          </div>
      </template>
      
      <script>
          export default {
              data() {
                  return {
                      msg: "学生信息",
                      myAge: this.age
                  }
              },
              methods: {
                  // props传输的值是不能修改的,直接修改会报错,说以可以在data定义,因为props的优先级高于data
                  UpDataAge() {
                      this.myAge++
                  }
              },
              // 接收到的props是不能修改的
              props: ['name', 'sex', 'age', 'number'] ,//简单申明接收,
          }
      </script>
      
      <style>
      </style>
      
      
    2. 限制类型

      <template>
          <div>
              <span>{{msg}}</span>
              <br>
              <span>学生名字:{{name}}</span>
              <br>
              <span>学生性别:{{sex === 1 ? "男" : "女"}}</span>
              <br>
              <span>学生年龄:{{myAge}}</span>
              <br>
              <button @click="UpDataAge">常识修改信息(控制台会报错)</button>
          </div>
      </template>
      
      <script>
          export default {
              data() {
                  return {
                      msg: "学生信息",
                      myAge: this.age
                  }
              },
              methods: {
                  // props传输的值是不能修改的,直接修改会报错,说以可以在data定义,因为props的优先级高于data
                  UpDataAge() {
                      this.myAge++
                  }
              },        
              props: { //接受的同时对数据进行类型限制
                  name: String,
                  sex: Number,
                  age: Number
              },
          }
      </script>
      
      <style>
      </style>
      
      
    3. 限制类型、限制必要性、指定默认值

      <template>
          <div>
              <span>{{msg}}</span>
              <br>
              <span>学生名字:{{name}}</span>
              <br>
              <span>学生性别:{{sex === 1 ? "男" : "女"}}</span>
              <br>
              <span>学生年龄:{{myAge}}</span>
              <br>
              <button @click="UpDataAge">常识修改信息(控制台会报错)</button>
          </div>
      </template>
      
      <script>
          export default {
              data() {
                  return {
                      msg: "学生信息",
                      myAge: this.age
                  }
              },
              methods: {
                  // props传输的值是不能修改的,直接修改会报错,说以可以在data定义,因为props的优先级高于data
                  UpDataAge() {
                      this.myAge++
                  }
              },      
              props: { //接受的同时对数据进行类型限制,默认值的指定,必要性的限定
                  name: {
                      type: String,
                      required: true,
                  },
                  sex: {
                      type: Number,
                      required: true,
                  },
                  age: {
                      type: Number,
                      default: 0
                  }
              }
          }
      </script>
      
      <style>
      </style>
      
      

备注:

props 是只读的, Vue 底层监测你对 props 的修改,如果进行了修改,就会发出警告,若业务确实需要修改,那么请复制 props 的内容打 Data 中一份,然后去修改 Data 中的数据

第十二章、mixin配置——混入

可以把多个组件共用的配在提取成一个混入对象

  1. 局部混入

    1. 先定义一个 minxin.js 文件,内容如下3

      export const mixin = {
          methods: {
              ShowName() {
                  console.log(this.name)
              }
          },
          mounted() {
              console.log("执行了" + this.name)
          }
      }
      export const mixin2 = {
          data() {
              return {
                  new_Json: "Json"
      
              }
          }
      }
      
    2. 然后在组件里引用

      <template>
          <div class="Student">
              <h3 @click="ShowName">学生名字:{{name}}</h3>
              <h3>学生性别:{{sex}}</h3>
              <h3>{{new_Json}}</h3>
          </div>
      </template>
      
      <script>
          import {mixin} from "../mixin"
          import {mixin2} from "../mixin"
      
          export default {
              data() {
                  return {
                      name: "张三",
                      sex: "男"
                  }
              },
              mixins:[mixin,mixin2]
          }
      </script>
      
      <style>
          .Student {
              color: blue;
          }
      </style>
      
      
      <template>
          <div class="school">
              <h3 @click="ShowName">学校名字:{{name}}</h3>
              <h3>学校地址:{{address}}</h3>
              <h3>{{new_Json}}</h3>
          </div>
      </template>
      
      <script>
          import {mixin} from "../mixin"
          import {mixin2} from "../mixin"
      
          export default {
              data() {
                  return {
                      name: "家里蹲",
                      address: "世界尽头"
                  }
              },
              mixins: [mixin, mixin2]
          }
      </script>
      
      <style>
          .school {
              color: red;
          }
      </style>
      
      
  2. 全局混入

    1. 先定义一个 minxin.js 文件,内容如下3

      export const mixin = {
          methods: {
              ShowName() {
                  console.log(this.name)
              }
          },
          mounted() {
              console.log("执行了" + this.name)
          }
      }
      export const mixin2 = {
          data() {
              return {
                  new_Json: "Json"
      
              }
          }
      }
      
    2. main.js 里面添加几行代码

      // 引入通用的混合类
      import {mixin, mixin2} from './mixin'
      // 调用mixinf添加混合
      Vue.mixin(mixin)
      Vue.mixin(mixin2)
      
    3. 查看控制台是否成功,都出现红框内容说明成功了

      请添加图片描述 请添加图片描述 在这里插入图片描述 在这里插入图片描述

第十三章、插件4

加强Vue,包含 install 方法的一个对象, install 的第一个参数是 Vue ,第二个以后的参数是插件使用者传递的数据。

  • 自定义插件使用方式

    1. 先定义一个 plugins.js 5

      export default {
          install(Vue) {
              // 全局过滤器
              Vue.filter('mySlice', function (value) {
                  return value.slice(0, 5)
              })
              // 全局自定义指令
              Vue.directive('FBind', {
                  // 指令与元素成功绑定时
                  bind(element, binding) {
                      element.value = binding.value
                  },
                  // 指令所在元素被插入页面时
                  inserted(element) {
                      element.focus()
                  },
                  // 指令所在的模板被从新解析时
                  update(element, binding) {
                      element.value = binding.value
                  }
              })
              // 全局的混入
              Vue.mixin({
                  data() {
                      return {
                          new_Json: "Json"
                      }
                  }
              })
              // 给Vue原型上添加一个方法
              Vue.prototype.hello = () => {
                  console.log(123)
              }
          }
      }
      
    2. main.js 添加下面代码

      import plugins from './plugins'// 引入插件
      Vue.use(plugins)// 应用插件
      
    3. 在组件使用插件里添加的类(这里是在APP组件里使用)

      <template>
          <div id="app">
              <School/>
              <!--使用了插件的过滤器-->
              <h3> {{name | mySlice}}</h3>
              <!--使用了插件里的混入里面的数据-->
              <h3>mixin:{{new_Json}}</h3>
              <!-- 使用了插件的自定义指令-->
              <label>
                  <input type="text" v-FBind:value="name">
              </label>
              <button @click="test">{{name}}button</button>
          </div>
      </template>
      
      <script>
          import School from "./components/School";
      
          export default {
              name: 'App',
              components: {School},
              data() {
                  return {
                      name: "APP"
                  }
              },
              methods: {
                  test() {
                      // 使用了插件里自定义方法
                      this.hello()
                  }
              }
          }
      </script>
      
      <style>
          * {
              margin: 0;
              padding: 0;
          }
      </style>
      

第十四章、scoped 属性、less

  • scoped 的使用

    1. 简单定义两个组件并设置样式

      <template>
          <div class="bc">
              <h3>学生姓名:{{name}}</h3>
          </div>
      </template>
      
      <script>
          export default {
              data() {
                  return {
                      name: "张三"
                  }
              }
          }
      </script>
      
      <style scoped>
          .bc {
              background-color: blue;
          }
      </style>
      
      <template>
          <div class="bc">
              <h3>学校名称:{{name}}</h3>
              <div class="test">
                  <h3>test</h3>
              </div>
          </div>
      </template>
      
      <script>
      
          export default {
              data() {
                  return {
                      name: "家里蹲"
                  }
              }
          }
      </script>
      
      <style scoped lang="less">
          .bc {
              background-color: red;
      
              .test {
                  border: solid 1px #000000;
              }
          }
      </style>
      
    2. 查看效果 请添加图片描述

      发现虽然两个组件都设置不同的背景颜色,但是都变成相同的了,应为用了相同的 class 样式名,所以会用你最后引入的组件的样式,进行往前覆盖,我最后引入的是蓝色,说以全都是蓝色

    3. 使用 scoped

      用法:让样式局部生效,防止冲突

      写法:style 标签上面添加 scoped 即可

      <style scoped>
      

      请添加图片描述

      注意:

      app 里面添加 scoped 属无效的,因为 scoped 只会在局部生效在 app 设置是无意义的

  • less 的使用

    1. 在终端执行命令

      npm i less-loader@7
      
    2. 使用 less 6

      写法:style 标签上面添加 lang="less" 即可

      <style lang="less">
      

第十五章、 WebStorage

  • 存储内容大小一般支持在 5MB 左右7

  • 浏览器端通过 Window.sessionStorageWindow.localStorage 属性类实现本地储存机制

  • API

    • xxxxxxStorage.setItem('key','value')

      该方法接收一个键和值作为参数,会把键值添加到存储中,如果键名存在,则是更新对应的值

    • xxxxxxStorage.getItem('person')

      该方法接收一个键名作为参数,返回键名对应的值

    • xxxxxxStorage.removeItem('key')

      该方法接收一个键名作为参数,并把该键名从存储中删除

    • xxxxxxStorage.clear()

      该方法清空储存中的数据

  • 备注:

    • sessionStorage 存储的内容会随着浏览器关闭而消失
    • localStorage 存储的内容,需要手动清除才会消失
    • xxxxxxStorage.getItem('person') value 获取不到,那么返回值就是 null
  • 案例:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>浏览器本地存储</title>
    </head>
    <body>
    <h3>localStorage浏览器关闭还存储着数据</h3>
    <button onclick="SaveData()">保存浏览器本地数据</button>
    <button onclick="ReadData()">读取浏览器本地数据</button>
    <button onclick="DeleteData()">删除一条浏览器本地数据</button>
    <button onclick="DeleteAllData()">删除全部浏览器本地数据</button>
    <div id="box">
    </div>
    <script>
        function SaveData() {
            localStorage.setItem('str', '你好')
            localStorage.setItem('num', '123')
            // JSON.stringify显示obj类型数据
            localStorage.setItem('objs', JSON.stringify({name: '张三', age: '18'}))
            box = document.getElementById("box")
            span = document.createElement("span")
            br = document.createElement("br")
            span.innerText = '保存成功,请查看控制台'
            box.appendChild(span)
            box.appendChild(br)
        }
    
        function ReadData() {
            // 读取不到数据都是null
            box = document.getElementById("box")
            span = document.createElement("span")
            br = document.createElement("br")
            span.innerText = localStorage.getItem('str') + ',' + localStorage.getItem('num') + ',' + localStorage.getItem('objs')
            box.appendChild(span)
            box.appendChild(br)
        }
    
        function DeleteData() {
            localStorage.removeItem('str')
            box = document.getElementById("box")
            span = document.createElement("span")
            br = document.createElement("br")
            span.innerText = '删除成功,请查看控制台'
            box.appendChild(span)
            box.appendChild(br)
        }
    
        function DeleteAllData() {
            localStorage.clear()
            box = document.getElementById("box")
            span = document.createElement("span")
            br = document.createElement("br")
            span.innerText = '清除成功,请查看控制台'
            box.appendChild(span)
            box.appendChild(br)
        }
    </script>
    </body>
    </html>
    
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>浏览器本地会话</title>
    </head>
    <body>
    <h3>sessionStorage浏览器关闭时清空会话</h3>
    <button onclick="SaveData()">保存浏览器本地会话</button>
    <button onclick="ReadData()">读取浏览器本地会话</button>
    <button onclick="DeleteData()">删除一条浏览器本地会话</button>
    <button onclick="DeleteAllData()">删除全部浏览器本地会话</button>
    <div id="box">
    </div>
    <script>
        function SaveData() {
            sessionStorage.setItem('str', '你好')
            sessionStorage.setItem('num', '123')
            // JSON.stringify显示obj类型会话
            sessionStorage.setItem('objs', JSON.stringify({name: '张三', age: '18'}))
            box = document.getElementById("box")
            span = document.createElement("span")
            br = document.createElement("br")
            span.innerText = '保存成功,请查看控制台'
            box.appendChild(span)
            box.appendChild(br)
        }
    
        function ReadData() {
            // 读取不到会话都是null
            box = document.getElementById("box")
            span = document.createElement("span")
            br = document.createElement("br")
            span.innerText = sessionStorage.getItem('str') + ',' + sessionStorage.getItem('num') + ',' + sessionStorage.getItem('objs')
            box.appendChild(span)
            box.appendChild(br)
        }
    
        function DeleteData() {
            sessionStorage.removeItem('str')
            box = document.getElementById("box")
            span = document.createElement("span")
            br = document.createElement("br")
            span.innerText = '删除成功,请查看控制台'
            box.appendChild(span)
            box.appendChild(br)
        }
    
        function DeleteAllData() {
            sessionStorage.clear()
            box = document.getElementById("box")
            span = document.createElement("span")
            br = document.createElement("br")
            span.innerText = '清除成功,请查看控制台'
            box.appendChild(span)
            box.appendChild(br)
        }
    </script>
    </body>
    </html>
    
    

第十六章、组件的自定义事件

  1. 绑定

    1. 通过调用父组件方法实现向父组件传值

      • 父组件
        <template>
            <div id="app">
                <H3>{{msg}}</H3>
        
                <!--通过调用父组件方法实现向父组件传值-->
                <h3>这是学校传过来的数据:{{GetSchoolNameData}}</h3>
                <School :GetSchoolName="GetSchoolName" class="School"/>
            </div>
        </template>
        
        <script>
            
            import School from "./components/School";
        
            export default {
                name: 'App',
                components: {Student, School},
                data() {
                    return {
                        msg: "你好啊",
                        GetStudentNameData: "",
                        GetSchoolNameData: "",
                    }
                },
                methods: {
                    GetSchoolName(name) {
                        this.GetSchoolNameData = name
                        console.log(name)
                    }
                }  
            }
        </script>
        
        <style>
            * {
                margin: 0;
                padding: 0;
                color: white;
            }
        
            #app {
                background-color: grey;
                padding: 5px;
            }
        
            .School {
                background-color: aqua;
                margin-bottom: 5px;
            }
        </style>
        
      • 子组件
        <template>
            <div>
                <h3>学校名称:{{name}}</h3>
                <div>
                    <h3>test</h3>
                    <h3>{{GetSchoolName(name)}}</h3>
                </div>
            </div>
        </template>
        
        <script>
        
            export default {
                data() {
                    return {
                        name: "家里蹲"
                    }
                },
                // 使用 props 接收父组件过来的值
                props: ['GetSchoolName']
            }
        </script>
        
    2. 通过自定义事件向父组件传值

      1. 使用 v-on 绑定
        • 父组件
          <template>
              <div id="app">
                  <H3>{{msg}}</H3>      
                  <!--通过自定义事件向父组件传值-->
                  <!--使用 v-on-->
                  <h3>这是学生传过来的数据:{{GetStudentNameData}}</h3>
                  <!--<Student @StudentName="GetStudentName" class="Student"/>-->
          
                  <!--这种写法要想触发一次可以这样写-->
                  <Student @StudentName.once="GetStudentName" class="Student"/>
              </div>
          </template>
          
          <script>
          
              import Student from "./components/Student";    
          
              export default {
                  name: 'App',
                  components: {Student, School},
                  data() {
                      return {
                          msg: "你好啊",
                          GetStudentNameData: "",
                          GetSchoolNameData: "",
                      }
                  },
                  methods: {            
                      GetStudentName(name) {
                          this.GetStudentNameData = name
                          console.log(name)
                      }
                  }
              }
          </script>
          
          <style>
              * {
                  margin: 0;
                  padding: 0;
                  color: white;
              }
          
              #app {
                  background-color: grey;
                  padding: 5px;
              }    
          
              .Student {
                  background-color: pink;
              }
          </style>
          
        • 子组件
          <template>
              <div>
                  <h3>学生姓名:{{name}}</h3>
                  <button @click="Send">按钮</button>
              </div>
          </template>
          
          <script>
              export default {
                  data() {
                      return {
                          name: "张三"
                      }
                  },
                  methods: {
                      Send() {
                          this.$emit('StudentName', this.name)
                      }
                  }
              }
          </script>
          
      2. 使用 ref 绑定
        • 父组件
          <template>
              <div id="app">
                  <H3>{{msg}}</H3>
                  <!--使用 ref (可以灵活使用)-->
                  <Student ref="StudentData" class="Student"/>
              </div>
          </template>
          
          <script>
          
              import Student from "./components/Student";
              import School from "./components/School";
          
              export default {
                  name: 'App',
                  components: {Student, School},
                  data() {
                      return {
                          msg: "你好啊",
                          GetStudentNameData: "",
                          GetSchoolNameData: "",
                      }
                  },
                  methods: {           
                      GetStudentName(name) {
                          this.GetStudentNameData = name
                          console.log(name)
                      }
                  },
                  mounted() {
                      // 可以重复触发(配合第二种写法)
                      this.$refs.StudentData.$on('StudentName', this.GetStudentName)
                      // 只触发一次(配合第二种写法)
                      // this.$refs.StudentData.$once('StudentName', this.GetStudentName)
                  }
              }
          </script>
          
          <style>
              * {
                  margin: 0;
                  padding: 0;
                  color: white;
              }
          
              #app {
                  background-color: grey;
                  padding: 5px;
              }
          
              .School {
                  background-color: aqua;
                  margin-bottom: 5px;
              }
          
              .Student {
                  background-color: pink;
              }
          </style>
          
          
        • 子组件
          <template>
              <div>
                  <h3>学生姓名:{{name}}</h3>
                  <button @click="Send">按钮</button>
              </div>
          </template>
          
          <script>
              export default {
                  data() {
                      return {
                          name: "张三"
                      }
                  },
                  methods: {
                      Send() {
                          this.$emit('StudentName', this.name)
                      }
                  }
              }
          </script>
          
  2. 解绑

    <template>
        <div>
            <h3>学生姓名:{{name}}</h3>
            <button @click="Send">按钮</button>
            <button @click="UnSend">按钮</button>
        </div>
    </template>
    
    <script>
        export default {
            data() {
                return {
                    name: "张三"
                }
            },
            methods: {
                Send() {
                    this.$emit('StudentName', this.name)
                    this.$emit('StudentName1', this.name)
                },
                UnSend() {
                    // 解绑单个事件
                    // this.$off('StudentName')
                    // 解绑多个事件
                    // this.$off(['StudentName', 'StudentName1'])
                    // 解绑全部事件
                    this.$off()
                }
            }
        }
    </script>
    

第十七章、全局事件总线

一种组件通信的方式,使用与任意组件通讯

按装全局事件总线:在 Main.jsVue 的实例对象添加如下代码

// 创建Vue实例对象
new Vue({    
 // 定义全局事件总线
 beforeCreate() {
     Vue.prototype.$bus = this
 }
}).$mount('#app')

使用事件总线:

  1. 接收数据:组件一想接收数据,则在组件一中给 $bus 绑定自定义事件,事件的回调留在组件一自身

    mounted() {
         // 接收数据
         this.$bus.$on('事件名', (value) => {
             //方法体
         })            
    },
    
  2. 提供数据:

    this.$bus.$emit('事件名', person)
    
  3. 解绑$bus在这个组件的自定义事件一定要添加

    beforeDestroy() {
        // TODO 解绑$bus在这个组件的自定义事件 一定要添加
        this.$bus.$off(['事件1', '事件2'])
        }
    

第十八章、消息订阅和发布-- pubsub.js 的使用8

一种组件通信的方式,使用与任意组件间通信

使用步骤:

  1. 安装

    npm i pubsub-js
    
  2. 引入

    import pubsub from 'pubsub-js'
    
  3. 接收数据

    mounted() {
        // msgName事件名称
        // data数据
        this.pubId = pubsub.subscribe('Student', (msgName, data) => {
           console.log("收到消息订阅", msgName, data)
        })
    }
    
  4. 提供数据

    methods: {
        sendStudentName() {
            // pubsub.publish(事件名称,数据)
            pubsub.publish('Student', 213)
        }
    }
    
  5. 解绑

    beforeDestroy() {
        // 解绑
        pubsub.unsubscribe(this.pubId)
    }
    

第十九章、


  1. 插件名称:Vue.js devtools ,要翻墙也有不翻墙的CSDN找一下 ↩︎

  2. Vuecomponent 对象 ↩︎

  3. 假设两个组件都要有个方法提示标题 ↩︎ ↩︎

  4. Vue.ses() ↩︎

  5. 文件名可以叫 某某.JS 不一定是 plugins ↩︎

  6. 具体使用就不过多说明了,后面会出一期细说的 ↩︎

  7. 浏览器不同大小不一样 ↩︎

  8. 第三方库 ↩︎

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值