学静思语
Published on 2025-02-15 / 1 Visits
0
0

前端框架(Vue.js)

前端框架(Vue.js)

一、基本介绍

1.vue是什么

  • Vue(读音/vju:/,类似于view)是一个前端框架,易于构建用户界面
  • Vue的核心库只关注视图层,不仅易于上手,还便于与第三库或项目整合
  • 支持和其他类库结合使用
  • 开发复杂的单页应用非常方便
  • Vue是Vue.js的简称
  • 官网:https://cn.vuejs.org/
  • git地址:https://github.com/vuejs/vue

2.MVVM{M(model)-V(view)-VM(ViewModel)}

2.1原理图

MVVM-principle

2.2MVVM解读

  • M:即Model(模型),包括数据和一些基本操作
  • V:即View,视图,页面渲染结果
  • VM:即View-Model,模型与视图间的双向操作(无需开发人员干涉)
  • 在MVVM之前,开发人员从后端获取需要的数据模型,然后要通过DOM操作Model渲染到View中。而后当用户操作视图,我们还需要通过DOM获取View中的数据,然后同步到Model中
  • 而MVVM中的VM要做的事情就是把DOM操作完全封装起来,开发人员不用再关心Model和View之间是如何互相影响的
  • 只要我们Model发生了改变,View上自然就会表现出来

3.快速入门

3.1代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vue快速入门</title>
</head>
<body>
<script type="text/javascript" src="vue/vue.js"></script>
<!--
    1.div元素不是必须得,也可以是其他元素,比如span,但是约定都是将vue实例挂载到div
      因为div更适合做布局
    2.id 不是必须为app,是程序员自己决定的,但是一般就是使用app
    -->
<div id="app">
<!--
    1.{{message}}:插值表达式
    2.message 就是从Model的data数据池来获取或设置
    3.当我们的代码执行时,会到data{} 数据池中区匹配数据,如果匹配上,
      就进行替换,如果没有匹配上,就会输出空
    4.这个插值表达式只能在标签中使用,不能在属性中使用
-->
    <h1>你好-{{name}}-{{message}}</h1>


</div>

<script type="text/javascript">
/*
    1.并不是只可以有一个Vue对象,而是可以有多个Vue对象,
      但是如果不是特殊情况一个Vue对象就够了
    2.注意一定要写在被挂载的元素之后,否则会挂载失败
*/
    let vm = new Vue({
        el:"#app",//创建的vue实例挂载到id=app的div(也可以理解为挂载到id=app的标签),名字一定要和要挂载的标签名的id一样
        data:{//data{} 表示数据池(model有了数据),可以有很多数据,以k-v形式设置(根据业务需要来设置),名称由程序员制定,不是固定的
            name:"学静思语",
            message:"欢迎"
        }
    });

    console.log(vm)
</script>

</body>
</html>

3.2注意事项和使用细节

  • 注意代码顺序,要求被挂载的元素要放在最前面,否则无法绑定数据,也就是会挂载失败
  • Vue.js采用简洁的模板语法,来声明的将数据渲染进DOM的系统,做到数据和显示分离
  • Vue没有繁琐的DOM操作,如果使用JQuery,我们需要先找到div节点,获取到DOM对象,然后进行节点操作,显然Vue更加简洁

二、Vue简单的操作

1.数据单向渲染

1.1 基本说明

  • v-bind: 指令可以基本完成基本数据渲染/绑定
  • v-bind: 简写形式就是一个冒号(:)
  • 其是由Vue解析的

1.2 注意事项和使用细节

  • 插值表达式是用在标签体的
  • 如果给标签属性绑定值,则使用 v-bind: 指令

1.3 代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>单向渲染</title>
</head>
<body>
<script type="text/javascript" src="vue/vue.js"></script>
<div id="app">
    <!--
        1.使用插值表达式引用data数据池数据是在标签体内
        2.如果是在 标签/元素 的属性上去引用data数据池数据时,不能使用插值表达式,需要使用 v-bind:
        3.v-bind: 是由Vue来解析
        4.v-bind: 可以简写,简写就是一个(:)
    -->
    <h1>{{message}}</h1>

    <img v-bind:src="img_src" v-bind:width="width">
    <img :src="img_src" :width="width">

