Vue基础

73 阅读12分钟

邂逅Vue.js

安装Vue

Vue的CDN引入:

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

通过本地进行安装

  • 下载Vue的源码,可以直接打开CDN的链接:打开链接,复制其中所有的代码;
  • 创建一个新的文件,比如vue.js,将代码复制到其中;
  • 通过script标签,引入刚才的文件:
<script src="../js/vue.js"></script>

声明式和命令式开发

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

    • 命令式编程和声明式编程:
    • 命令式编程关注的是“how to do”自己完成整个how的过程;
    • 声明式编程关注的是"what to do”,由框架(机器)完成“how”的过程
  • 在原生的实现过程中,我们是如何操作的呢?

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

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

MVVM模型

回顾MVC

MVC 模式代表 Model-View-Controller(模型-视图-控制器)模式。

这种模式用于应用程序的分层开发。

  • Model(模型) - 模型代表一个存取数据的对象或 JAVA POJO。它也可以带有逻辑,在数据变化时更新控制器。
  • View(视图) - 视图代表模型包含的数据的可视化。
  • Controller(控制器) - 控制器作用于模型和视图上。它控制数据流向模型对象,并在数据变化时更新视图。它使视图与模型分离开。

什么是MVVM?

MVVM (Model-View-ViewModel) 是一种软件架构设计模式,由微软WPF (用于替代WinForm,以前就是用这个技术开发桌面应用程序的)和Silverlight (类似于Java Applet,简单点说就是在浏览器上运行的WPF)的架构师Ken Cooper和Ted Peters 开发,是一种简化用户界面的事件驱动编程方式。由John Gossman (同样也是WPF和Silverlight的架构师)于2005年在他的博客上发表。

MVVM 源自于经典的MVC (ModI-View-Controller) 模式

MVVM的核心是ViewModel层,负责转换Model中的数据对象来让数据变得更容易管理和使用,其作用如下:

  • 该层向上与View层进行双向数据绑定
  • 向下与Model层通过接口请求进行数据交互。

Vue基本属性

data属性

  • data属性是传入一个函数,井目该函数需要返回一个对象:

    • 在ue2.x的时候,也可以传入一个对象(虽然官方推荐是一个函数);
    • 在Vu3x的时候,必须传入一个函数,否则就会直接在浏览器中报错:
  • data中返回的对象会被Vue的响应式系统劫持,之后对该对象的修改或者访问都会在劫特中被处理:

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

methods属性

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

    • 这些方法可以被绑定到模板中:
    • 在该方法中,我们可以使用this关键字来直接方问到data中返回的对象的属性:
  • 对于有经验的同学,在这里我提一个问题,官方文档有这么一段描述:

    • 问题一:为什么不能使用箭头函数(官方文档有给出解释)
    • 问题二:不使用箭头函数的情况下,this到底指向的是什么?(可以作为一道面试题)

注意 注意,不应该使用箭头函数来定义method函数(例如plus:0→this.a++)。理由是箭头函数绑定了父级作用域的上下文所以this将不会按照期里指向组件实例,this.a将是undefined.

computed 计算属性

  • 注意:计算属性看起来像是一个函数,但是我们在使用的时候不需要加(),这个后面讲setter和getter时会讲到;
  • 我们会发现无论是直观上,还是效果上计算属性都是更好的选择;
  • 并且计算属性是有缓存的;
<div id="app">
    <h2>{{fullName}}</h2>
</div>
<script>
    const app = new Vue({
        el: '#app',
        data: {
            firstName: 'Guo'
            lastName: 'shuaige'
        },
        //计算属性在此处添加
        computed: {
            fullName() {
                return this.firstName + this.lastName
            }
        }
    })
</script>
  • computed / methods区别

  • 多次使用的时候

    • methods: 每次都会调用
    • computed: 计算机会缓存, 不变的情况下只调用一次
  • 监听器的定义与使用(自查文档)

    Vue提供了一种更通用的方式来观察和响应Vue实例上的数据变动:监听属性。当有一些数据需要随着其他数据变化而变动时,就可以使用监听器。 听起来监听器和计算属性差不多,从功能描述来看,确实是,不过在实际应用中二者还是有很大差别。

Vue基础

Vue代码片段

<!DOCTYPE html>
<html lang="zh-CN">
<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">
        <h3>{{ }}</h3>
    </div>
​
    <script src="../lib/vue.js"></script>
    <script>
        const app =Vue.createApp({
            // template:``,
            data: function(){   //数据
                return {
                    
                }
            },
            methods: {          //方法
                
            }
        })
        app.mount("#app")
    </script>
</body>
</html>

