Vue3基础笔记(一)

本文是Vue3的基础笔记,介绍了Vue的渐进式特性、TypeScript重写、Proxy数据劫持和一些API的变化。讲解了Vue的安装、使用、生命周期以及MVVM模式。探讨了template写法和注意事项,包括methods中箭头函数的问题。此外,还涵盖了Vue3的基础语法,如插值表达式、v-bind和事件绑定v-on,以及它们的不同用法和修饰符。
摘要由CSDN通过智能技术生成

跟着 coderwhy老师学习的

邂逅Vuejs

认识Vuejs

  • Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架
  • 什么是渐进式框架呢?表示我们可以在项目中一点点来引入和使用Vue,而不一定需要全部使用Vue来开发整个

    项目;

  • 源码使用TypeScript来进行重写:

    在Vue2.x的时候,Vue使用Flow来进行类型检测;

    在Vue3.x的时候,Vue的源码全部使用TypeScript来进行重构,并且Vue本身对TypeScript支持也更好了;

  • 使用Proxy进行数据劫持

  • 删除了一些不必要的API:

    移除了实例上的$on, $off 和 $once;

    移除了一些特性:如filter、内联模板等;

  • 包括编译方面的优化:

    生成Block Tree、Slot编译优化、diff算法优化;

  • 由Options API 到 Composition API:

    在Vue2.x的时候,我们会通过Options API来描述组件对象;

    Options API包括data、props、methods、computed、生命周期等等这些选项;

    存在比较大的问题是多个逻辑可能是在不同的地方:

    比如created中会使用某一个method来修改data的数据,代码的内聚性非常差;

    Composition API可以将 相关联的代码 放到同一处 进行处理,而不需要在多个Options之间寻找;

  • Hooks函数增加代码的复用性:

    在Vue2.x的时候,我们通常通过mixins在多个组件之间共享逻辑;

    但是有一个很大的缺陷就是 mixins也是由一大堆的Options组成的,并且多个mixins会存在命名冲突的问题;

    在Vue3.x中,我们可以通过Hook函数,来将一部分独立的逻辑抽取出去,并且它们还可以做到是响应式的;

安装vue

1.CDN引入

<script src="https://unpkg.com/vue@next"></script>

2.下载引入

下载Vue的源码,可以直接打开CDN的链接:

打开链接,复制其中所有的代码;

创建一个新的文件,比如vue.js,将代码复制到其中;

3.npm安装

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

Vue的使用

<div id="app">
    <h2>Hello World</h2>
  </div>

  <script src="https://unpkg.com/vue@next"></script>
  <script>
    const why = {
      template: '<h2>Hello World</h2>'
    }

    const app = Vue.createApp(why);
    app.mount("#app")
  </script>

vue的生命周期/MVVM

  • MVC和MVVM都是一种软件的体系结构

    MVC是Model – View –Controller的简称,是在前期被使用非常框架的架构模式,比如iOS、前端;

    MVVM是Model-View-ViewModel的简称,是目前非常流行的架构模式;

  • 通常情况下,我们也经常称Vue是一个MVVM的框架。

    Vue官方其实有说明,Vue虽然并没有完全遵守MVVM的模型,但是整个设计是受到它的启发的。

template写法

<script type="x-template" id="why">
    <div>
      <h2>{{message}}</h2>
      <h2>{{counter}}</h2>
      <button @click='increment'>+1</button>
      <button @click='decrement'>-1</button>
    </div>
  </script>
<template id="why">
    <div>
      <h2>{{message}}</h2>
      <h2>{{counter}}</h2>
      <button @click='increment'>+1</button>
      <button @click='decrement'>-1</button>
      <button @click="btnClick">按钮</button>
    </div>
  </template>

注意点

  1. methods 里面的方法 为什么不能写成箭头函数?

    写成箭头函数以后,就会找上层的作用域,上层的作用域就是 script 指向的就是 window

    ​ vue3.x 中,this不再是指向的 实例,而是一个 proxy

  2. vscode 新建代码片段

    具体的步骤如下:

    第一步,复制自己需要生成代码片段的代码;

    第二步,https://snippet-generator.app/在该网站中生成代码片段;

    第三步,在VSCode中配置代码片段;