</div>
<script type="text/javascript">
    /*
        1.并不是只可以有一个Vue对象,而是可以有多个Vue对象,
          但是如果不是特殊情况一个Vue对象就够了
        2.注意一定要写在被挂载的元素之后,否则会挂载失败
    */
    let vm = new Vue({
        el:"#app",//创建的vue实例挂载到id=app的div(也可以理解为挂载到id=app的标签),名字一定要和要挂载的标签名的id一样
        data:{//data{} 表示数据池(model有了数据),可以有很多数据,以k-v形式设置(根据业务需要来设置),名称由程序员制定,不是固定的
            message:"hello!老鼠精",
            img_src:"img/1.jpg",
            width:"150px"
        }
    });

    console.log(vm)
</script>

</body>
</html>

2.数据双向渲染

2.1基本说明

  • v-bind: 是数据单向渲染:data数据池绑定的数据变化,会影响View,View的变化是不会影响data数据池的数据变化
  • v-model: 是数据的双向渲染
  • data数据池的数据变化会影响View的变化【底层的机制是Data Bindings】
  • View的变化会影响data数据池的数据变化【底层机制是 DOM Listeners】
  • v-model:value=““,可以进行数据双向渲染,v-model也可以进行数据双向渲染

2.2代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>数据双向渲染</title>
</head>
<body>
<script type="text/javascript" src="vue/vue.js"></script>
<div id="app">
    <!--
        1.v-bind: 是数据单向渲染:data数据池绑定的数据变化,会影响View,View的变化是不会影响data数据池的数据变化
        2.v-model: 是数据的双向渲染,data数据池的数据变化会影响View的变化,View的变化会影响data数据池的数据变化
        3.v-model:value="",可以进行数据双向渲染,v-model也可以进行数据双向渲染
    -->
    <h1>{{message}}</h1>
    <input type="text" v-model="hobby.val"><br>
    <input type="text" v-bind:value="hobby.val">
    <h2>你的爱好是:  {{hobby.val}}</h2>

</div>
<script type="text/javascript">
    /*
        1.并不是只可以有一个Vue对象,而是可以有多个Vue对象,
          但是如果不是特殊情况一个Vue对象就够了
        2.注意一定要写在被挂载的元素之后,否则会挂载失败
    */
    let vm = new Vue({
        el:"#app",//创建的vue实例挂载到id=app的div(也可以理解为挂载到id=app的标签),名字一定要和要挂载的标签名的id一样
        data:{//data{} 表示数据池(model有了数据),可以有很多数据,以k-v形式设置(根据业务需要来设置),名称由程序员制定,不是固定的
            message:"hello!请输入你的爱好",
            // 这里这样做是为了以后的拓展
            hobby:{
                val:"购物"
            }
        }
    });

    console.log(vm)
</script>

</body>
</html>

3.事件绑定

3.1基本说明

  • 使用 v-on 进行事件处理,比如: v-on:click 表示处理鼠标点击事件
  • 事件调用的方法定义在 vue 对象声明的 methods 节点中
  • v-on: 事件名 可以绑定指定事件

3.2注意事项和使用细节

  • 如果方法没有参数,可以直接省略()【需要浏览器支持】
  • v-on 指令的简写形式 @ 【需要浏览器支持】
  • 如果要知道可以绑定哪些事件,可以在浏览器控制台中查看$el–>childNodes可以绑定哪些事件

3.3 代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>事件绑定</title>
</head>
<body>
    <script type="text/javascript" src="vue/vue.js"></script>
    <div id="app">
        <h1>{{message}}</h1>
<!--
        1.v-on:click 表示我们要给button元素绑定一个click的事件
        2.sayHi() 表示绑定的方法,在方法池 methods{} 定义的
        3.底层仍是DOM编程
