超详细的Vue新手向教程

news2024/9/23 17:25:07

一,前言

本篇文章的正文部分为渐近式介绍Vue基础中的OptionAPI和相关指令,在两大内容之外,本文结尾处会附上vue的特性。    ps:本文总字数过22000,足够详细,尽量新手向的同时也包含一些原理性知识,部分内容结合文档。

二,正文

基本流程

<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <div id="app">
    <h2>{{msg}}</h2>
  </div>
  <script src="../static/vue.js"></script>
  <script>
    const app = Vue.createApp(
      {
        template: ``,
        data() {
          return {
            msg: "Hello Vue"
          }
        },
        methods: {

        }
      }
    )
    app.mount("#app")
  </script>

</body>

</html>

 接下来,我们将将上述过程分开来解释

Step One. Vue应用的创建

<script>
    const app = Vue.createApp(
      {
        template: ``,
        data() {
          return {
            
          }
        },
        methods: {

        }
      }
    )
    app.mount("#app")
  </script>

 首先,我们通过Vue.createApp()方法构建Vue的应用对象,它需要接收一个选项对象作为参数,并且该选项对象包含了OptionAPI(data,methods,computed....) 完整见下图

但在本文中,我们只探讨一些基本的OptionAPI:

  • template
  • data
  • methods
  • computed
  • watch

Step Two. 应用实例的挂载

Vue作为国内广泛使用的渐进式框架,可以很好地与原生及其其他框架共同开发,而应用实例的挂在很好的体现了这一点,app.mount()方法可以将Vue应用在选定的DOM对象上,赋予DOM对象可以使用Vue的属性而不会影响到该DOM对象以外的内容,这样其他部分就可以使用原生JS开发而不会产生耦合。该例子中我们将应用实例挂载在id为“app”上的div元素上。

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

Step Three.  template介绍

<body>
  <div id="app">

  </div>
  <script src="../static/vue.js"></script>
  <script>
    const app = Vue.createApp(
      {
        template: `<h2>{{msg}}</h2>`,
        data() {
          return {
            msg: "Hello Vue"
          }
        }
        
      }
    )
    app.mount("#app")
  </script>

</body>

</html>

 如图,template接收DOM对象,这样Vue才能使用这些DOM对象渲染内容,为了更简便地开发,我们可以不在template中写任何内容,直接在挂载元素中写入是等价的。

<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <div id="app">
    <h2>{{msg}}</h2>
  </div>
  <script src="../static/vue.js"></script>
  <script>
    const app = Vue.createApp(
      {
        template: ``,
        data() {
          return {
            msg: "Hello Vue"
          }
        },
        methods: {

        }
      }
    )
    app.mount("#app")
  </script>

</body>

</html>

上述代码与实例代码是等价的。,一般都是直接在挂载元素中开发。

Step Four.  data介绍


<body>
  <div id="app">
    <h2>{{msg}}</h2>
  </div>
  <script src="../static/vue.js"></script>
  <script>
    const app = Vue.createApp(
      {
        template: ``,
        data() {
          return {
            msg: "Hello Vue"
          }
        },
        methods: {

        }
      }
    )
    app.mount("#app")
  </script>

</body>

</html>

如图,data属性需要传入一个函数,图中的写法为语法糖,是常规写法的简便写法。在vue3中必须传入函数。data中返回的对象会被 vue响应式系统劫持,你可以认为data返回的对象中所有内容被时刻监听着,只要发生改变,这种变化也会同步到虚拟DOM上而对渲染结果产生影响。而在挂载元素中,形如{{ }}的写法被称为mustache写法,在{{}}中我们可以填入有返回值的内容,比如三元表达式,函数,变量。不支持赋值语句这样的无返回值内容,也不支持if-else语句等。这些内容后续会详细解释。在该例子中,{{ msg }}中msg显然为变量,我们可以改变data中的msg来动态改变h2中的内容。这个过程类似JS中修改innerText属性,但mustache能力更强。

 

 Step Five. methods介绍

在介绍methods前,我们先看以下案例:


<body>
  <div id="app">
    <h2>{{msg}}</h2>
    <button @click="btnClick">按钮</button>
  </div>
  <script src="../static/vue.js"></script>
  <script>
    const app = Vue.createApp(
      {
        template: ``,
        data() {
          return {
            msg: "Hello Vue",
            btnClick: function () {
              console.log("clicked");
            }
          }
        },
        methods: {

        }
      }
    )
    app.mount("#app")
  </script>

</body>

</html>

先不用管"@click"语句,它就是一个绑定事件的指令,我们观察data中,我们新增了一个对象方法,而这个方法绑定在了按钮上,我们进入网页:

 

 

结果说明这样写其实是没什么问题的,但是为了数据与方法分离,同时为了更简便地写方法,我们引入了methods这个选项式API。

使用methods后,我们可以观察变化,这一切都是等价的:


<body>
  <div id="app">
    <h2>{{msg}}</h2>
    <button @click="btnClick">按钮</button>
  </div>
  <script src="../static/vue.js"></script>
  <script>
    const app = Vue.createApp(
      {
        template: ``,
        data() {
          return {
            msg: "Hello Vue",


          }
        },
        methods: {
          btnClick() {
            console.log("clicked");
          }
        }
      }
    )
    app.mount("#app")
  </script>

</body>

</html>

 我们可以看到写在methods中后,这就实现了数据与方法分离的效果,减少了耦合性。这样以后修改更加简便,并且还可以使用新写法,形式上更有C的风格。在methods中的方法,我们可以通过this关键词来访问data中的数据:



<body>
  <div id="app">
    <h2>{{msg}}</h2>
    <button @click="btnClick">按钮</button>
  </div>
  <script src="../static/vue.js"></script>
  <script>
    const app = Vue.createApp(
      {
        template: ``,
        data() {
          return {
            msg: "Hello Vue",


          }
        },
        methods: {
          btnClick() {
            console.log(this.msg);
          }
        }
      }
    )
    app.mount("#app")
  </script>

</body>

</html>

 

Notes:

在methods中不允许使用箭头函数,使用箭头函数指向的对象为window,而在window中我们不可以获取到data中的内容,那么,this到底指向什么呢?

methods 对象内的函数中的 this 关键字通常指向当前 Vue 实例。这意味着你可以通过 this 访问 Vue 实例的所有数据和属性,包括 datacomputedprops 等。

当你在 methods 中定义一个函数并调用它时,this 关键字将自动绑定到 Vue 实例上。这样你就可以在方法内部访问和修改数据属性。

Step Six. computed介绍

我们为什么需要计算属性呢?在介绍computed属性前,可以先看Mustache语法部分,再看下面的例子:

<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <div id="app">
    <h2>{{ msg }}</h2>
    <p>{{ getFullName() }}</p>
    <p>{{ reverseGreeting() }}</p>
  </div>
  <script src="../static/vue.js"></script>
  <script>
    const app = Vue.createApp(
      {
        template: ``,
        data() {
          return {
            msg: "Hello Vue",
            firstName: 'John',
            lastName: 'Doe',
            greeting: 'Hello Vue!'
          }
        },
        methods: {
          getFullName() {
            return this.firstName + ' ' + this.lastName
          },
          reverseGreeting() {
            return this.greeting.split('').reverse().join('');
          }
        }

      }
    )
    app.mount("#app")
  </script>

</body>

</html>

 

在上面这个例子中,我们使用methods中的方法计算了复杂的data,接下来我们使用computed属性来替代methods方法。

<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <div id="app">
    <h2>{{ msg }}</h2>
    <p>{{ getFullName() }}</p>
    <p>{{ reverseGreeting() }}</p>
    <p>{{ fullName }}</p>
    <p>{{ reverse }}</p>
  </div>
  <script src="../static/vue.js"></script>
  <script>
    const app = Vue.createApp(
      {
        template: ``,
        data() {
          return {
            msg: "Hello Vue",
            firstName: 'John',
            lastName: 'Doe',
            greeting: 'Hello Vue!'
          }
        },
        methods: {
          getFullName() {
            return this.firstName + ' ' + this.lastName
          },
          reverseGreeting() {
            return this.greeting.split('').reverse().join('');
          }
        },
        computed: {
          fullName() {
            return this.firstName + ' ' + this.lastName
          },
          reverse() {
            return this.greeting.split('').reverse().join('');
          }
        }

      }
    )
    app.mount("#app")
  </script>

</body>

</html>

 

从形式上看,computed属性也就少个()而已,但区别还是很大的:computed中的内容存在缓存中。当firstName和lastName不发生变化时,调用fullName时就不会再计算一遍,而是直接读取。但methods中的方法不同,调用一次就计算一次。所以使用computed属性可以提升优化。

computed: {
          fullName() {
            return this.firstName + ' ' + this.lastName
          },
          reverse() {
            return this.greeting.split('').reverse().join('');
          }
        }

 

Step Seven.  watch介绍

以下的写法为app.vue中的写法,其实本质上都差不多。

说到watch,其实就是为某个变量添加一个监听器,当这个变量发生变化时就调用一个方法,监听分为浅度侦听和深度侦听。如下图,我们为msg变量设定了一个侦听器,当按下按钮,msg内容改变,侦听器启动,执行console代码。

对于watch中的监听函数,他们的名字不能随意取,必须和监听的变量名一致。

同时,监听函数触发时会返回修改前的值和修改后的值,我们可以接收这两个值。如图的newvalue和oldvalue。

<template>
  <h3>监听器</h3>
  <p>{{ msg }}</p>
  <button @click="updateHandler">更新数据</button>
</template>

<script>
export default{
  data(){
    return{
     msg:"hello",
    }
  },

  methods:{
    updateHandler(){
      this.msg = "world"
    }
  },
  watch:{
    msg(newvalue,oldvalue){
      console.log(oldvalue,newvalue);
    }
  }
}
</script>

<style>
</style>

Mustache语法

在 Vue.js 中,Mustache 语法(也称为插值语法)是一种简单的文本替换机制,用于在模板中展示数据。这种语法使用一对花括号 {{ }} 包裹表达式,表达式的结果将在渲染时插入到 HTML 中相应的位置。 

除了用作变量的显示,mustache语法也支持一些较为复杂的使用:

(1)动态属性

以下用字符串拼接为例

<div id="app">
  {{ firstName + ' ' + lastName }}
</div>
<script>
const app = Vue.createApp({
  data() {
    return {
      firstName: 'John',
      lastName: 'Doe'
    };
  }
});

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

(2)条件语句

mustache语法只支持三元来做判断,不能使用if-else。

<div id="app">
  {{ isShow ? 'Visible' : 'Hidden' }}
</div>

<script>
const app = Vue.createApp({
  data() {
    return {
      isShow:true
    };
  }
});

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

(3)方法调用

以一个反转单词的方法为例,插值语法是支持调用函数的。

<div id="app">
  {{ reverseGreeting() }}
</div>

<script>
const app = Vue.createApp({
  data() {
    return {
      greeting: 'Hello Vue!'
    };
  },
   methods:{
        reverseGreeting() {
      return this.greeting.split('').reverse().join('');
    }}

});

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

 

 指令内容