基础语法

插值表达式(胡子语法|插值语法等)

<div id="app"></div>

  <template id="my-app">
    <!-- 1.mustache的基本使用 -->
    <h2>{{message}} - {{message}}</h2>
    <!-- 2.是一个表达式 -->
    <h2>{{counter * 10}}</h2>
    <h2>{{ message.split(" ").reverse().join(" ") }}</h2>
    <!-- 3.也可以调用函数 -->
    <!-- 可以使用computed(计算属性) -->
    <h2>{{getReverseMessage()}}</h2>
    <!-- 4.三元运算符 -->
    <h2>{{ isShow ? "哈哈哈": "" }}</h2>
    <button @click="toggle">切换</button>

    <!-- 错误用法 -->
    <!-- var name = "abc" -> 赋值语句 -->
    <!-- <h2>{{var name = "abc"}}</h2>
    <h2>{{ if(isShow) {  return "哈哈哈" } }}</h2> -->
  </template>

  <script src="../js/vue.js"></script>
  <script>
    const App = {
      template: '#my-app',
      data() {
        return {
          message: "Hello World",
          counter: 100,
          isShow: true
        }
      },
      methods: {
        getReverseMessage() {
          return this.message.split(" ").reverse().join(" ");
        },
        toggle() {
          this.isShow = !this.isShow;
        }
      }
    }

    Vue.createApp(App).mount('#app');
  </script>

插值操作

  • v-once:
    该指令后面不需要跟任何表达式(比如之前的v-for后面是由跟表达式的)
    该指令表示元素和组件(组件后面才会学习)只渲染一次,不会随着数据的改变而改变,性能优化。
<div id="app"></div>

  <template id="my-app">
    <h2>{{counter}}</h2>
    <div v-once>
      <!-- 这两个 h2 标签是 div 的子元素,所以他俩都不会再重新渲染 -->
      <h2>{{counter}}</h2>
      <h2>{{message}}</h2>
    </div>
    <button @click="increment">+1</button>
  </template>

  <script src="../js/vue.js"></script>
  <script>
    const App = {
      template: '#my-app',
      data() {
        return {
          counter: 100,
          message: "abc"
        }
      },
      methods: {
        increment() {
          this.counter++;
        }
      }
    }

    Vue.createApp(App).mount('#app');
  </script>
  • v-text v-html v-pre 数据填充的三个指令:

1、v-text 填充纯文本

2、v-html 填充HTML片段

如果我们展示的内容 本身 是 html 的,那么 vue 并不会进行 特殊的解析,
如果我们希望解析这个内容,则可以 给他加一个 v-html 指令

3、v-pre 填充原始信息

显示原始信息,跳过编译过程

<div id="app"></div>

  <template id="my-app">
    <h2 v-text="message"></h2>
    <!-- 等价于下面的代码 -->
    <h2>{{message}}</h2>
    <div>{{msg}}</div>
    <div v-html="msg"></div>
    <h2 v-pre>{{message}}</h2>
    <!-- 这里最后会  输出  {{message}} -->
  </template>

  <script src="../js/vue.js"></script>
  <script>
    const App = {
      template: '#my-app',
      data() {
        return {
          message: "Hello World",
          msg: '<span style="color:red; background: blue;">哈哈哈</span>'
        }
      }
    }

    Vue.createApp(App).mount('#app');
  </script>
  • v-cloak:

    v-cloak指令用法

    插值表达式存在的问题:“ 闪动 ”

    如何解决此问题:使用 v-cloak 指令

    解决此问题的原理:先隐藏,替换好值之后再显示最终的值

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <style>
    [v-cloak] {
      display: none;
    }
  </style>
</head>

<body>
<div id="app"></div>

  <template id="my-app">
    <h2 v-cloak>{{message}}</h2>
  </template>

  <script src="../js/vue.js"></script>
  <script>
    const App = {
      template: '#my-app',
      data() {
        return {
          message: "Hello World"
        }
      }
    }

    Vue.createApp(App).mount('#app');
  </script>

</body>

</html>

v-bind

  • v-bind控制标签属性

    v-bind指令,让普通的标签属性的值为 data中的属性名
    v-bind指令简写为冒号

    动态的绑定一个或者多个属性也是可以的