-->
        <button v-on:click="sayHi()">点击这里输出</button>
        <button v-on:click="sayOk()">点击这里输出</button>
        <button v-on:click="sayHi">点击这里输出</button>
        <button @click="sayOk">点击这里输出</button>
    </div>

    <script type="text/javascript">
        let vm = new Vue({
            el:"#app",
            data:{
                message:"Vue事件绑定",
            },
            // 1. methods 对应的值是一个对象
            // 2. 在{} 中,可以写很多的方法,可以理解为一个方法池
            methods:{
                sayHi(){
                    console.log("hi,金角大王")
                },
                sayOk(){
                    console.log("ok,银角大王")
                }
            }


        });
    </script>
</body>
</html>

4.修饰符

4.1修饰符基本介绍

  • 修饰符(Modifiers)是以(.)指明的后缀,指出某个指令以特殊方式绑定
  • 是为特殊情况做出的一种行为,来完成特定的业务逻辑
  • 学习网址:https://v2.cn.vuejs.org/v2/guide/events.html

4.2代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>修饰符</title>
</head>
<body>
<!--导入Vue -->
<script type="text/javascript" src="vue/vue.js"></script>
<!--创建容器-->
<div id="app">
        <!--创建一个from表单-->
<!--
        1.修饰符用于指出一个指令应该以特殊方式绑定
        2.v-on:submit.prevent中的.prevent 修饰符表示阻止表单提交的默认行为,然后执行指定的方法


-->
    <form action="http://baidu.com" v-on:submit.prevent="submit">
        <input type="text" v-model="monster.name"><br>
        <input type="submit" value="注册">
    </form>

<!--扩展部分-->
    <h1>修饰符扩展部分</h1>
<!--被绑定的按钮只能被单击一次,如果刷新界面的话还是可以再单击的,如果想实现只单击需要前后端一起实现-->
    <button v-on:click.once="click">点击一次</button>
<!--监听enter,特殊绑定-->
    <input type="text" v-on:keyup.enter="onsubmit">
    <input type="text" v-on:keyup.down="onsubmit">
<!--.trim就是把你输入框左右边的空格去除-->
    <input type="text" v-model.trim="monster.name">
</div>
<!--创建Vue对象-->
<script type="text/javascript">
    //定义Vue对象
    let vm = new Vue({
        el:"#app",
        data:{
            monster:{
            // 这里可以不定义属性,可以动态生成
            }
        },
        methods:{
            submit(){
                console.log("请输入名称",this.monster.name)
            },
            click(){
                console.log("被单击了")
            },
            onsubmit(){
                console.log("单击了enter键")
            }
        }
    });
</script>
</body>
</html>

5.条件渲染/控制:v-if/v-show

5.1 基本说明

  • v-if和v-show条件指令完成条件渲染/控制
  • v-if介绍
  • v-if 指令用于条件性的渲染一块内容,这块内容只会在指令的表达式返回true值的时候被渲染
  • 还有v-else和v-else-if指令,和java中的if-else-if差不多
  • v-show介绍
  • v-show 用于根据条件展示元素,用法大致与v-if一样

5.2 代码

  • v-if代码

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>修饰符</title>
    </head>
    <body>
    <!--导入Vue -->
    <script type="text/javascript" src="vue/vue.js"></script>
    <!--创建容器-->
    <div id="app">
          <input type="checkbox" v-model="check">是否同一条款【v-if实现】
    <!--
          1.这里v-if指令是从data数据池中取数据
          2.v-if/v-else 会根据 返回值来决定是否动态创建对应的子组件
    -->
          <h1 v-if="check">你同意了条款</h1>
          <h1 v-else>你不同意条款</h1>
    </div>
    <!--创建Vue对象-->
    <script type="text/javascript">
      //定义Vue对象
      let vm = new Vue({
          el:"#app",
          data:{
              check:false
          }
      });
    </script>
    </body>
    </html>
    
  • v-show代码

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>修饰符</title>
    </head>
    <body>
    <!--导入Vue -->
    <script type="text/javascript" src="vue/vue.js"></script>
    <!--创建容器-->
    <div id="app">
          <input type="checkbox" v-model="check">是否同一条款【v-show实现】
    <!--
          1.这里v-show指令是从data数据池中取数据
    -->
          <h1 v-show="check">你同意了条款</h1>
          <h1 v-show="!check">你不同意条款</h1>
    </div>
    <!--创建Vue对象-->
    <script type="text/javascript">
      //定义Vue对象
      let vm = new Vue({
          el:"#app",
          data:{
              check:false
          }
      });
    </script>
    </body>
    </html>
    