这就是最新版本的所有指令了,其中,v-show,v-if,v-else,v-else-if组成了条件渲染部分,v-for大多用在迭代服务器传来的数据中,它可以依次渲染元素。v-bind用来绑定动态属性,v-on用来绑定事件,v-model用作表单处理。以上提及指令为最常用的指令,其他的指令大多是用来优化的,前期不太常用,但也会提及一部分。

(1)v-once

仅渲染元素和组件一次,并跳过之后的更新。在随后的重新渲染,元素/组件及其所有子项将被当作静态内容并跳过渲染。这可以用来优化更新时的性能。

 



<body>
  <div id="app">
    <h2 v-once>{{msg}}</h2>
    <!-- v-once只会渲染一次,后续改变不会影响这个元素了。 -->
    
    <button @click="changeInfo">改变信息</button>
  </div>
  <script src="../static/vue.js"></script>
  <script>
    const app = Vue.createApp(
      {
        template: ``,
        data() {
          return {
            msg: "Hello Vue",
          }
        },
        methods: {
          changeInfo() {
            this.msg = "Hello World"
          }
        }
      }
    )
    app.mount("#app")
  </script>

</body>

</html>

进入网页后,多次点击按钮文本没发生改变,但是data中的值会发生改变,v-once只是作用在渲染上,而不是限制值的修改。 

(2)v-text


<body>
  <div id="app">
    <h2 v-text="msg"></h2>
    <!-- 区别在于mustache语法更加灵活,v-text用的较少 -->
    


    <button @click="changeInfo">改变信息</button>
  </div>
  <script src="../static/vue.js"></script>
  <script>
    const app = Vue.createApp(
      {
        template: ``,
        data() {
          return {
            msg: "Hello Vue",
           
          }
        },
        methods: {
          changeInfo() {
            this.msg = "Hello World"
          }
        }
      }
    )
    app.mount("#app")
  </script>

</body>

</html>

mustache语法可以完全替代这个指令,了解即可,没啥用。 

(3)v-html



<body>
  <div id="app">
    <h2>{{ web }}</h2>
    <h2 v-html="web">{{ web }}</h2>

    <button @click="changeInfo">改变信息</button>
  </div>
  <script src="../static/vue.js"></script>
  <script>
    const app = Vue.createApp(
      {
        template: ``,
        data() {
          return {
            msg: "Hello Vue",
            web: "<a href='www.baidu.com'>百度</a>"
          }
        },
        methods: {
          changeInfo() {
            this.msg = "Hello World"
          }
        }
      }
    )
    app.mount("#app")
  </script>

</body>

</html>

 

v-html 的内容直接作为普通 HTML 插入—— Vue 模板语法是不会被解析的。如果你发现自己正打算用 v-html 来编写模板,不如重新想想怎么使用组件来代替。 

 

 以上为vue.js文档内容,就作用上讲,v-html就是解析字符串中的内容,相当于innerHTML。但是在开发中用得不是很多,了解即可。

(4)v-pre

跳过该元素及其所有子元素的编译。

元素内具有 v-pre,所有 Vue 模板语法都会被保留并按原样渲染。最常见的用例就是显示原始双大括号标签及内容。这个用的就更少了,了解即可。

(5)v-cloak

在介绍v-cloak前,设想以下场景:当网站等待服务器发送数据时或者正在传输大量数据时,这会造成一定的延时,但是对于template模板却可以很快渲染完成,这时就出现骨架渲染完成但是数据却没有接收完成的现象,这是插值语法就无法渲染,这就会出现{{ msg }}这种按照原样渲染的模样,这对于用户而言是不友好的。所以我们采用v-cloak来控制这种未来得及链接数据的元素。


<style>
  [v-cloak] {
    display: none;
  }
</style>

<body>
  <div id="app">
    <h2 v-cloak>{{msg}}</h2>
    <!-- 等待渲染完成后再显示,完成前使用style属性遮掩 -->
  </div>
  <script src="../static/vue.js"></script>
  <script>
    setTimeout(() => {
      const app = Vue.createApp(
        {
          template: ``,
          data() {
            return {
              msg: "Hello Vue"
            }
          },
          methods: {

          }
        }
      )
      app.mount("#app")
    }, 3000);//延时3s
  </script>

</body>

</html>

在上述代码中,我们为应用实例化延时3s来模拟接受数据的延时情况,添加v-cloak,当未接收到msg数据时,v-cloak会启用[v-cloak]{display:none},隐藏该元素,直到msg得到数据后才会取消掉该属性。 

(6)v-bind

关于v-bind的语法糖:

<body>
  <div id="app">
    <h2>网站</h2>
    <a v-bind:href="link">百度</a>
  </div>
  <script src="../static/vue.js"></script>
  <script>
    const app = Vue.createApp(
      {
        template: ``,
        data() {
          return {
            msg: "Hello Vue",
            link: "http://www.baidu.com"
          }
        },
        methods: {

        }
      }
    )
    app.mount("#app")
  </script>

</body>

</html>
<body>
  <div id="app">
    <h2>网站</h2>
    <a :href="link">百度</a>
  </div>
  <script src="../static/vue.js"></script>
  <script>
    const app = Vue.createApp(
      {
        template: ``,
        data() {
          return {
            msg: "Hello Vue",
            link: "http://www.baidu.com"
          }
        },
        methods: {

        }
      }
    )
    app.mount("#app")
  </script>

</body>

</html>

以上的两种写法完全等价,v-bind:attr="" === :attr=""。 

<1>绑定class
  • 对象语法
  • 数组语法

对象语法

<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<style>
  .active {
    color: red;
  }
</style>