<!-- vue2 template模板中只能有一个根元素 -->
  <!-- vue3 是允许template中有多个根元素 -->
  <template id="my-app">
    <!-- 1.v-bind的基本使用 -->
    <img v-bind:src="imgUrl" alt="">
    <a v-bind:href="link">百度一下</a>

    <!-- 2.v-bind提供一个语法糖 : -->
    <img :src="imgUrl" alt="">
    <img src="imgUrl" alt="">
  </template>

v-bind动态绑定class(对象)

<div id="app"></div>

    <template id="my-app">
      <div :class="className">哈哈哈哈</div>
      <!-- 对象语法: {'active': boolean} -->
      <div :class="{'active': isActive}">呵呵呵呵</div>
      <button @click="toggle">切换</button>

      <!-- 也可以有多个键值对 -->
      <div :class="{active: isActive, title: true}">呵呵呵呵</div>

      <!-- 默认的class和动态的class结合 -->
      <div class="abc cba" :class="{active: isActive, title: true}">
        呵呵呵呵
      </div>

      <!-- 将对象放到一个单独的属性中 -->
      <div class="abc cba" :class="classObj">呵呵呵呵</div>

      <!-- 将返回的对象放到一个methods(computed)方法中 -->
      <div class="abc cba" :class="getClassObj()">呵呵呵呵</div>      
    </template>

    <script src="../js/vue.js"></script>
    <script>
      const App = {
        template: "#my-app",
        data() {
          return {
            className: "why",
            isActive: true,
            title: "abc",
            classObj: { 
              active: true, 
              title: true 
            },
          };
        },
        methods: {
          toggle() {
            this.isActive = !this.isActive;
          },
          getClassObj() {
            return { 
              active: true, 
              title: true 
            }
          }
        },
      };

      Vue.createApp(App).mount("#app");
    </script>

v-bind动态绑定class(数组)

<div id="app"></div>

  <template id="my-app">
    <div :class="['abc', title]">哈哈哈哈</div>
    <div :class="['abc', title, isActive ? 'active': '']">哈哈哈哈</div>
    <div :class="['abc', title, {active: isActive}]">哈哈哈哈</div>
  </template>

  <script src="../js/vue.js"></script>
  <script>
    const App = {
      template: '#my-app',
      data() {
        return {
          message: "Hello World",
          title: "cba",
          isActive: true
        }
      }
    }

    Vue.createApp(App).mount('#app');
  </script>

v-bind动态绑定style(对象)

<div id="app"></div>

  <template id="my-app">
    <!-- :style="{cssPropertyName: cssPropertyValue}" -->
    <div :style="{color: finalColor, 'font-size': '30px'}">哈哈哈哈</div>
    <div :style="{color: finalColor, fontSize: '30px'}">哈哈哈哈</div>
    <div :style="{color: finalColor, fontSize: finalFontSize + 'px'}">哈哈哈哈</div>

    <!-- 绑定一个data中的属性值, 并且是一个对象 -->
    <div :style="finalStyleObj">呵呵呵呵</div>
    <!-- 调用一个方法 -->
    <div :style="getFinalStyleObj()">呵呵呵呵</div>
  </template>

  <script src="../js/vue.js"></script>
  <script>
    const App = {
      template: '#my-app',
      data() {
        return {
          message: "Hello World",
          finalColor: 'red',
          finalFontSize: 50,
          finalStyleObj: {
            'font-size': '50px',
            fontWeight: 700,
            backgroundColor: 'red'
          }
        }
      },
      methods: {
        getFinalStyleObj() {
          return {
            'font-size': '50px',
            fontWeight: 700,
            backgroundColor: 'red'
          }
        }
      }
    }

    Vue.createApp(App).mount('#app');
  </script>

v-bind动态绑定style(数组)

<div id="app"></div>

  <template id="my-app">
    <div :style="[style1Obj, style2Obj]">哈哈哈</div>
    <img :src="" alt="">
    <a :href=""></a>
    <div :class></div>
  </template>

  <script src="../js/vue.js"></script>
  <script>
    const App = {
      template: '#my-app',
      data() {
        return {
          message: "Hello World",
          style1Obj: {
            color: 'red',
            fontSize: '30px'
          },
          style2Obj: {
            textDecoration: "underline"
          }
        }
      }
    }

    Vue.createApp(App).mount('#app');
  </script>