5.3 v-if和v-show的比对

  • v-if会确保在切换过程中,条件块内的事件监听和子组件销毁和重建
  • v-show机制相对简单,不管初始条件是什么,元素总是会被渲染,并且只是对CSS进行切换
  • 建议:如果要频繁的切换,建议使用v-show;如果运行时条件很少改变,使用v-if较好

6.列表渲染:v-for

6.1基本介绍

image-20240313205747666

image-20240313205835963

image-20240313205950844

image-20240313210030122

image-20240313210106052

image-20240313210145972

6.2代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>v-for遍历数据</title>
</head>
<body>
    <script type="text/javascript" src="vue/vue.js"></script>
    <div id="app">
        <h1>{{messages.test1}}</h1>
        <ul>
           <li v-for="num in nums">
               {{num}}
           </li>
        </ul>
        <h1>{{messages.test2}}</h1>
        <ul>
            <li v-for="(num,index) in nums">{{index}}-{{num}}</li>
        </ul>
        <h1>{{messages.test3}}</h1>
        <table border="2" width="400px">
            <tr v-for="(monster,index) in monsters">
                <td>{{index + 1}}</td>
                <td>{{monster.name}}</td>
                <td>{{monster.age}}</td>
            </tr>
        </table>
    </div>

    <script type="text/javascript">
        let vm = new Vue({
            el:"#app",
            data:{
                messages:{
                    test1:"简单列表渲染",
                    test2:"简单列表渲染-带下标",
                    test3:"遍历数据列表"
                },
                nums:[1,2,3],
                monsters:[{name:"牛魔王",age:100},{name:"孙悟空",age:100},{name:"哪吒",age:50}]
            }

        });

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

7.组件化编程

7.1 基本介绍

  • 组件(Component)是Vue.js最强大的功能之一
  • 组件也是一个Vue实例,也包括:data、methods、生命周期函数等
  • 组件渲染需要Html模板,所以增加了template属性,值就是HTML模板
  • 对于全局组件,任何Vue实例都可以直接在HTML中通过组件名称来使用组件
  • data是一个函数,不再是一个对象,这样每次引用组件都是独立的对象

7.2注意事项和使用细节

  • 如果方法体,只有简单的语句,比如count++,那么可以简写成v-on:click=“count++”
  • 组件定义需要放置在new Vue()前面,否则组件注册会失败

7.3代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>组件化编程-传统方式</title>
</head>
<body>
<!--引入Vue-->
<script type="text/javascript" src="vue/vue.js"></script>
<!--创建容器-->
<!--
    1.这种编程方式添加可很多属性,造成了业务数据的重复,没有体现复用性
    2.这种方式需要大量的方法,所以引入Vue的模块编程,也是Vue最强大的功能之一
-->
<div id="app">
    <button v-on:click="add">点击次数{{count}}次【非模块化编程】 </button><br>
    <button v-on:click="count2++">点击次数{{count2}}次【非模块化编程】 </button><br>
    <button v-on:click="count3++">点击次数{{count3}}次【非模块化编程】 </button><br>
    <counter></counter>
</div>
<!--创建Vue对象-->
<script type="text/javascript">
    let vm = new Vue({
        //进行挂载
        el:"#app",
        data:{
            count:10,
            count2:10,
            count3:10
        },
        methods:{
            add(){
                this.count++;
            },
        }


    });
</script>

</body>
</html>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>模块化编程-全局组件</title>
</head>
<body>
<!-- 引入vue-->
<script type="text/javascript" src="vue/vue.js"></script>
<!--创建容器-->
<div id="app">
    <counter></counter><br>
    <counter></counter><br>
    <counter></counter><br>