基础语法(值插入模板内容)

Mustache双大括号语法

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

    • 并且我们前端提到过,data返回的对象是有添加到Vue的响应式系统中;
    • 当data中的数据发生改变时,对应的内容也会发生更新。
    • 当然,Mustache中不仅仅可以是data中的属性,也可以是一个JavaScript的表达式。
<template id="my-app">
    <div>
        <!--mustache基本使用:-->
        <h2>{{message}}</h2>
        <!--JovaScript表达式-->
        <h2>{{counter 2}}</h2>
        <h2>{{message.split("").reverse()join("")}}</h2>
        <!--·调用一个nethods中的函数:-->
        <h2>{{reverse(message)}}</h2>
    </div>
</template>

v-once指令(了解)

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

    • 当数据发生变化时,元素或者组件以及其所有的子元素将视为静态内容并且跳过;
    • 该指令可以用于性能优化;
  • 如果是子节点,也是只会渲染一次:

v-text指令(了解)

  • 用于更新元素的 textContent:
<span v-text="msg"></span>
<!--等价于-->
<span>{{ msg }}</span>

v-html指令(了解)

  • 默认情况下,如果我们展示的内容本身是html的,那么vue井不会对其进行特殊的解析。

    • 如果我们希望这个内容被vue可以解析出来,那么可以使用v-html来展示:
<template id="my-app">
    <div v-html='info'></div>
</template>
<script src="./js/vue.js"></script>
<script>
const App={
      template:'#my-app',
    data() {
        return{
            info:`<span style='color:red;font-size:30px'>哈哈哈</span>`
    }
   }
 }
​

v-pre(了解)

  • V-pre用于跳过元素和它的子元素的编译过程,显示原始的Mustache标签:

    • 跳过不需要编译的节点,加快编译的速度

v-cloak

  • 这个指铃保持在元素上直到关联组件实例结束编译。

    • 和CSS规则如[v-cloak]{display:none}一起用时,这个指令可以隐未编译的Mustache标签直到组件实例准备完毕。

基础属性

v-bind属性

  • v-bind用于绑定一个或多个属性值,或者向另一个组件传递props值(这个学到组件时再介绍)

    • 在开发中,有哪些属性需要动态进行绑定呢?
    • 还是有很多的,比如图片的链接src网站的链接href 动态绑定一些类、样式等等
<template id="my-app"><!--·完整的写法·-->
<img v-bind:src="src"alt=""><!--·语法糖写法·-->
<img :src="src"alt="">
<!--·注意和上面的区别--
​
··<!--·绑定元素·-->
<a :href="href"></a></template>

绑定class-对象语法

  • 对象语法:我们可以传给:(class-bind:class的简写)一个对象,以动态地切换class。
<template id="my-app">
<!--·1,普通的绑定方式-->
<div class="className">{{message}}</div><!--·2.对象绑定-->
<!--·动态切换class是否加入:·f类(变量):boolean(true/false)}·-->
<div class="why":class="{nba:true,'james':true}"></div>
</template>
  • 数组语法:我们可以把一个数组传给:class,以应用一个class列表:
<template id="my-app">
<!--·1.直接传入一个数组-->
<div :class="['why','nba']">哈哈哈</div><!--·2.数组中也可以使用三元运算符或者绑定变量-->
<div :class="['why',nba, isActive?'active':'']">呵呵呵</div><!--·3.数组中也可以使用对象语法·-->
<div :class="['why',nba,{'actvie' : 'isActive'}]">嘻嘻嘻</div>
</template>

绑定style

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

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

  • 绑定cass有两种方式:

    • 对象语法
    <template id="my-app">
    <!--·1.基本使用:·传入一个对像,·并且对像内容都是确定的:-->
    <div :style="{color:'red',fontsize:'30px','background-color':'blue']">{{message}}</div><!--2.变量数据:传入一个对像,·值会来自于data-->
    <div :style="{color:'red',fontsize:size+'px','background-color':'blue']">{{message}}</div><!--·3.对象数据:直接在data中定义好对像在这里使用-->
    <div :style="styleObj">{{message}} </div></template>
    
    • 数组语法
    <!--stye的数组语法可以将多个样式对象应用到同一个元素上:-->
    <template id="my-app">
    <div :style="[styleobj1,styleobj2]">{{message}}</div>
    </template>
    

动态绑定属性

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

    • 前端我们无论绑定src,class、style,属性名称都是固定的:
    • 如果属性名称不是固定的,我们可以使用:[属性名]=“值”的格式来定义:
    • 这种绑定的方式,我们称之为动态绑定属性:
<template id="my-app">
<!--·属性的名称是动态的-->
<div :[name]="value">{{message}}</div>
</template>
  • 如果我们希望将一个对象的所有属性,绑定到元素上的所有属性,应该怎么做呢?

    • 非常简单,我们可以直接使用v-bind绑定一个对象:
    • 案例:info对象会被拆解成div的各个属性
<!-- 在data选项中 info: { name: 'Klaus', age: 24 } -->
<!-- 直接使用v-bind 即可 不需要加上对应属性名 因为这里是绑定多个属性 -->
<div v-bind="info">foo</div><!-- 简写形式 - 不推荐,可读性较差 -->
<div :="info">foo</div><!-- 上述的写法等价于 -->
<div :name="info.name" :age="info.age">foo</div>

v-on绑定事件

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

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

    • 这个时候,我们就必须监听用户发生的事件,比如点击、拖拽、键盘事件等等
    • 在Vue中如何监听事件呢?使用v-on指令。

基本使用

<1--1.基本使用-->
<!--·绑定一个表达式-->
<button v-on:click="counter++"></button>
    
<!--·绑定到一个nethods方法中·-->
<button v-on:click="btnclick">1</button>
 
<!--v-on的语法糖-->
<button @click="btnclick">按钮2</button>
    
<!--·绑定鼠标移动事件:-->
<div @mousemove="mouseMove">div的区域</div>
    
<!--·2.绑定对象-->
<button v-on="{click : btnclick, mousemove : mouseMove}">特殊按钮3</button>

参数传递

  • 没有参数的情况下, 可以不写( ); 如果方法本身有一个参数, 会默认将原生事件event参数传递进去
  • 如果传入某个参数, 同时需要event时, 可以通过$event传入时间
<!--情况一: 方法没有参数-->
  <button @click="btnClick1">按钮1</button>
  <button @click="btnClick1()">按钮1</button>
​
  <!--情况二: 如果方法有参数-->
  <!--1.调用时不传入参数,会默认将event作为第一个参数传入-->
  <button @click="btnClick2">按钮2</button>
  <!--2.调用时不传入参数,那么参数为undefined-->
  <button @click="btnClick2()">按钮2</button>
​
  <!--情况三: 如果方法有参数,并且希望传入event-->
  <button @click="btnClick3(10, $event)">按钮3</button>

v-on的修饰符

修饰符作用实际调用
.stop阻止事件冒泡event.stopPropagation()
.prevent阻止默认事件event.preventDefault()
{keyCode I keyAlias}监听某个键盘的键帽
.native监听组件根元素的原生事件
.once只触发一次回调
.left只当点击鼠标左键时触发

条件渲染

  • v-if、v-else、v-else-if用于根据条件来渲染某一块的内容:

    • 这些内容只有在条件为true时,才会被渲染出来;
    • 这三个指令与JavaScript的条件语句if、else、else if类似;
<template id="my-app">
<input type="text"v-model.number="score">
<h2 v-if="score>90">优秀</h2>
<h2 v-else-if="score>80">良好</h2>
<h2 v-else-1f="score>60">普通</h2>
<h2 v-else>不及格</h2>
</template>
  • v-if 的渲染原理:

    • v-if是惰性的;
    • 当条件为false时,其判断的内容完全不会被渲染或者会被销毁掉;
    • 当条件为true时,才会真正渲染条件块中的内容;

v-if和v-show的区别

特点性能
v-for每次都会重新删除或创建元素切换性能高
v-show每次不会重新进行DOM的删除和创建操作(不支持template),通过css的display属性来进行切换。初始渲染消耗高

总结: 如果元素可能永远不会显示出来被用户看到,则推荐v-if;如果元素涉及到频繁切换,则推荐v-show

v-for基本使用

  1. 迭代数组

    <ul>
        <li v-for = "(item , i) in sites">{{item.name}}</li>
    </ul>
    ​
    <script>
      const app = new Vue({
        el: '#app',
        data: {
            sites:[
                { name: 'Runnoob'},
                { name:'Google'},
                { name:'Taobao'}
            ]
        }
      });
    </script>
    
  2. 迭代对象的属性

    <div v-for = "(value ,key,index)  in  user">值是:{{value}}  键是:{{key}}   索引是:{{index}}</div><script>
      const app = new Vue({
        el: '#app',
        data: {
            user:{
                id:1,
                name:'guo',
                gender:'nan'
            }
        }
      });
    </script>
    
  3. 迭代数字

    <p v-for = "i in 10">这是第{{i}}个p标签</p>
    
    • v-for 迭代数字时,i 值从1开始
    • key在使用的时候,必须使用v-bind属性绑定的形式,指定key的值
  4. key的作用

    key的作用是为了高效的更新虚拟DOM key要具有唯一性, 不然就没意义

  • 在使用v-for进行列表渲染时,我们通常会给元素或者组件绑定一个key属性。

  • 这个key属性有什么作用呢?我们先来看一下官方的解释:

    • key属性主要用在Vue的虚拟DOM算法,在新旧nodes对比时辨识VNodes;
    • 如果不使用key,Vue会使用一种最大限度减少动态元素并且尽可能的尝试就地修改/复用相同类型元素的算法;
    • 而使用key时,它会基于key的变化重新排列元素顺序,并且会移除/销毁key不存在的元素;
    <li v-for="(item, index) in names" :key="item">{{index + 1}} - {{item}}</li>
    

