Loading

♠ vue 模版语法、vue3变化

Vue3带来的变化(性能)

使用Proxy进行数据劫持

  • 在Vue2.x的时候,Vue2是使用Object.defineProperty来劫持数据的getter和setter方法的;
  • 这种方式一致存在一个缺陷就是当给对象添加或者删除属性时,是无法劫持和监听的;
  • 所以在Vue2.x的时候,不得不提供一些特殊的API,比如$set或$delete,事实上都是一些hack方法,也增加了开发者学习新的API的成本;
  • 而在Vue3.x开始,Vue使用Proxy来实现数据的劫持;

删除了一些不必要的API:

  • 移除了实例上的$on, $off 和 $once;
  • 移除了一些特性:如filter、内联模板等;

包括编译方面的优化:

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

Vue3带来的变化(新的API)

由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的对比

查看代码
<!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>Document</title>
  </head>
  <body>
    <h2 class="counter">0</h2>
    <button class="increment">+1</button>
    <button class="decrement">-1</button>

    <script>
      // 1.获取所有的元素
      const counterEl = document.querySelector(".counter");
      const incrementEl = document.querySelector(".increment");
      const decrementEl = document.querySelector(".decrement");

      // 2.定义变量
      let counter = 100;
      counterEl.innerHTML = counter;

      // 3.监听按钮的点击
      incrementEl.addEventListener("click", () => {
        counter += 1;
        counterEl.innerHTML = counter;
      });
      decrementEl.addEventListener("click", () => {
        counter -= 1;
        counterEl.innerHTML = counter;
      });
    </script>
  </body>
</html>
查看代码
<!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>Document</title>
</head>
<body>
  
  <div id="app">哈哈哈哈啊</div>

  <script src="../js/vue.js"></script>
  <script>
    Vue.createApp({
      //不使用'',使用模版字符串,模版字符串可以换行
      template: `
        <div>
          <h2>{{message}}</h2>
          <h2>{{counter}}</h2>
          <button @click='increment'>+1</button>
          <button @click='decrement'>-1</button>
        </div>
      `,
      //VUE2是可以返回{}, vue3需要返回 function
      data: function() {
        return {
          //这些数据可以加入到vue的响应式系统(在模版中使用)
          message: "Hello World",
          counter: 100
        }
      },
      // 定义各种各样的方法
      methods: {
        increment() {
          console.log("点击了+1");
          this.counter++;
        },
        decrement() {
          console.log("点击了-1");
          this.counter--;
        }
      }
    }).mount('#app');
  </script>
</body>
</html>

声明式和命令式

原生开发和Vue开发的模式和特点,我们会发现是完全不同的,这里其实涉及到两种不同的编程范式

  • 命令式编程和声明式编程;
  • 命令式编程关注的是 “how to do”,声明式编程关注的是 “what to do”,由框架(机器)完成 “how”的过程;

在原生的实现过程中,我们是如何操作的呢?

  • 我们每完成一个操作,都需要通过JavaScript编写一条代码,来给浏览器一个指令;
  • 这样的编写代码的过程,我们称之为命令式编程;
  • 在早期的原生JavaScript和jQuery开发的过程中,我们都是通过这种命令式的方式在编写代码的;

在Vue的实现过程中,我们是如何操作的呢?

  • 我们会在createApp传入的对象中声明需要的内容,模板template、数据data、方法methods;
  • 这样的编写代码的过程,我们称之为是声明式编程;
  • 目前Vue、React、Angular的编程模式,我们称之为声明式编程;

MVVM模型

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

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

通常情况下,我们也经常称Vue是一个MVVM的框架。Vue官方其实有说明,Vue虽然并没有完全遵守MVVM的模型,但是整个设计是受到它的启发的。

template属性

 

在使用createApp的时候,我们传入了一个对象,接下来我们详细解析一下之前传入的属性分别代表什么含义。

template属性:表示的是Vue需要帮助我们渲染的模板信息:

  • 目前我们看到它里面有很多的HTML标签,这些标签会替换掉我们挂载到的元素(比如id为app的div)的innerHTML;
  • 模板中有一些奇怪的语法,比如 {{}},比如 @click,这些都是模板特有的语法;

但是这个模板的写法有点过于别扭了,并且IDE很有可能没有任何提示,阻碍我们编程的效率。

Vue提供了两种方式:

方式一:使用script标签,并且标记它的类型为 x-template;