</div>
<!--创建Vue实例-->
<script type="text/javascript">
    // 创建全局组件
    //1.创建全局模块为counter的全局模块
    //2.{} 表示就是我们的组件相关的内容
    //3.temple 指定该组件的界面,也可以理解为HTML界面,因为会引用到数据池的数据,所以需要模板字符串
    //4.要把Vue组件视为一个Vue实例,也有自己的数据池和methods
    //5.对于组件,我们的数据池的数据,是使用函数/方法返回【目的是为了保证每个组件的数据是独立的】,因而不能使用原来的方式
    //6.这时就达到目的了,界面通过template实现共享,业务处理也复用了,但是记住这个不能再另一个界面使用
    Vue.component("counter",{
        template:`<button v-on:click="add">点击次数{{count}}次-非模块化编程</button>`,
        data(){//这里和原来的方式不同,为了保证每次的数据都是独立的,所以把这个data数据池改成了一个方法
            return {
                count:10
            }
        },
        methods:{
            add(){
                this.count++ ;
            }
        }
    });

    new Vue({
        el:"#app"
    });
</script>
</body>
</html>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>模块化编程-局部组件</title>
</head>
<body>
<!-- 引入vue-->
<script type="text/javascript" src="vue/vue.js"></script>
<!--创建容器-->
<div id="app">
    <counter></counter><br>
    <counter></counter><br>
    <counter></counter><br>

</div>
<!--创建Vue实例-->
<script type="text/javascript">
    // 创建局部组件
    //1.创建局部组件为counter的局部组件
    //2.该组件只能在引入的Vue中挂载的容器中使用,如果出了组件注册的容器,则不能使用
    //3.
    const  counter = {
        template:`<button v-on:click="add">点击次数{{count}}次-非模块化编程</button>`,
        data(){//这里和原来的方式不同,为了保证每次的数据都是独立的,所以把这个data数据池改成了一个方法
            return {
                count:10
            }
        },
        methods:{
            add(){
                this.count++ ;
            }
        }
    };

    let vm = new Vue({
        el:"#app",
    //   要进引入某个组件
    //   这个时候"counter"就是一个组件,是一个局部组件,它的使用范围只在当前的Vue可以使用
        components:{
            'counter':counter
        }
    });
</script>
</body>
</html>

三、vue的生命周期

1.vue的基本介绍

  • vue实例有一个完整的生命周期,也就是说从开始创建、初始化数据、编译模板、挂载DOM、渲染-更新、卸载等一系列过程,称为Vue实例的生命周期
  • 钩子函数(监听函数):Vue实例在完整的生命周期过程中(比如设置数据监听、编译模板、将实例挂载到DOM、在数据变化时更新DOM等),也会运行叫做生命周期钩子函数
  • 钩子函数的作用就是在某个阶段,给程序员一个做某些处理的机会

2.生命周期图

lifecycle

2.1图片解读

  • new Vue()
  • new 了一个Vue的实例对象,此时就会进入组件的创建过程
  • Init Events & Lifecycle
  • 初始化组件的事件和生命周期函数
  • beforeCreate
  • 组件创建之后遇到的第一个生命周期函数,这个阶段data和methods以及DOM结构都未被初始化,也就是获取不到data的值,不能调用methods中的函数
  • Init injections & reactivity
  • 这个阶段中,正在初始化data和methods中的方法
  • created
  • 这个阶段组件的data和methods中的方法已初始化结束,可以访问,但是DOM结构为初始化,页面未被渲染
  • 在这个阶段经常会发起Ajax请求,因为这个时候页面未被渲染,获取的数据可以及时的进行更新,然后渲染,保证页面所显示的是最新的数据
  • 编译模板结构(在内存中进行)
  • beforeMount
  • 当模板在内存中编译完成,此时内存中的模板结构还未渲染至页面上,看不到真实的数据
  • Create vm.$el and replace 'el' with it
  • 这一步,正在把内存中渲染好的模板结构替换至真实的DOM结构也就是页面上
  • mounted
  • 此时,页面渲染好,用户看到的是真实的页面数据,生命周期创建阶段完毕,进入到了运行中的阶段
  • 生命周期运行中
  • beforeUpdate
    • 当执行此函数,数据池的数据是新的,但是页面是之前的数据
  • Virtual DOM re-render and patch
    • 根据最新的data数据,重新渲染内存中的模板结构,并把渲染好的模板结构,替换至页面上
  • updated
    • 页面已经完成了更新,此时,data数据和页面的数据都是最新的
  • beforeDestroy
  • 当执行此函数时,组件即将被销毁,但还是没有真正开始销毁,此时组件的data、methods数据或方法还可以被调用
  • Teardown
  • 注销组件和事件监听
  • destroyed
  • 组件已经完成了销毁