<body>
  <div id="app">
    <!-- 最基本的绑定方法 -->
    <h2 :class="classes">Hello</h2>
    <button :class=" isActive?'active':''" @click="btnClick">我已阅读</button>
  </div>
  <script src="../static/vue.js"></script>
  <script>
    const app = Vue.createApp(
      {
        template: ``,
        data() {
          return {
            classes: "a b c",
            isActive: false
          }
        },
        methods: {
          btnClick() {
            this.isActive = !this.isActive;
          }
        }
      }
    )
    app.mount("#app")
  </script>

</body>

</html>

如图,观察h2的绑定class方式,classes为data中的一个变量,在calsses中,我们存有“a b c”三个类,这就是最基本的绑定类的方式,但这种绑定有个缺点:我们虽然可以通过修改classes的内容来间接的修改h2上的类,但是却不能动态的添加或者移除这个类。 

 比如我们想要实现在某种行为下附加这个类,而在其余时间不附加这个类,如果通过最基本的方式,就如button的class添加一致:通过三元运算符来判断是否启用active这个类别,这确实没问题,但是当这类动态类别数量较多时,代码可读性会很差。所以我们引入了对象语法。

<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<style>
  .active {
    color: red;
  }
</style>

<body>
  <div id="app">
    <!-- 最基本的绑定方法 -->
    <h2 :class="classes">Hello</h2>
    <!-- 对象语法 -->
    <button :class="classes" :class="{active:isActive}" @click="btnClick">我已阅读</button>
    <!-- 静态class与动态class不会出现覆盖的问题,而是结合在一起 -->
  </div>
  <script src="../static/vue.js"></script>
  <script>
    const app = Vue.createApp(
      {
        template: ``,
        data() {
          return {
            classes: "a b c",
            isActive: false
          }
        },
        methods: {
          btnClick() {
            this.isActive = !this.isActive;
          }
        }
      }
    )
    app.mount("#app")
  </script>

</body>

</html>

如图,对象语法很简洁,形如:

<div :class="{类别:是否启用}">

当然一个对象当然可以拥有很多元素,也就是说我们可以添加很多这样的键值对,同时控制很多对类别的启用和关闭。 这里就不演示了。

虽然说对象语法直接接收对象没问题,但是不代表对象语法只能通过对象赋值这种形式。只要返回的结果是一个可读取的对象,那这种方式就没问题,比如通过变量名引用对象,通过函数来获取对象,这都是可行的。

数组语法

<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<style>
  .active {
    color: red;
  }
</style>

<body>
  <div id="app">
    <button :class="classes" :class="['a','b',{'active':isActive}]" @click="btnClick">我已阅读</button>
    <!-- 静态class与动态class不会出现覆盖的问题,而是结合在一起 -->
  </div>
  <script src="../static/vue.js"></script>
  <script>
    const app = Vue.createApp(
      {
        template: ``,
        data() {
          return {
            classes: "a b c",
            isActive: false
          }
        },
        methods: {
          btnClick() {
            this.isActive = !this.isActive;
          }
        }
      }
    )
    app.mount("#app")
  </script>

</body>

</html>

数组语法可以直接写类名(加引号),变量(不加引号),也可以写对象。数组语法用的不是很多 ,了解即可。

<2>绑定style
CSS property 名可以用驼峰式 (camelCase) 或短横线分隔 (kebab-case,记得用引号括起来) 来命名;
  • 对象语法
  • 数组语法

对象语法

<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <div id="app">
    <h2>动态绑定style</h2>
    <p :style="{color:'red','font-size':'10px',backgroundColor:'black'}"></p>
 
  </div>
  <script src="../static/vue.js"></script>
  <script>
    const app = Vue.createApp(
      {
        template: ``,
        data() {
          return {
            msg: "Hello Vue",
            fontColor: "red"
          }
        },
        methods: {  
    
        }
      }
    )
    app.mount("#app")
  </script>

</body>

</html>

如上图,对象中的键为CSS Property,它不是字符串,所以不用带引号,对于CSS property,我们有两种方式引入:如'font-size'这种中间带'-'的类型,它是作为字符串出现的,需要带引号。而'backgroundColor'这种驼峰式命名法是作为非字符串出现的,是不用带引号的,注意甄别。 

关于其他的,都和绑定class差不多,不管使用函数返回一个style对象,还是用个style的对象名来引用都是可行的。

数组语法 

<div :style="[styleObjectA, styleObjectB]"></div>

文档实例: 

<!-- 绑定 attribute -->
<img v-bind:src="imageSrc" />

<!-- 动态 attribute 名 -->
<button v-bind:[key]="value"></button>

<!-- 缩写 -->
<img :src="imageSrc" />

<!-- 缩写形式的动态 attribute 名 (3.4+),扩展为 :src="src" -->
<img :src />

<!-- 动态 attribute 名的缩写 -->
<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 }]"></div>

<!-- style 绑定 -->
<div :style="{ fontSize: size + 'px' }"></div>
<div :style="[styleObjectA, styleObjectB]"></div>

<!-- 绑定对象形式的 attribute -->
<div v-bind="{ id: someProp, 'other-attr': otherProp }"></div>

<!-- prop 绑定。“prop” 必须在子组件中已声明。 -->
<MyComponent :prop="someThing" />

<!-- 传递子父组件共有的 prop -->
<MyComponent v-bind="$props" />

<!-- XLink -->
<svg><a :xlink:special="foo"></a></svg>

 

<3>动态绑定属性 

形如:[attrName]="Object"

和上面的区别就是属性名变成了变量。

<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <div id="app">
    <p :[name]="'active'"></p>
    
  </div>
  <script src="../static/vue.js"></script>
  <script>
    const app = Vue.createApp(
      {
        template: ``,
        data() {
          return {
            msg: "Hello Vue",
            name: 'class',
           
          }
        },
        methods: {


        }
      }
    )
    app.mount("#app")
  </script>