方式二:使用任意标签(通常使用template标签,因为不会被浏览器渲染),设置id;

template元素是一种用于保存客户端内容的机制,该内容再加载页面时不会被呈现,但随后可以在运行时使用JavaScript实例化;

这个时候,在createApp的对象中,我们需要传入的template以 # 开头:如果字符串是以 # 开始,那么它将被用作 querySelector,并且使用匹配元素的 innerHTML 作为模板字符串;

查看代码
<!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>Document</title>
</head>
<body>
  
  <div id="app">哈哈哈哈啊</div>

  <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>

  <script src="../js/vue.js"></script>
  <script>
    //document.querySelector("#why")
    Vue.createApp({
      template: '#why',
      data: function() {
        return {
          message: "Hello World",
          counter: 100
        }
      },
      // 定义各种各样的方法
      methods: {
        increment() {
          console.log("点击了+1");
          this.counter++;
        },
        decrement() {
          console.log("点击了-1");
          this.counter--;
        }
      }
    }).mount('#app');
  </script>
</body>
</html>
<!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>Document</title>
</head>
<body>
  
  <div id="app"></div>

  <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>

  <script src="../js/vue.js"></script>
  <script>
    document.querySelector("#why")
    Vue.createApp({
      template: '#why',
      data: function() {
        return {
          message: "Hello World",
          counter: 100
        }
      },
      // 定义各种各样的方法
      methods: {
        // es6增强写法
        increment() {
          console.log("点击了+1");
          this.counter++;
        },
        decrement() {
          console.log("点击了-1");
          this.counter--;
        },
        btnClick: () => {
          // this === window? 不可以
          // 写成一个箭头函数时, 这个this就是window
          // 在箭头函数中是不绑定this, 但是函数中如果使用了this
          console.log(this);
        },
        btn2Click: function() {
          // this === window? 不可以
          // 写成一个箭头函数时, 这个this就是window
          // 在箭头函数中是不绑定this, 但是函数中如果使用了this
          //会一层一层向上找,{}并不是作用域,一直找到<script>
          console.log(this);
        }
      }
    }).mount('#app');

  </script>
</body>
</html>

data属性

data属性是传入一个函数,并且该函数需要返回一个对象:

  • 在Vue2.x的时候,也可以传入一个对象(虽然官方推荐是一个函数);
  • 在Vue3.x的时候,必须传入一个函数,否则就会直接在浏览器中报错;

data中返回的对象会被Vue的响应式系统劫持,之后对该对象的修改或者访问都会在劫持中被处理:

  • 所以我们在template中通过 {{counter}} 访问counter,可以从对象中获取到数据;
  • 所以我们修改counter的值时,template中的 {{counter}}也会发生改变;

methods属性

methods属性是一个对象,通常我们会在这个对象中定义很多的方法:

这些方法可以被绑定到 template 模板中;在该方法中,我们可以使用this关键字来直接访问到data中返回的对象的属性;

 

模板语法

React的开发模式:

  • React使用的jsx,所以对应的代码都是编写的类似于js的一种语法;
  • 之后通过Babel将jsx编译成 React.createElement 函数调用;

Vue也支持jsx的开发模式(后续有时间也会讲到):

  • 但是大多数情况下,使用基于HTML的模板语法;
  • 在模板中,允许开发者以声明式的方式将DOM和底层组件实例的数据绑定在一起;
  • 在底层的实现中,Vue将模板编译成虚拟DOM渲染函数;

Mustache双大括号语法

如果我们希望把数据显示到模板(template)中,使用最多的语法是 “Mustache”语法 (双大括号) 的文本插值。

  • 并且我们前mian提到过,data返回的对象是有添加到Vue的响应式系统中;
  • 当data中的数据发生改变时,对应的内容也会发生更新。
  • 当然,Mustache中不仅仅可以是data中的属性,也可以是一个JavaScript的表达式。
查看代码
<!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>Document</title>
</head>
<body>
  
  <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>
</body>
</html>

v-once指令

v-once用于指定元素或者组件只渲染一次:

  • 当数据发生变化时,元素或者组件以及其所有的子元素将视为静态内容并且跳过;
  • 该指令可以用于性能优化

如果是子节点,也是只会渲染一次:

v-html

默认情况下,如果我们展示的内容本身是 html 的,那么vue并不会对其进行特殊的解析。如果我们希望这个内容被Vue可以解析出来,那么可以使用 v-html 来展示;