v-model 实现双向绑定

  1. 基本原理

    • v-bind绑定value属性的值;
    • v-on绑定input事件监听到函数中,函数会获取最新的值赋值到绑定的属性中;
    <body>
        <div id="app">
            <input type="text" :value="datas" @input="inputClick">
             <!-- 等价于
            <input type="text" v-model="datas"> -->
            <h2>{{datas}}</h2>
            
            <h2>{{datas}}</h2>
        </div>
    ​
        <script src="../lib/vue.js"></script>
        <script>
            const app =Vue.createApp({
                // template:``,
                data: function(){
                    return {
                        datas: 12345
                    }
                },
                methods: {
                    inputClick(event){
                        this.datas = event.target.value
                    }
                }
            })
            app.mount("#app")
        </script>
    </body>
    
  2. 结合radio类型

       <label for="male">
             <input type="radio" id="male" name="sex" value="男" v-model="sex">男
           </label>
           <label for="female">
             <input type="radio" id="female" name="sex" value="女" v-model="sex">女
           </label>
           <h2>{{sex}}</h2>
    ​
       <script>
           const app = new Vue({
               el: '#app',
               data: {
                   sex: '男'
               }
           })
       </script>
    
  • sex里面写上数据时,由于双向绑定,对应的按钮处也会有选中效果,这样可以解决单选按钮的默认问题
  1. 结合chechbox类型

    //单选框
    <label for="agree">
          <input type="checkbox" id="agree" v-model="isAgree">同意协议
    </label>
    <h2>{{isAgree}}</h2>
    <button :disabled="!isAgree">下一步</button>
    <script>
        const app = new Vue({
            el: '#app',
            data: {
                isAgree: false       //单选框对应的是boolean值
            }
        })
    </script>
    ​
    ​
    //多选框
    <input type="checkbox" value="篮球" v-model="hobbies">篮球
    <input type="checkbox" value="乒乓球" v-model="hobbies">乒乓球
    <input type="checkbox" value="足球" v-model="hobbies">足球
    <h2>爱好是{{hobbies}}</h2>
    <script>
        const app = new Vue({
            el: '#app',
            data: {
                hobbies: [ ]                //多选框对应的是数组
            }
        })
    </script>
    
  2. 结合select类型

    <select name="abc"  v-model="fruit">
          <option value="苹果">苹果</option>
          <option value="香蕉">香蕉</option>
          <option value="葡萄">葡萄</option>
    </select>
    <h2>选择的是:{{fruit}}</h2><script>
        const app = new Vue({
            el: '#app',
            data: {
                fruit: '香蕉'
            }
        })
    </script>
    
    • 注意:select的v-model是写在select中的!
  3. 值绑定

    我们前面的value中的值,都是定义在input时直接给定,但是在实际开发中,这些input的值可能是定义在data中的,所以需要通过 v-bind:value动态地给value绑定值

    <label v-for="item in allHobbies" :for="item">
          <input type="checkbox" :id="item" :value="item" v-model="hobbies">{{item}}
    </label>
    <h2>选择的是:{{hobbies}}</h2><script>
        const app = new Vue({
            el: '#app',
            data: {
                hobbies: [ ],
                allHobbies: ['篮球', '足球', '乒乓球', '羽毛球']
            }
        })
    </script>
    
  4. 使用修饰符

    1. lazy修饰符

      • 默认情况下v-model是实时同步输入框的数据的 (容易同步的过于频繁 )
      • lazy修饰符可以让数据在失去焦点或回车时才更新
      <input type="text" v-model.lazy="输入">
      
    2. number修饰符

      • 默认情况下,在输入框中无论输入的是字母还是数字,都会被当做String类型处理
      • 但是如果我们希望处理的是数组类型,那么最好直接将内容当做数字处理
    3. trim修饰符

      • 如果输入的内容首尾有很多空格,可以使用它去除