</body>

</html>

<4>绑定对象 

批量处理属性与对应值

<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <div id="app">
    <span v-bind="infos"></span>
  </div>
  <script src="../static/vue.js"></script>
  <script>
    const app = Vue.createApp(
      {
        template: ``,
        data() {
          return {
            msg: "Hello Vue",
      
            infos: {
              title: "list",
              age: 18,
              gender: "male"
            }
          }
        },
        methods: {


        }
      }
    )
    app.mount("#app")
  </script>

</body>

</html>

这种情况下,v-bind:不能省略,它会接收对象将其键作为属性名,值作为属性名所对应的值,支持嵌套对象。 

(7)v-on

v-on的语法糖

<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <div id="app">
    <h2>{{msg}}</h2>
    <button v-on:click="btnClick"></button>
    <button @click="btnClick"></button>
  </div>
  <script src="../static/vue.js"></script>
  <script>
    const app = Vue.createApp(
      {
        template: ``,
        data() {
          return {
            msg: "Hello Vue"
          }
        },
        methods: {
          btnClick() {
            console.log("Clicked");
          }
        }
      }
    )
    app.mount("#app")
  </script>

</body>

</html>

其中,

<button v-on:click="btnClick"></button>
<button @click="btnClick"></button>

完全等价。

当然,你可以选取其他触发事件条件:mousedown,mouseup等等。

<1>v-on的使用

在上文中,我们已经提及了一种事件的绑定方法,v-on同样支持多种事件的绑定。

<button v-on="{ mousedown: doThis, mouseup: doThat }"></button>

借此,我们通过v-on来构建一个计数器:

 

<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <div id="app">
    <h2>{{counter}}</h2>
    <button @click="btnUp">➕</button>
    <button @click="btnDown">➖</button>
  </div>
  <script src="../static/vue.js"></script>
  <script>
    const app = Vue.createApp(
      {
        template: ``,
        data() {
          return {
            counter: 10
          }
        },
        methods: {
          btnUp() {
            this.counter++
          },
          btnDown() {
            this.counter--
          }
        }
      }
    )
    app.mount("#app")
  </script>

</body>

</html>

 

<2>参数传递

当方法不需要参数时,默认将事件对象作为参数,如果方法具有参数时,使用$event来访问事件对象。

当监听原生 DOM 事件时,方法接收原生事件作为唯一参数。如果使用内联声明,声明可以访问一个特殊的 $event 变量:v-on:click="handle('ok', $event)"

<3>修饰符

以下为文档内容截取:

<!-- 停止传播 -->
<button @click.stop="doThis"></button>

<!-- 阻止默认事件 -->
<button @click.prevent="doThis"></button>

<!-- 不带表达式地阻止默认事件 -->
<form @submit.prevent></form>

<!-- 链式调用修饰符 -->
<button @click.stop.prevent="doThis"></button>

<!-- 按键用于 keyAlias 修饰符-->
<input @keyup.enter="onEnter" />

<!-- 点击事件将最多触发一次 -->
<button v-on:click.once="doThis"></button>

 

 

(8)条件指令

如图,条件渲染比较符合其他编程语言的习惯,这里就不赘述了,想要了解更多,可以看文档:

v-if文档

<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <div id="app">
    <h3>if测试</h3>
    <div v-if="flag">真</div>
    <div v-else>假</div>
    <div v-if="type === 'A'">A</div>
    <div v-else-if="type === 'B'">B</div>
    <div v-else-if="type === 'C'">C</div>
    <div v-else-if="type === 'D'">D</div>
    <div v-show="type==='A'"></div>
  </div>
  <script src="../static/vue.js"></script>
  <script>
    const app = Vue.createApp(
      {
        template: ``,
        data() {
          return {
            flag: false,
            type: "D"
          }
        },
        methods: {

        }
      }
    )
    app.mount("#app")
  </script>

</body>

</html>

 其中,v-show的作用和v-if相似,v-show没有else的语句。

v-show与v-if的区别

当v-show条件为假时,v-show会为元素添加display:none的样式,而v-if条件为假时,元素被清除。如果我们的原生需要在显示和隐藏之间频繁的切换,那么使用v-show;如果不会频繁的发生切换,那么使用v-if

 

(9)v-for

基于原始数据多次渲染元素或模板块。

<1>v-for的使用
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<style>
  .item {
    border: 2px solid black;
    padding: 50px;
    margin-top: 2px;

  }
</style>