v-pre

v-pre用于跳过元素和它的子元素的编译过程,显示原始的Mustache标签:跳过不需要编译的节点,加快编译的速度;

v-cloak

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

v-bind的绑定属性

前端讲的一系列指令,主要是将值插入到模板内容中。但是,除了内容需要动态来决定外,某些属性我们也希望动态来绑定

  • 比如动态绑定a元素的href属性;
  • 比如动态绑定img元素的src属性;

绑定属性我们使用v-bind:

  • 缩写::
  • 预期:any (with argument) | Object (without argument)
  • 参数:attrOrProp (optional)
  • 修饰符
  • camel - 将 kebab-case attribute 名转换为 camelCase。
  • 用法:动态地绑定一个或多个 attribute,或一个组件 prop 到表达式。
查看代码
<!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>Document</title>
</head>
<body>
  
  <div id="app"></div>

  <!-- 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>

  <script src="../js/vue.js"></script>
  <script>
    const App = {
      template: '#my-app',
      data() {
        return {
          imgUrl: "https://pic.cnblogs.com/avatar/2604179/20211027110339.png",
          link: "https://www.baidu.com"
        }
      }
    }

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

绑定class介绍

在开发中,有时候我们的元素class也是动态的,比如:

  • 当数据为某个状态时,字体显示红色。
  • 当数据另一个状态时,字体显示黑色。

绑定class有两种方式:

  • 对象语法
  • 数组语法

对象

查看代码
<!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>Document</title>
    <style>
      .active {
        color: red;
      }
    </style>
  </head>
  <body>
    <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, //不能写isActive,不可以相互引用
              title: true 
            },
          };
        },
        methods: {
          toggle() {
            this.isActive = !this.isActive;
          },
          getClassObj() {
            return { 
              active: true, 
              title: true 
            }
          }
        },
      };

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

 

数组 

查看代码
<!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>Document</title>
</head>
<body>
  
  <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>
</body>
</html>

绑定style介绍

我们可以利用v-bind:style来绑定一些CSS内联样式:

  • 这次因为某些样式我们需要根据数据动态来决定;
  • 比如某段文字的颜色,大小等等;
  • CSS property 名可以用驼峰式 (camelCase) 或短横线分隔 (kebab-case,记得用引号括起来) 来命名;

绑定class有两种方式:

  • 对象语法
  • 数组语法

对象

 

查看代码
<!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>Document</title>
</head>
<body>
  
  <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>
</body>
</html>

数组

查看代码
<!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>Document</title>
</head>
<body>
  
  <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>
</body>
</html>

动态绑定属性

在某些情况下,我们属性的名称可能也不是固定的:

前端我们无论绑定src、href、class、style,属性名称都是固定的;如果属性名称不是固定的,我们可以使用 :[属性名]=“值” 的格式来定义;这种绑定的方式,我们称之为动态绑定属性;

绑定一个对象

如果我们希望将一个对象的所有属性,绑定到元素上的所有属性,应该怎么做呢?非常简单,我们可以直接使用 v-bind 绑定一个 对象;

案例:info对象会被拆解成div的各个属性

v-on绑定事件

前面我们绑定了元素的内容和属性,在前端开发中另外一个非常重要的特性就是交互。

在前端开发中,我们需要经常和用户进行各种各样的交互:

  • 这个时候,我们就必须监听用户发生的事件,比如点击、拖拽、键盘事件等等
  • 在Vue中如何监听事件呢?使用v-on指令。
查看代码
<!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>Document</title>

  <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>
</body>
</html>   

v-on的使用:

缩写:@

预期:Function | Inline Statement | Object

参数:event

修饰符

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

用法:绑定事件监听

v-on的基本使用

查看代码
<!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>Document</title>

  <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>
</body>
</html>   

v-on参数传递

当通过methods中定义方法,以供@click调用时,需要注意参数问题: 情况一:如果该方法不需要额外参数,那么方法后的()可以不添加。 但是注意:如果方法本身中有一个参数,那么会默认将原生事件event参数传递进去 情况二:如果需要同时传入某个参数,同时需要event时,可以通过$event传入事件。

查看代码
<!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>Document</title>
</head>
<body>
  
  <div id="app"></div>

  <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>
</body>
</html>

posted @ 2022-01-07 23:47  sunflower-js  阅读(139)  评论(0编辑  收藏  举报