v-bind动态绑定属性名称

<div id="app"></div>

  <template id="my-app">
    <div :[name]="value">哈哈哈</div>
  </template>

  <script src="../js/vue.js"></script>
  <script>
    const App = {
      template: '#my-app',
      data() {
        return {
          name: "cba",
          value: "kobe"
        }
      }
    }

    Vue.createApp(App).mount('#app');
  </script>

v-bind属性直接绑定一个对象

<div id="app"></div>

  <template id="my-app">
    <div v-bind="info">哈哈哈哈</div>
    <div :="info">哈哈哈哈</div>
  </template>

  <script src="../js/vue.js"></script>
  <script>
    const App = {
      template: '#my-app',
      data() {
        return {
          info: {
            name: "why",
            age: 18,
            height: 1.88
          }
        }
      }
    }

    Vue.createApp(App).mount('#app');
  </script>

事件绑定v-on

v-on:事件名=“事件函数名或者处理程序”

修饰符

.stop - 调用 event.stopPropagation()。
.prevent - 调用 event.preventDefault()。
.capture - 添加事件侦听器时使用 capture 模式。
.self - 只当事件是从侦听器绑定的元素本身触发时才触发回调。
.{keyAlias} - 仅当事件是从特定键触发时才触发回调。
.once - 只触发一次回调。
.left - 只当点击鼠标左键时触发。
.right - 只当点击鼠标右键时触发。
.middle - 只当点击鼠标中键时触发。
.passive - { passive: true } 模式添加侦听器

基本使用

  <style>
    .area {
      width: 200px;
      height: 200px;
      background: red;
    }
  </style>
</head>
<body>
  
  <div id="app"></div>

  <template id="my-app">
    <!-- 完整写法: v-on:监听的事件="methods中方法" -->
    <button v-on:click="btn1Click">按钮1</button>
    <div class="area" v-on:mousemove="mouseMove">div</div>
    <!-- 语法糖 -->
    <button @click="btn1Click">按钮1</button>
    <!-- 绑定一个表达式: inline statement -->
    <button @click="counter++">{{counter}}</button>
    <!-- 绑定一个对象 -->
    <div class="area" v-on="{click: btn1Click, mousemove: mouseMove}"></div>
    <div class="area" @="{click: btn1Click, mousemove: mouseMove}"></div>
  </template>

  <script src="../js/vue.js"></script>
  <script>
    const App = {
      template: '#my-app',
      data() {
        return {
          message: "Hello World",
          counter: 100
        }
      },
      methods: {
        btn1Click() {
          console.log("按钮1发生了点击");
        },
        mouseMove() {
          console.log("鼠标移动");
        }
      }
    }

    Vue.createApp(App).mount('#app');
  </script>

参数传递

  <template id="my-app">
    <!-- 默认传入event对象, 可以在方法中获取 -->
    <button @click="btn1Click">按钮1</button>
    <!-- $event可以获取到事件发生时的事件对象 -->
    <button @click="btn2Click($event, 'coderwhy', 18)">按钮2</button>
  </template>

  <script src="../js/vue.js"></script>
  <script>
    const App = {
      template: '#my-app',
      data() {
        return {
          message: "Hello World"
        }
      },
      methods: {
        btn1Click(event) {
          console.log(event);
        },
        btn2Click(event, name, age) {
          console.log(name, age, event);
        }
      }
    }

    Vue.createApp(App).mount('#app');
  </script>

事件修饰符

  <template id="my-app">
    <div @click="divClick">
      <button @click.stop="btnClick">按钮</button>
    </div>
    <input type="text" @keyup.enter="enterKeyup">
  </template>

  <script src="../js/vue.js"></script>
  <script>
    const App = {
      template: '#my-app',
      data() {
        return {
          message: "Hello World"
        }
      },
      methods: {
        divClick() {
          console.log("divClick");
        },
        btnClick() {
          console.log('btnClick');
        },
        enterKeyup(event) {
          console.log("keyup", event.target.value);
        }
      }
    }

    Vue.createApp(App).mount('#app');
  </script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值