<body>
  <div id="app">
    <h2>电影列表</h2>
    <ul>
      <li style="list-style-type: none;" v-for="(item,index) in movies">{{ index }} {{ item }}</li>
    </ul>   
  </div>
  <script src="../static/vue.js"></script>
  <script>
    const app = Vue.createApp(
      {
        template: ``,
        data() {
          return {
            movies: ["速度与激情", "星际穿越", "地球脉动", "哪吒"],  
        },
        methods: {

        }
      }
    )
    app.mount("#app")
  </script>

</body>

</html>

 

在python中,这种形式与enumerate()方法类似,可以同时获取到下标和对应元素。

 

<2>v-for支持类型

对于v-for而言,只要是可迭代对象,就可以作为v-for支持类型。

下面举数字,字符串和对象为例:

<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<style>
  .item {
    border: 2px solid black;
    padding: 50px;
    margin-top: 2px;

  }
</style>

<body>
  <div id="app">
    <h2>电影列表</h2>
    <ul>
      <li v-for="item in 10">{{ item }}</li>
      <li v-for="item in 'Hello Vue'">{{ item }}</li>
    </ul>

    

  </div>
  <script src="../static/vue.js"></script>
  <script>
    const app = Vue.createApp(
      {
        template: ``,
        data() {
          return {
           
          }
        },
        methods: {

        }
      }
    )
    app.mount("#app")
  </script>

</body>

</html>

 

<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<style>
  .item {
    border: 2px solid black;
    padding: 50px;
    margin-top: 2px;

  }
</style>

<body>
  <div id="app">
    <h2>电影列表</h2>
    

    <h2>学生列表</h2>
    <div v-for="stu in students">
      <div class="item">
        <p>ID-{{ stu.id }}</p>
        <p>Name-{{ stu.name }}</p>
        <p>Age-{{ stu.age }}</p>
        <p>Major-{{ stu.major }}</p>
      </div>
    </div>

    <div v-for="(value,key,index) in product">
      {{ index }} - {{ key }} - {{ value }}
    </div>

  </div>
  <script src="../static/vue.js"></script>
  <script>
    const app = Vue.createApp(
      {
        template: ``,
        data() {
          return {
            movies: ["速度与激情", "星际穿越", "地球脉动", "哪吒"],
            //对象数组的渲染
            students: [
              { id: 1, name: "Mike", age: 18, major: "Mathmatics" },
              { id: 2, name: "Jane", age: 18, major: "Art" },
              { id: 3, name: "Rian", age: 18, major: "IT" }
            ],
            product: { id: 22, productName: "Little Prince", price: "39.8", amount: "1100" },
          }
        },
        methods: {

        }
      }
    )
    app.mount("#app")
  </script>

</body>

</html>

 

 

<3>template元素

template元素就像一个调整图层一样,它不会被渲染,它唯一的用处就是承载命令。

<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<style>
  .item {
    border: 2px solid black;
    padding: 50px;
    margin-top: 2px;

  }
</style>

<body>
  <div id="app">
    <h2>电影列表</h2>


    <h2>学生列表</h2>
    <template v-for="stu in students">
      <div class="item">
        <p>ID-{{ stu.id }}</p>
        <p>Name-{{ stu.name }}</p>
        <p>Age-{{ stu.age }}</p>
        <p>Major-{{ stu.major }}</p>
      </div>
    </template>

    <template v-for="(value,key,index) in product">
      {{ index }} - {{ key }} - {{ value }}
    </template>

  </div>
  <script src="../static/vue.js"></script>
  <script>
    const app = Vue.createApp(
      {
        template: ``,
        data() {
          return {
            movies: ["速度与激情", "星际穿越", "地球脉动", "哪吒"],
            //对象数组的渲染
            students: [
              { id: 1, name: "Mike", age: 18, major: "Mathmatics" },
              { id: 2, name: "Jane", age: 18, major: "Art" },
              { id: 3, name: "Rian", age: 18, major: "IT" }
            ],
            product: { id: 22, productName: "Little Prince", price: "39.8", amount: "1100" },
          }
        },
        methods: {

        }
      }
    )
    app.mount("#app")
  </script>

</body>

</html>
<4>数组更新检测
Vue 将被侦听的数组的变更方法进行了包裹,所以它们也将会触发视图更新。

 

以上的方法都可以刷新视图,即影响渲染结果。

<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <div id="app">
    <h2>{{msg}}</h2>
    <ul>
      <li v-for="item in movies">{{ item }}</li>
    </ul>

    <button @click="appendMovie">添加电影</button>
  </div>
  <script src="../static/vue.js"></script>
  <script>
    const app = Vue.createApp(
      {
        template: ``,
        data() {
          return {
            movies: ["速度与激情", "星际穿越", "地球脉动", "哪吒"]
          }
        },
        methods: {
          appendMovie() {
            this.movies.push("白蛇传");
          }
        }
      }
    )
    app.mount("#app")
  </script>

</body>

</html>

 

除了上面其中方法外,如filter(),slice(),map()这种创建新数组的方法不会被监控,即修改后必须得赋给原数组才可以引起变化。

  

<5>key

一般v-for都需要带上key作为该数据的唯一性标志,因为加上key后可以提高效率。

原理较为复杂,简单来说,就是使用了key可以使用diff算法来进行匹配key相同的VNode,而不是大量删除和修改来满足插入值的情况。

(10)v-model

v-model作为表单中最重要的指令之一,功能强大,内容比较多,这里就不赘述了,留待下篇文章讨论。这里可以提前了解一下:v-model就是可以双向绑定,当我们在input(text)中输入值时,它会实时传输给message,当我们修改message值的时候也会改变input(text)的内容,他们是互相影响的。lazy修饰词就是将实时变化改为失去焦点时变化。

<template>
  <h3>表单</h3>
  <input type="text" name="" id="" v-model="message">
  <input type="checkbox" name="" id="" v-model="check">
  <p>{{ message }}</p>
  <p>{{ check }}</p>
  <input type="text" name="" id="" v-model.lazy="message">
  <p>{{ message }}</p>
</template>

<script>
export default{
  data(){
    return{
     message:"",
     check:false
    }
  },
  watch:{
    check(newvalue,oldvalue){
      if(newvalue === true)
      {
        alert("网站协议");
      }
    
    }
  }
}
</script>

<style>
</style>

三,总结

OptionAPI(选项式API)

  • Template: 定义 Vue 实例的 HTML 模板。可以是一个字符串模板,也可以是一个外部文件的引用。
  • Data: 定义 Vue 实例的数据属性。这些属性可以在模板中使用,也可以在方法中引用。data 必须是一个函数,每次创建新实例时都会返回一个新的对象。
  • Methods:  定义可被组件内部使用的可复用函数。方法可以在模板中通过 . 符号调用,也可以通过事件监听器调用。
  • Computed: 定义依赖于其他数据属性的计算属性。计算属性会缓存结果,只有在其依赖的数据属性改变时才会重新计算。
  • Watch:  监听数据属性的变化并执行相应的回调函数。可以用于执行异步操作或开销较大的计算任务。

指令

v-once:只渲染元素和组件一次。

v-text:更新元素的 textContent

v-html:更新元素的 innerHTML

v-pre:跳过 Vue 的编译过程。

v-cloak:隐藏未编译的 Mustache 语法直到实例准备就绪。

v-bind:动态绑定属性。

v-on:绑定事件监听器。

v-for:循环渲染列表或数组。

v-model:实现表单输入控件与数据的双向绑定。

v-if....:条件渲染。

v-show:切换元素的 CSS display 属性。

四,附言

声明式与命令式

(1)声明式

定义

  • 声明式编程关注的是“做什么”,而不是“怎么做”。也就是说,你告诉计算机你想达到的目标或结果,而不是具体的步骤。
  • 声明式编程通常涉及使用高级抽象,如函数式编程、逻辑编程、数据库查询语言等。

特点

  • 更加简洁,易于理解和维护。
  • 通常更加接近人类的思考方式。
  • 可以提高代码的可读性和可维护性。
  • 适用于处理数据流和变换的场景。

示例: 在前端开发中,Vue.js 的模板系统就是一个典型的声明式编程的例子。例如,使用 v-if 指令来控制元素的显示或隐藏:

<div v-if="isVisible">Hello World</div>

这里我们声明了只有当 isVisible 为真时才显示这个元素,而不需要关心具体的实现细节。

(2)命令式

定义

  • 命令式编程关注的是“怎么做”,即明确地告诉计算机每一步应该做什么。
  • 这种编程方式更接近底层硬件的操作,通常涉及更多的控制流语句(如 for 循环、if 语句等)。

特点

  • 更加灵活,可以精确控制程序的行为。
  • 适用于需要复杂流程控制的场景。
  • 通常需要编写更多的代码来完成相同的任务。

示例: 在命令式编程中,你可能需要显式地编写循环来遍历数组并修改每个元素:

let numbers = [1, 2, 3, 4, 5];
for (let i = 0; i < numbers.length; i++) {
  numbers[i] *= 2;
}
  • 声明式编程:适用于构建用户界面、处理数据流、执行查询等场景。
  • 命令式编程:适用于需要精确控制流程、优化性能、处理复杂逻辑的情况。

MVVM(Model-View-ModelView)

我们可以看到ViewModel中有DOM Listeners,这个就是vue为什么能够在变量改变时快速改变渲染的原因,就和Qt中主循环效果差不多,一直循环等待修改。而Data Bindings可以参考Mustache语法,它其实就是使用Data Bindings实现的。 

 


创作不易,点个赞鼓励一下呗~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2053912.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

TILs 评分:TCGA 肿瘤浸润淋巴细胞病理切片深度学习评分!图片下载与可视化

生信碱移 病理切片的TILs评分 TCGA 数据库是最大的肿瘤组学公开数据库之一。尽管如此&#xff0c;更多的研究往往仅局限于关注 TCGA 中各类肿瘤样本的上游组学信息或基本病理特征&#xff0c;而忽略了对样本数字化 H&E 病理染色图像的进一步应用。 ▲ TCGA中肿瘤样本的病…

Centos系统中创建定时器完成定时任务

Centos系统中创建定时器完成定时任务 时间不一定能证明很多东西&#xff0c;但是一定能看透很多东西&#xff0c;坚信自己的选择&#xff0c;不动摇&#xff0c;使劲跑&#xff0c;明天会更好。 在 CentOS 上&#xff0c;可以使用 systemd 定时器来创建一个每十秒执行一次的任务…

拟合与插值|线性最小二乘拟合|非线性最小二乘拟合|一维插值|二维插值

挖掘数据背后的规律是数学建模的重要任务&#xff0c;拟合与插值是常用的分析方法 掌握拟合与插值的基本概念和方法熟悉Matlab相关程序实现能够从数据中挖掘数学规律 拟合问题的基本提法 拟合问题的概念 已知一组数据(以二维为例)&#xff0c;即平面上n个点 ( x i , y i ) …

Blazor开发框架Known-V2.0.8

V2.0.8 Known是基于Blazor的企业级快速开发框架&#xff0c;低代码&#xff0c;跨平台&#xff0c;开箱即用&#xff0c;一处代码&#xff0c;多处运行。目前已有部分客户在使用&#xff0c;最近客户的项目和产品&#xff0c;有的在Docker中运行&#xff0c;有的在重新升级改造…

2024.8.18周报

摘要 本周利用阳朔水站的数据对1D浅水方程进行了求解&#xff0c;通过将1D浅水方程的物理约束纳入到神经网络&#xff0c;将时空坐标x&#xff0c;t作为输入到神经网络中&#xff0c;得到预测解水深和流量的数据&#xff0c;然后利用真实的数据进行比较&#xff0c;计算损失。…

【鸿蒙学习】HarmonyOS应用开发者基础 - 白皮书V3.0的关键知识点

本文内容由智谱清言的长文章解读生成。 智谱AI&#xff08;https://zhipuai.cn/&#xff09; 白皮书V3.0这份文档详细介绍了鸿蒙生态应用开发的各个方面&#xff0c;涵盖了从核心概念到开发流程、测试和运维分析的各个环节。由于这本书有128页&#xff0c;读完时间较长&#xf…

Java数组02:数组内存分析、三种初始化方式及特点

本节内容视频链接&#xff1a;Java数组03&#xff1a;三种初始化及内存分析_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV12J41137hu?p53&vd_sourceb5775c3a4ea16a5306db9c7c1c1486b5 1.数组内存分析 堆&#xff1a;存放new的对象和数组&#xff1b;可以被所有线…

【精选】基于Python大型购物商城系统(京东购物商城,淘宝购物商城,拼多多购物商城爬虫系统)

目录&#xff1a; 目录&#xff1a; 系统介绍&#xff1a; 系统开发技术 Python语言 Django框架简介 MySQL数据库技术 B/S架构 系统设计 系统总体设计 系统详细界面实现&#xff1a; 系统测试 测试目的 测试用例 本章小结 参考代码&#xff1a; 为什么选择我&…

【C语言可变参数函数的使用与原理分析】

文章目录 1 前言2 实例2.1实例程序2.2程序执行结果2.3 程序分析 3 补充4 总结 1 前言 在编程过程中&#xff0c;有时会遇到需要定义参数数量不固定的函数的情况。 C语言提供了一种灵活的解决方案&#xff1a;变参函数。这种函数能够根据实际调用时的需求&#xff0c;接受任意…

yum 源更新

本人使用Centos7系统&#xff1b; 系统自带的Yum源地址&#xff0c;下载速度又慢&#xff0c;而且有些包还是没有的&#xff0c;于是考虑将yum进行更换&#xff0c;可以更换为国内其他厂商的yum源&#xff0c;比如&#xff1a;阿里、腾讯、163、清华的&#xff0c;尽可能汇总&…

如何有效利用渗压计来避免溃坝风险

有效利用渗压计来避免溃坝风险是一个综合性的过程&#xff0c;涉及渗压计的安装、监测、数据分析以及应急响应等多个方面。以下是一些关键步骤和建议&#xff1a; 选择合适的渗压计&#xff1a; 根据具体工程需求和环境条件&#xff0c;选择合适的渗压计类型确保渗压计的质量可…

嘀嗒出行拼车系统源码

嘀嗒出行APP的开发需求与功能架构主要围绕提升用户出行体验、提高匹配效率、保障行程安全以及满足多样化的出行需求来构建。以下是对嘀嗒出行APP开发需求与功能架构的详细解析 一、开发需求 市场需求&#xff1a;随着出行市场的竞争加剧&#xff0c;嘀嗒出行需要不断提高自身服…

Codigger 视频会议(Meeting):医疗行业的创新协作利器

在当今数字化快速发展的时代&#xff0c;医疗行业也在不断拥抱信息技术带来的变革。远程医疗协作作为提升医疗服务效率和质量的重要手段&#xff0c;正日益受到关注。而 Codigger 视频会议&#xff08;Meeting&#xff09;则成为了医疗领域中一颗璀璨的明星&#xff0c;为医疗行…

Cacti SQL注入漏洞分析(CVE-2023-51448)

Cacti 为全球用户提供强大且可扩展的运营监控和故障管理框架。它还是一个完整的网络绘图解决方案&#xff0c;旨在利用RRDTool的数据存储和绘图功能。Cacti 包括一个完全分布式和容错的数据收集框架、用于设备、图表和树的高级基于模板的自动化功能、多种数据采集方法、通过插件…

自然语言处理系列三十三》 语义相似度》同义词词林》算法原理

注&#xff1a;此文章内容均节选自充电了么创始人&#xff0c;CEO兼CTO陈敬雷老师的新书《自然语言处理原理与实战》&#xff08;人工智能科学与技术丛书&#xff09;【陈敬雷编著】【清华大学出版社】 文章目录 自然语言处理系列三十三同义词词林算法原理代码实战 总结 自然语…

软件测试面试题整理(一)之自动化测试题大合集

1 什么是POM&#xff0c;为什么要使用它&#xff1f; POM是Page Object Model的简称&#xff0c;它是一种设计思想&#xff0c;而不是框架。大概的意思是&#xff0c;把一个一个页面&#xff0c;当做一个对象&#xff0c;页面的元素和元素之间操作方法就是页面对象的属性和行为…

甘肃旅游服务平台代码--论文pf

TOC springboot422甘肃旅游服务平台代码--论文pf 绪论 1.1 研究背景 现在大家正处于互联网加的时代&#xff0c;这个时代它就是一个信息内容无比丰富&#xff0c;信息处理与管理变得越加高效的网络化的时代&#xff0c;这个时代让大家的生活不仅变得更加地便利化&#xff0…

基于java的养老服务系统/基于web的养老院管理系统

摘要 随着科学技术的飞速发展&#xff0c;社会的方方面面、各行各业都在努力与现代的先进技术接轨&#xff0c;通过科技手段来提高自身的优势&#xff0c;养老服务当然也不能排除在外&#xff0c;从健康体检、体检预约的统计和分析&#xff0c;在过程中会产生大量的、各种各样的…

WLAN射频调优

射频调优的基本原则 信道优化的基本原则 2.4G射频在非高密部署场景中推荐采用1、6、11这种3个不重叠的信道进行规划&#xff0c;同理也可以选用2、7、12或3、8、13的组合方式&#xff1b;在高密部署场景中则推荐采用1、5、9、13共4个信道组合进行规划。5G射频推荐采用36、40、…

【二分查找】--- 进阶题目赏析

Welcome to 9ilks Code World (๑•́ ₃ •̀๑) 个人主页: 9ilk (๑•́ ₃ •̀๑) 文章专栏&#xff1a; 算法Journey 本篇博客我们继续来了解一些有关二分查找算法的进阶题目。 &#x1f3e0; 寻找峰值 &#x1f4cc; 题目内容 162. 寻找峰值 - 力扣&#…