3.代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>生命周期演示</title>
</head>
<body>
<!--引入Vue-->
<script type="text/javascript" src="vue/vue.js"></script>
<!--创建容器-->
<div id="app">
    <h2 id="num">{{num}}</h2>
    <button v-on:click="add">点赞</button>
    <h1>{{name}}有{{num}}次点赞</h1>
</div>
<!--创建Vue对象-->
<script type="text/javascript">
    let vm = new Vue({
        el:"#app",
        data:{
            num:0,
            name:"Kristina"
        },
        methods:{
            add(){
                this.num++;
            },
            show(){
                return this.num;
            }
        },
        beforeCreate(){//生命周期函数-创建Vue实例前
            console.log("====================beforeCreate====================");
            console.log("数据模型/数据池数据是否加载/能否使用[no]",this.num,"   ",this.name);
            // console.log("数据模型/方法池数据是否加载/能否使用[no]",this.show());
            console.log("页面DOM是否加载[yes]",document.getElementById("num"));
            console.log("页面DOM是否被渲染[no]",document.getElementById("num").innerText);

        },
        created(){//生命周期函数-创建Vue实例后
            console.log("====================created====================");
            console.log("数据模型/数据池数据是否加载/能否使用[yes]",this.num,"   ",this.name);
            console.log("数据模型/方法池数据是否加载/能否使用[yes]",this.show());
            console.log("页面DOM是否加载[yes]",document.getElementById("num"));
            console.log("页面DOM是否被渲染[no]",document.getElementById("num").innerText);
        },
        beforeMount(){//生命周期函数-挂载Vue实例前
            console.log("====================beforeMount====================");
            console.log("数据模型/数据池数据是否加载/能否使用[yes]",this.num,"   ",this.name);
            console.log("数据模型/方法池数据是否加载/能否使用[yes]",this.show());
            console.log("页面DOM是否加载[yes]",document.getElementById("num"));
            console.log("页面DOM是否被渲染[no]",document.getElementById("num").innerText);
        },
        mounted(){//生命周期函数-挂载Vue实例后
            console.log("====================mounted====================");
            console.log("数据模型/数据池数据是否加载/能否使用[yes]",this.num,"   ",this.name);
            console.log("数据模型/方法池数据是否加载/能否使用[yes]",this.show());
            console.log("页面DOM是否加载[yes]",document.getElementById("num"));
            console.log("页面DOM是否被渲染[yes]",document.getElementById("num").innerText);
        },
        beforeUpdate(){//生命周期函数-生命周期运行时数据被修改前
            console.log("====================beforeUpdate====================");
            console.log("数据模型/数据池数据是否加载/能否使用[yes]",this.num,"   ",this.name);
            console.log("数据模型/方法池数据是否加载/能否使用[yes]",this.show());
            console.log("页面DOM是否加载[yes]",document.getElementById("num"));
            console.log("页面DOM是否被渲染[no]",document.getElementById("num").innerText);
        },
        updated(){//生命周期函数-生命周期运行时数据被修改后
            console.log("====================updated====================");
            console.log("数据模型/数据池数据是否加载/能否使用[yes]",this.num,"   ",this.name);
            console.log("数据模型/方法池数据是否加载/能否使用[yes]",this.show());
            console.log("页面DOM是否加载[yes]",document.getElementById("num"));
            console.log("页面DOM是否被渲染[yes]",document.getElementById("num").innerText);
        }



    });
</script>
</body>
</html>

Comment