学习笔记:尚硅谷Vue2基础篇

发布于:2024-04-30 ⋅ 阅读:(69) ⋅ 点赞:(0)

Vue2

  1. 学习笔记:Vue2基础篇_ljtxy.love的博客-CSDN博客
  2. 学习笔记:Vue2中级篇_ljtxy.love的博客-CSDN博客
  3. 学习笔记:Vue2高级篇_ljtxy.love的博客-CSDN博客

Vue3

  1. 学习笔记:Vue3_ljtxy.love的博客)-CSDN博客

    文章目录

1.概述

笔记小结:

  1. 定义:Vue 3 是一种流行的构建用户界面渐进式JavaScript前端框架
  2. 特点:组件
  3. 周边库:axios、vue-cli、vue-resource、vue-router、vuex、element-ui

1.1定义

​ Vue 3 是一种流行的构建用户界面渐进式JavaScript前端框架,用于构建用户界面和单页应用程序(SPA)。它是 Vue.js 框架的第三个主要版本,是对 Vue.js 2 的重大升级和改进。Vue 3 专注于提升性能**、可维护性和**开发体验,引入了许多新的特性和改进

官方网站:简介 | Vue.js (vuejs.org)

image-20221101134932545

说明:

​ 渐进式:Vue可以自底向上逐层的应用简单应用:只需一个轻量小巧的核心库。复杂应用:可以引入各式各样的Vue插件

1.2特点

​ 采用组件化模式,提高代码复用率、且让代码更好维护。采用组件化模式,提高代码的复用率、让代码更好维护、声明式编码,让用户无需再操作DOM,提高开发的效率、使用虚拟DOM加上优秀的DIFF算法,尽量复用DOM节点

image-20221101135220149

说明:

​ 组件化:每一个组件都是用HTML、CSS、JS代码组成

1.3周边库

  • vue-cli:vue脚手架
  • vue-resource:插件
  • axios:异步请求
  • vue-router:路由
  • vuex:状态管理
  • element-ui:基于vue的UI组件库(PC端)

2.基本用例-单文件Vue使用(了解)

笔记小结:

​ 步骤:导入相应Vue.js文件创建Vue实例编写实例

步骤一:新建HTML页面,引入Vue.js文件

 <script src="js/vue.js"></script>

步骤二:在JS代码区域,创建Vue核心对象,进行数据绑定

 <script>
    new Vue({
      el:"#app",// el用于指定当前Vue实例为哪个容器服务,值通常为css选择器字符串。
      data:{// data中用于存储数据,数据供el所指定的容器去使用,值我们暂时先写成一个对象。
          name:""
        }
    })
  </script>

说明:

  • Vue实例和容器是一一对应的,也就是说一个 new Vue({})对于一个容器。
  • root容器里的代码依然符合html规范,只不过混入了一些特殊的Vue语法;

补充:

​ 一个root容器里的代码被称为【Vue模板】;

步骤三:编写视图

<body>
    <!--3.编写视图-->
    <div id="app">
        <input name="username" v-model="username">
        <!--插值语法-->
        {{username}} <!--{{xxx}}中的xxx要写js表达式,且xxx可以自动读取到data中的所有属性;-->
    </div>
</body>

补充:

  • 一旦data中的数据发生改变,那么页面中用到该数据的地方也会自动更新;
  • 真实开发中只有一个Vue实例,并且会配合着组件一起使用;

3.选项式API

笔记小结:请查看各个小节

3.1模板语法

笔记小结:

  1. 概述:Vue 使用一种基于 HTML 的模板语法,使我们能够声明式地将其组件实例的数据绑定到呈现的 DOM 上。
  2. 分类:
    • 插值语法:
      • 概述:{{ xxx }},xxx是js表达式
      • 功能:可以直接读取到data中的所有属性,也就是渲染data里面的数据
    • 指令语法:
      • 概述:v-bind :href="xxx”或简写:href=“xxx”,xxx同样要写js表达式
      • 功能:用于解析标签(包括:标签属性、标签体内容、绑定事件…) ,且可以直接读取data中的所有属性
  3. 补充:
    • v-bind:可以用来执行运算执行函数,若绑定的内容为js表达式则可以执行运算,若绑定的内容为data数据中的函数则可以执行函数
    • Vue中有很多的指令,且形式都是: v-???,此处我们只是拿v-bind举个例子

3.1.1概述

​ Vue 使用一种基于 HTML 的模板语法,使我们能够声明式地将其组件实例的数据绑定到呈现的 DOM 上。所有的 Vue 模板都是语法层面合法的 HTML,可以被符合规范的浏览器和 HTML 解析器解析。

3.1.2插值语法

{{ }}大括号,也是最常用的取值符号,用来渲染data里面的数据

<body>
    <a >点我去{{school.name}}学习1</a> <!--插值语法-->
</body>
<script>
    ……
    data:{
        name: "jack",
            school:{
                name:'尚硅谷',
                url: ' http://www.atguigu.com'
            }
    }
    ……
</script>

补充:

  • 绑定数据时可以使用.(点号)作为分隔符
<a v-bind:href="school.url.toUpperCase()" x="hello">点我去{{school.name}}学习1</a>

3.1.3指令语法

  • v-bind指令,给标签里的任何一个属性(属性可以自定义)动态的绑定值,让引号里面的东西当成js表达式来执行
<a v-bind:href="ur1">点我去尚硅谷学习1</a>
<!-- 简写为冒号-->
<a :href="ur1">点我去尚硅谷学习1</a>

说明:

​ 上面这种 v-bind 这也是我们对于 vue 指令最初的理解,但实际上,vue 指令的预期值(如 v-bind:class="classProperty" 中,v-bind 是指令,: 后面的 class 是参数,而 classProperty 则在官方文档中被称为“预期值”),除了像上面那样绑定一个字符串类型变量,其实它是支持一个单一 JavaScript 表达式v-for 除外)

  • 执行运算
<div id="app">
 <p v-bind:title="t1 + ' ' + t2">html属性不能使用双大括号形式绑定,只能使用v-bind指令</p>
</div>
......
var vm = new Vue({
 el: '#app',
 data: {
     t1: 'title1',
     t2: 'title2'
 }
});

说明:

  • 最终渲染
<div id="app">
 <p title="title1 title2">html属性不能使用双大括号形式绑定,只能使用v-bind指令</p>
</div>
  • 执行函数
<div id="app">
 <p v-bind:title="getTitle()">html属性不能使用双大括号形式绑定,只能使用v-bind指令</p>
</div>
......
var vm = new Vue({
 el: '#app',
 data: {
     getTitle: function () {
         return 'title content';
     }
 }
});

说明:

  • 最终渲染
<div id="app">
<p title="title content">html属性不能使用双大括号形式绑定,只能使用v-bind指令</p>
</div>

3.1.4案例—姓名展示

<!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>
    <script src="../js/vue.js" type="text/javascript"></script>
  </head>
  </head>
  <body>
    <div id="root">
      姓:<input type="text" v-model="firstname"><br><br>
      名:<input type="text" v-model="lastname"><br><br>
      全名:{{firstname}}-{{lastname}}
    </div>
    <script>
       Vue.config.productionTip = false;
       new Vue({
           el: '#root',
           data: {
            firstname:"宝宝",
            lastname:"玥玥"
           }
       })
    </script>
  </body>
</html>

补充:

​ 这里的V-model指令,是数据双向绑定的意识,详细请查看下一小节

3.2数据绑定

笔记小结:

  1. 概述:Vue的数据绑定是指将数据模型用户界面之间建立起的连接,也就是将data里面的数据显示在标签中
  2. 分类:
    • **单向绑定(**v-bind):数据只能从data流向页面
    • 双向绑定(v-model):数据不仅能从data流向页面,还可以从页面流向data。而双向绑定一般都应用在表单类元素上(如:input、select等)。v-model:value可以简写为v-model,因为v-model默认收集的就是value值
  3. 挂载与响应式对象:
    • el有2种写法:
      1. new Vue时候配置el属性
      2. 先创建Vue实例,随后再通过vm.$mount( ’ #root ')指定el的值
    • data有2种写法
      1. 对象式
      2. 函数式
      3. 补充:目前哪种写法都可以,以后学习到组件时,data必须使用函数式,否则会报错
    • 注意:由Vue管理的函数,一定不要写箭头函数,一旦写了箭头函数,this就不再是Vue实例了

3.2.1概述

​ Vue的数据绑定是指将数据模型用户界面之间建立起的连接,使得数据的变化可以自动反映在界面上,同时用户界面上的交互操作也可以影响数据模型的变化。这种双向的数据同步机制使得开发者能够更轻松地管理和维护用户界面和数据之间的一致性。

3.2.2单向与双向绑定

v-bindv-model都是Vue框架中用于数据绑定的指令,但它们在应用的场景和功能上有一些区别。

  1. v-bind

    • v-bind用于实现从数据到界面的单向数据绑定,将数据模型中的值绑定到HTML元素的属性上。
    • 使用方式:v-bind:属性名="数据模型中的属性"或简写为:属性名="数据模型中的属性"
    • 示例:<img :src="imageUrl">会将imageUrl的值绑定到src属性上,实现图片的动态加载
  2. v-model

    • v-model用于实现双向数据绑定,将表单元素的值与数据模型中的属性双向关联。主要用于表单元素(如input、textarea、select)。
    • 使用方式:v-model="数据模型中的属性"
    • 示例:<input v-model="username">会将输入框的值与username属性双向绑定,输入框中的值变化会影响username的值,反之亦然。

    总结:

    • 如果你想将数据模型中的值绑定到HTML元素的属性上,使用v-bind
    • 如果你需要在表单元素和数据模型之间实现双向绑定,使用v-model

说明:

​ 详细参考:内置指令 | Vue.js (vuejs.org)

3.2.3挂载与响应式对象写法

  • El:正常挂载和手动挂载(了解)
<script> // 格式
    el:"#root" // 正常挂载
    v.$mount("#root") //手动挂载
</script>
<script> //示例
    const v = new Vue({
        //el: '#root',//第一种写法
    })
    console.log(v)
    v.$mount("#root")//第二种写法*/
</script>
  • data:对象式和函数式(掌握)
<script> //格式
    data:{name:'尚硅谷'}
    data(){return {name:'尚硅谷'}}
</script>

<script> //示例
    new Vue({
        el : "#root",
        /*data:{name:'尚硅谷'}*/ // data的第一种写法:对象式(了解)
        data(){   //data的第二种写法:函数式
            return{
                name:"尚硅谷"
            }
        }
    })
</script>

补充:

vue组件可能会有很多个实例,采用函数返回一个全新data形式,使每个实例对象的数据不会受到其他实例对象数据的污染

3.3指令

笔记小结:

  1. 概述:指令就是Vue模板中添加特定功能的特殊属性
  2. 分类:
    1. 内置指令
      • 数据绑定:v-bind 简写为 :例如 :value=“xxx”、v-model:value 简写为 v-model 例如 v-model=“xxx”
      • 事件绑定:v-on 简写为 @ 例如 @click=“xxx”
      • 数据遍历:v-for:遍历数组、对象、字符串
      • 条件渲染:条件渲染if/else/if-else/show。if动态控制节点是否存在、show动态控制节点是否展示
      • 数据渲染:v-text:向其所在的节点中渲染文本内容、v-once:节点在初次动态渲染后,就视为静态内容了、v-cloak:本质是一个特殊属性,Vue实例创建完毕并接管容器后,会删掉v-cloak属性
      • 数据编译:v-pre:跳过其所在节点的编译过程
      • 数据插入:v-html,向指定节点中渲染包含html结构的内容。注意不能乱使用,防止外人页面插入!
  3. 自定义指令:详细请查看本小节

3.3.1概述

​ Vue指令是用于在Vue模板中添加特定功能的特殊属性。它们以 v- 作为前缀,并在模板中绑定到DOM元素上。Vue提供了多个内置指令,每个指令都有特定的功能和用途。

​ 指令分为内置指令和自定义指令

3.3.2内置指令

3.3.2.1数据绑定bind/model

v-bind:单项绑定解析表达式:可简写为 :xxx

v-model:双向数据绑定,可以替代value

3.3.2.2事件绑定on

v-on:绑定事件监听,可简写为@

3.3.2.3数据遍历for

v-for:遍历数组、对象、字符串

3.3.2.4条件渲染if/else/if-else/show

v-if:条件渲染(动态控制节点是否存在)

v-else:条件渲染(动态控制节点是否存在)

v-if-else:条件渲染(动态控制节点是否存在)

v-show:条件渲染(动态控制节点是否展示)

3.3.2.5数据渲染text/once/cloak
  • v-text:向其所在的节点中渲染文本内容

补充:

与插值语法的区别: v-text会替换掉节点中的内容,{{xx}}则不会

  • v-once:节点在初次动态渲染后,就视为静态内容了。

补充:

  • 以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能
<div id="root">
    <h2 v-once>初始化的n值是:{{n}}</h2>
    <h2>当前的n值是:{n}}</h2>
    <button @click="n++">点我n+1</button>
</div>

<script type="text/javascript">
    new Vue({
        el: "#root",
        data:{
        n:1}
</script>    
  • v-cloak:本质是一个特殊属性,Vue实例创建完毕并接管容器后,会删掉v-cloak属性。

说明:

  • 使用css配合v-cloak可以解决网速慢时页面展示出{{xxx}}的问题。
<style>
[v-cloak]{
	display:none;
}
</style>
<body>
	<h2 v-cloak>{{name}}</h2>
</body>
3.3.2.6数据编译pre

v-pre:跳过其所在节点的编译过程。

说明:

  • 可利用它跳过:没有使用指令语法、没有使用插值语法的节点,会加快编译
<h2 v-pre>Vue其实很简单</h2>
  • 这样,当Vue看到时,就会直接渲染跳过编译,加快了编译的速度
3.3.2.7数据插入html

v-html:向指定节点中渲染包含html结构的内容

补充:

​ 与插值语法的区别:v-html会替换掉节点中所有的内容,{{xx}}则不会、v-htm1可以识别html结构

注意:

  • v-html有安全性问题!!!
  • 在网站上动态渲染任意HTML是非常危险的,容易导致XSS攻击。
  • 一定要在可信的内容上使用v-htm1。永不要用在用户提交的内容上!

补充:XXS攻击

  • XSS攻击通常指的是通过利用网页开发时留下的漏洞,通过巧妙的方法注入恶意指令代码到网页,使用户加载并执行攻击者恶意制造的网页程序。可以识别html结构
<div v-html="str"></div>
<script>
new vue({el : ' #root',
	data:{
	name:"尚硅谷',
	str: '<h3>你好啊!</h3>'
	}
})
</script>
  • 此时页面上会显示vue实例中的内容

    image-20221115003137567

3.3.3自定义指令

笔记小结:

  1. 概述:当内置指令满足不了使用时,可使用自定义指令
  2. 定义语法:
    1. 局部指令:
      new Vue({directives:{指令名:配置对象})或new Vue({directives{指令名**:回调函数**}})
    2. 全局指令:
      Vue.directive(指令名,配置对象)或 Vue.directive(指令名,回调函数)
  3. 注意:配置对象中常用的3个回调
    1. bind:指令与元素成功绑定时调用。
    2. inserted:指令所在元素被插入页面时调用。
    3. update:指令所在模板结构被重新解析时调用。
  4. 备注:
    1. 指令定义时不加v-,但使用时要加v-;
    2. 指令名如果是多个单词,要使用kebab-case命名方式,不要用camelCase命名

方式一:全局指令

/*格式:
    方式一:Vue.directive(指令名,配置对象)
    方式二:Vue.directive(指令名,回调函数)
*/
<script>
    Vue.directive( ' fbind' ,{
        //指令与元素成功绑定时(一上来)
        bind(element,binding){ // 指令生命钩子 bind、inserted、update
            element.value = binding.value
        },
        //指令所在元素被插入页面时
        inserted(element,binding){
            element.focus()
        },
        //指令所在的模板被重新解析时
        update(element,binding){
            element.value = binding.value
        }
    })
</script>

方式二:局部指令

/* 格式
    方式一:new Vue({															
           		 directives:{指令名:配置对象}   
            }) 
    方式二:new Vue({															
           		 directives:{指令名:回调函数}   
            }) 
*/

<body>
    <div id="root">
        <h1><span v-text="n"></span></h1>
        <h2>放大10倍后的n值是:<span v-big="n"></span></h2>
        <button @click="n++">点我n+1</button><br><br>
        <input type="text" v-fbind="n">
    </div>
</body>

<script>
    new Vue({
        el: '#root',
        data: {
            n:1
        },
        directives:{
            big(element,binding){// 指令函数式写法
                element.innerHTML=binding.value*10  
                console.log(element);    //<span>10</span>             
                console.log(binding);	 //value对象
            },
            fbind:{ //指令对象方式写法
                //当指令与元素成功绑定时(一上来),执行此方法
                bind(element,binding){            
                    element.value=binding.value      
                    console.log("bind")       
                },
                //当指令所在元素被插入页面时,执行此方法
                inserted(element,binding){
                    element.focus()
                    console.log("focus")
                },
                //当指令所在的模板被重新定义时,执行此方法
                update(element,binding){
                    element.value=binding.value 
                    console.log("update")
                }
            }
        }
</script>

补充:

  • element代表此标签,binding代表此对象

image-20221116101010642

补充:

  • 指令名为多个单词时采用kebab-case命名方式,例如:big-number

  • camelCase命名方式为小驼峰命名方法例如backgroundColor

补充:

       directives:{
             //函数式会直接跳过inserted命令,也没有对外提供方法
             fbind(element,binding){
                 element.value=binding.value
                 element.focus()
             }
         }

3.3事件处理

笔记小结

  1. 概述:通过事件处理来响应用户的交互动作。例如点击、输入等等
  2. 基本用例:
  3. 绑定事件
  4. 配置事件函数
  5. 注意:
    1. 使用v-on :xxx或**@**xxx绑定事件,其中xxx是事件名;
    2. 事件的回调需要配置在methods对象中,最终会在vm上;
    3. methods中配置的函数,不要用箭头函数!否则this就不是vm了;
    4. methods中配置的函数,都是被Vue所管理的函数,this的指向是vm或组件实例对象;
    5. @click="demo”和click="demo($event)”效果一致,但后者可以传参;
  6. 事件修饰符:详细查看本小节
<!--事件修饰符可以连续写-->
<a href="http://www.atguigu.com" @click.prevent.stop="showInfo">点我提示信息</a>
<!--特殊的ctrl+y后松开y才可执行-->
<input type="text" placeholder="按下回车提示输入" @keyup.ctrl.y="showInfo">
<!--传递参数加小括号-->
<button @click="showInfo1">点我提示信息1(不传参)</button>
<button @click="showInfo2($event,66)">点我提示信息2(传参)</button>

3.3.1概述

​ 在Vue中,你可以通过事件处理来响应用户的交互动作,例如点击、输入等。Vue提供了一些指令来处理事件,以及一种用于在组件中定义和触发自定义事件的机制。

3.3.2基本用例-事件处理

步骤一:绑定点击事件

<button v-on:click="showInfo">点我提示信息</button><!--当你点击button的时候,Vue就会帮你找showInfo的函数 -->

补充:

​ 使用v-on :xxx或**@x**xx绑定事件,其中xxx是事件名;

步骤二:实现方法

<script>
    ……
        <!--通过methods来接收 -->
    methods: {
        showInfo(event, number) {<!--当点击事件的时候,会默认传入一个event对象-->
            console.log(event, number);
            console.log(event.target);<!--<button>点我提示信息</button> -->
            alert("OK!");
        }
    }
</script>

注意:

  • 事件的回调需要配置在methods对象中,最终会在vm上;
  • methods中配置的函数,不要用箭头函数!否则this就不是vm了;
  • methods中配置的函数,不要用箭头函数!否则this就不是vm了;

补充:

​ event.target可以获取当前绑定方法的对象,也就是获取自己,包括整个标签.。target事件属性课返回事件的目标节点(触发该事件的节点),如生成事件的元素、文档或窗口

3.3.3事件修饰符

笔记小结:

  • 概述:Vue 事件修饰符是用于 v-on 指令(或简写 @)的特殊后缀,用于对 DOM 事件的行为进行**额外的控制**。
  • 常用修饰符:
    • prevent:阻止默认事件(常用)
    • stop:阳止事件目治(常用)
    • once:事件只触发一次(常用)
  • capture:使用事P的撒获模式;
  • self:只有event.target是当前操作的元素是才触发事件;
  • passive:事件的默认行为立即执行,无需等待事件回调执行完毕;
3.3.3.1概述

​ Vue 事件修饰符是用于 v-on 指令(或简写 @)的特殊后缀,用于对 DOM 事件的行为进行额外的控制。它们可以在触发 DOM 事件时对事件传递的信息进行修改或对默认行为进行干预。

3.3.3.2Prevent(常用)
  • 阻止默认事件
<a href="http://www.atguigu.com" @click.prevent="showInfo">点我提示信息</a>

说明:

​ 在以下情况下有用:单击"提交"按钮,阻止其提交表单单击链接,防止链接跟随UR

3.3.3.3Stop(常用)
  • 阻止事件冒泡
<div class="demo1" @click="showInfo">
	<button @click.stop="showInfo">点我提示信息</button>
</div>

说明:

​ 通常情况下,div与button标签都绑定点击事件会触发两次点击。若使用stop时间修饰符则只会触发最外层的一次点击

3.3.3.4Once(常用)
  • 事件只触发一次
<button @click.once="showInfo">点我提示信息</button>

说明:

​ 此点击只会触发一次点击事件,点击多次无效

3.3.3.5Capture
  • 使用事P的撒获模式;
<div class="box1"@click="showMsg(1)">
	div1
    <div class="box2"@click="showMsg(2)">
   		 div2
    </div>
</div>

说明:

​ capture修饰符可以实现与事件冒泡的方向相反,事件捕获由外到内。

3.3.3.6Self
  • 只有event.target是当前操作的元素是才触发事件;
<div class="demo1" @click.self="showInfo">
	<button @click="showInfo">点我提示信息</button>
</div>
3.3.3.7Passive
  • 事件的默认行为立即执行,无需等待事件回调执行完毕;
<ul @wheel.passive="demo" class="list">
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
</ul>

3.3.4键盘事件

笔记小结:

  1. 概述:在 Vue 中,你可以使用 v-on 指令(或简写 @)来监听和处理键盘事件
  2. 常用事件:
  • 回车 =>enter
  • 删除=>delete(捕获删除”和“退格”健)退出=>esc
  • 空格=>space
  • 换行=> tab(特殊,必须配合keydown去使用)
  • 上=>up
  • 下=> down
  • 左=>left
  • 右=> right
  1. 注意:Vue未提供别名的按键,可以使用按键原始的key值去绑定,但注意要转为kebab-case(短横线命名)
  2. 系统修饰健(用法特殊):ctrl、alt、shift、meta
  • 配合keyup使用:按下修饰键的同时,再按下其他键,随后释放其他键,事件才被触发
  • 配合keydown使用:正常触发事件
  1. 也可以使用keyCode去指定具体的按键(不推荐)
  2. vue.config.keyCodes.自定义健名=健码,可以去定制按健别名
3.3.4.1概述

​ 在 Vue 中,你可以使用 v-on 指令(或简写 @)来监听和处理键盘事件

说明:

​ 参考资料:详解在vue项目当中绑定键盘事件_vue keypress_任磊abc的博客-CSDN博客

3.3.4.2基本用例-使用演示

步骤一:绑定点击事件

<button @keydown.enter="xx">click me</button>

说明:

​ 当按下这些键盘上的特殊键的时候就可触发相应的动作

补充:

  • 回车 =>enter
  • 删除=>delete(捕获删除”和“退格”健)退出=>esc
  • 空格=>space
  • 换行=> tab(特殊,必须配合keydown去使用)
  • 上=>up
  • 下=> down
  • 左=>left
  • 右=> right

步骤二:实现点击回调

<script>
    ……
    methods:{
        xx(event){
            console.log(event)
        }
        ……
</script>

3.4计算属性

笔记小结:

  1. 概述:在 Vue 中,计算属性(Computed Properties)是一种用于在模板中动态计算值的属性。当要用的属性不存在或要通过已有属性计算得来时使用
  2. 原理:底层借助了objcet.defineproperty方法提供的gettersetter(详细,请查看本小结原理)
  3. 补充:get函数什么时候执行?
  • 初次读取时会执行一次。
  • 当依赖的数据发生改变时会被再次调用。
  1. 优势:与methods实现相比,内部有缓存机制(复用),效率更高,调试方便。
  2. 备注:
  • 计算属性最终会出现在vm上,直接读取使用即可。
  • 如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生

3.4.1概述

​ 在 Vue 中,计算属性(Computed Properties)是一种用于在模板中动态计算值的属性。计算属性的值会根据它们依赖的响应式属性的变化而自动更新,而且计算属性会缓存结果,只有在其依赖的响应式属性发生变化时才会重新计算。

3.4.2基本用例-计算属性使用

步骤一:定义模板

<div id="root">
      姓:<input type="text" v-model="firstname"><br><br>
      名:<input type="text" v-model="lastname"><br><br>
      全名:{{fullname}}
</div>

步骤二:实现属性计算

说明:

​ 计算属性可以再模板中应用对象或者函数的形式

  • 利用computed属性,实现计算功能
<script>
    ……
    /*
    computed:{
        fullname:{
            get(){ // 获取
                return this.firstname + this.lastname
            },
                set(value){
                    const arr=value.split("-")
                    this.firstname=arr[0]
                    this.lastname=arr[1]
                }
        }
    }*/

    computed:{   // 计算属性的简写形式
        fullname:()=>{   // 箭头函数与fullname:function的写法是一样的
            console.log(this)
            return this.firstname + "-" + this.lastname
        }
    }
</script>

说明:

​ 当输入新的姓名时,全名属性会发生改变

3.4.3案例—姓名展示

说明:

​ 演示计算属性的用法

<!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>
  <script src="../js/vue.js" type="text/javascript"></script>
</head>
</head>
<body>
  <!-- data里面的数据一发生变化,模板重新解析 -->
  <div id="root">
    姓:<input type="text" v-model="firstname"><br><br>
    名:<input type="text" v-model="lastname"><br><br>
    全名:{{fullname}}
  </div>
  <script>
    Vue.config.productionTip = false;
    const vm= new Vue({
        el: '#root',
        data: {
          firstname:"唐",
          lastname:"昕玥",
        },
       /*
       computed:{   // 计算属性的简写形式
            fullname:()=>{   // 箭头函数与fullname:function的写法是一样的
              console.log(this)
              return this.firstname + "-" + this.lastname
            }
          }
          */
        computed:{
          fullname:{
            get(){
              return this.firstname +this.lastname
            },
            set(value){
              const arr=value.split("-")
              this.firstname=arr[0]
              this.lastname=arr[1]
            }
          }
        }
    })
    
  </script>
</body>
</html>

3.5监视属性

笔记小结:

  1. 概述:在 Vue 中,你可以使用“监视”(Watch)来监听响应式数据的变化,并在数据变化时执行相应的操作。当需要对监视的属性发生变化时进行回调函数的操作进行使用。监视内有
  2. 注意:
  3. 当被监视的属性变化时,回调函数自动调用,进行相关操作
  4. 监视的属性必须存在,才能进行监视!!
  5. 监视的两种写法:
    • new Vue时传入watch配置
    • 通过vm.$watch监视
  6. 深度监视:
  • Vue中的watch默认不监测对象内部值的改变(一层)
  • 配置deep:true可以监测对象内部值改变(多层)
  1. 备注:
  • vue自身可以监测对象内部值的改变,但Vue提供的watch默认不可以!
  • 使用watch时根据数据的具体结构,决定是否采用深度监视。
  1. 原理:检测数据的原理,详细请查看本小节

3.5.1概述

​ 在 Vue 中,你可以使用“监视”(Watch)来监听响应式数据的变化,并在数据变化时执行相应的操作。监视可以用于观察特定的数据属性,当这些属性发生变化时,执行一些自定义的逻辑。

注意:

​ 监视的属性必须存在,才能进行监视!!

3.5.2基本用例-监视属性使用

方式一:在创建Vm实例的时候就明白要监听谁

<script>
    ……
    watch:{
        isHot:{
            immediate:true, //初始化时调用一下该方法中的handler
            handler(newValue,oldvalue){
                console.log(newValue,oldvalue) //监听属性里面可以纯在新值与旧值
        }
    }
</script>

说明:

​ Handler是个函数,isHot是data对象里面的一个属性

方式二:创建Vm实例后根据用户需求做的操作来增加监听

<script>
    vm.$watch("isHot",{
        immediate:true,
        handler(newValue,oldvalue){
            console.log(newValue,oldvalue)}
    })
</script>

3.5.3深度监视

<script>
data:{
    isHot:false,
    number:{
            a:100,
            b:200,
		}
}
//监视多级结构中所有属性的变化
numbers:{
    deep:true, // 开启深度监视
    handler(){
	console.log( ' numbers改变了')
}
</script>

说明:

​ 若未开启深度监视功能,则对象里面的属性值将无法进行更改

3.5.4监视的简写形式

说明:

​ 当监听内容只有handler的时候适合简写形式

方式一:正常写法

<script>
/*isHot:{
	//immediate:true,//初始化时让handler调用一下
	//deep:true,//深度监视
	handler(newValue,oldValue){
	console.log( 'isHot被修改了', newValue, oldValue)}
}
*/
//简写
isHot(newValue,oldvalue){console.log( 'isHot被修改了',newValue,oldValue)}
</script>

方式二:手动方式

<script>
/*vm.$watch( ' isHot",i
	immediate:true,//初始化时让handler调用一下deep:true,//深度监视
	handler(newValue,oldValue){
	console.log( ' isHot被修改了' , newValue,oldValue)}
})
*/
vm.$watch( ' isHot " ,function(newValue,oldValue){
console.log( 'isHot被修改了',newValue,oldValue)})
</script>

3.5.5监测数据的原理✳

笔记小结:

  • 概述:vue会监砚data中所有层次的数据。

  • 问题:

    1. 如何监测对象中的数据?

      通过setter实现监视,且要在new Vue时就传入要监测的数据。

      1. 对象中后追加的属性,Vue默认不做响应式处理
      2. 如需给后添加的属性做响应式,请使用如下API:
        Vue.set(target.propertyName/index,value)或vm.$set(target.propertyName/index,value)
    2. 如何监测数组中的数据?

      通过包裹数组更新元素的方法实现,本质就是做了两件事:

      • 调用原生对应的方法对数组进行更新。
      • 重新解析模板,进而更新页面。
    3. 在Vue修改数组中的某个元素一定要用如下方法:

      • 使用这些API:push()、pop()、shift()、unshift()、splice()、sort()、reverse()
      • vue.set()或vm.$set()
3.5.5.1监听数据之对象

前提:

​ 需要明白MVVM模型,需要了解数据代理的原理

image-20221114202121470

说明:

​ 当对象的数据发生改变时,也就意味着模型发送了改变。数据会被数据代理Object.defineProperty方法给监测到。其后数据发送给VM进行响应式数据的更新。然后加载到视图中。

补充:

​ 详细参考:034_尚硅谷Vue技术_Vue监测数据的原理_对象_哔哩哔哩_bilibili

  • 模拟一个数据监测
<!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>
    <script type="text/javascript">
      // 1.创建一个data数据
      let data = {
        name: "温暖的家",
        address: "上海",
      };
      // 2.创建一个监视对象,用于监视data中的属性变化
      const obs = new Observer(data);
      console.log(obs);
      // 3.准备一个VM实例对象
      let vm = {};
      vm._data = data = obs;

      function Observer(obj) {
        //汇总对象中所有的属性形成一个数组
        const keys = Object.keys(obj);
        //遍历
        keys.forEach((k) => {
          Object.defineProperty(this, k, {
            get() {
              return obj[k];
            },
            set(val) {
              console.log("OK!vm开始工作!!!");
              obj[k] = val;
            },
          });
        });
      }
    </script>
  </body>
</html>
3.5.5.2Vue.set()方法
<script>
    Vue.config.productionTip = false;
    new Vue({
        el: '#root',
        data: {
            students:{
                name:"张三",
                age:18,
            }
        },
        methods: {
            addSex(){
                // Vue.set(this.students,"sex","男")
                this.$set(this.students,"sex","男")
            }
        },
    })
</script>

说明:set方法

image-20221114233204520

3.5.5.3监测数据原理之数组

image-20221114233619177

<script>
    data:{
        student:{
            name: " tom',age:18,
            hobby:["抽烟","喝酒",'烫头'],
            friends:[{name : "jerry" ,age:35},{name : "tony " ,age:36}]
    }
    //数组对象
    updateFirstFriendName{
        this.student.friends[0].name ="张三"
        this.student.friends[0].age = 5
    }
    //数组
    updateHobby(){
        // this.student.hobby.splice(0,1,'开车')
        // Vue.set(this.student.hobby,0, '开车')
        this.student.hobby.splice(0,1,'开车')
    }
</script>    

3.5.6案例—天气展示-普通

说明:

​ 演示普通监听的用法

<!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>
    <script src="../js/vue.js" type="text/javascript"></script>
  </head>
  </head>
  <body>
    <div id="root">
      <h1>今天天气很{{info}}</h1>
      <button @click="wehtherchange">切换天气</button>
    </div>
    <script>
       Vue.config.productionTip = false;
         const vm=new Vue({
             el: '#root',
             data:{
              isHot:false
             },
             computed:{
              info(){return this.isHot ?"炎热":"凉爽"}
             },
             methods:{
              wehtherchange(){
                this.isHot=!this.isHot
              }
             },
            //  watch:{
            //   isHot:{
                // handler(newValue,oldValue){
                //   console.log("x",newValue,oldValue)
                // }
            //   }
            //  }

         })
         vm.$watch("isHot",{
          immediate:true,
          handler(newValue,oldValue){
                  console.log("x",newValue,oldValue)
                }
         })
    </script>
  </body>
</html>

3.5.7案例—天气展示-深度

说明:

​ 演示深度监听的用法

<!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>
    <script src="../js/vue.js" type="text/javascript"></script>
  </head>
  </head>
  <body>
    <div id="root">
      <h1>今天天气很{{info}}</h1>
      <button @click="wehtherchange">切换天气</button>
    </div>
    <script>
       Vue.config.productionTip = false;
         const vm=new Vue({
             el: '#root',
             data:{
              isHot:false,
              number:{
                a:100,
                b:200,
              }
             },
             computed:{
              info:function(){return this.isHot ?"炎热":"凉爽"}
             },
             methods:{
              wehtherchange(){
                this.isHot=!this.isHot
              }
             },
             watch:{
              "isHot":{
                handler(newValue,oldValue){
                  console.log("x",newValue,oldValue)
                }
              },
              'number.a':{//监视多级结构中某个属性的变化
              // deep:true,
              handler(){
                console.log("ok!")
              }
             },
             number:{//监视多级结构中所有属性的变化
              deep:true,
              handler(){
                console.log("ok!")
              }
             }
             },
         })
    </script>
  </body>
</html>

3.6样式绑定

笔记小结:

  1. 概述:在 Vue 中,你可以使用绑定语法来动态地管理元素的样式。样式绑定可以根据数据的变化来动态地改变元素的样式class样式

  2. 分类:

  • Class样式:

    • 写法:class=xxx

    • 备注:xxx可以是字符串、对象、数组

    • 补充:

      <!-- 绑定class样式--字符串写法,适用于:样式的类名不确定,需要动态指定-->
      <div class="basic" :class="mood" @click="changeMood">{{name}}</div> <br /><br/>
      <!--绑定class样式--数组写法,适用于:要绑定的样式个数不确定、名字也不确定-->
      <div class="basic" :class="classArr">{{name}}</div>  <br /><br/>
      <!--绑定class样式--对象写法,适用于:要绑定的样式个数确定、名字也确定,但要动态决定用不用-->
      <div class="basic" :class="class0bj">{{name}}</div>
      <!--总结,数组写法写多个,字符串写法写单个,对象写法动态开-->
      
  • Style样式:

    • 写法:style=“{fontsize: xxx}”
    • 备注:其中xxx是动态值
    • 补充::style="[a,b]"其中a、b是样式对象。也就是数组对象的写法

3.6.1概述

​ 在 Vue 中,你可以使用绑定语法来动态地管理元素的样式。样式绑定可以根据数据的变化来动态地改变元素的样式,使你能够根据不同的情况来应用不同的样式规则

3.6.2Class样式

3.6.2.1字符串
  • 样式的类名不确定,需要动态指定
<!-- 绑定class样式--字符串写法,适用于:样式的类名不确定,需要动态指定-->
<style>
    .basic {
        height: 200px;
        width: 200px;
    }
    .happy {
        background-color: red;
    }
    .sad {
        background-color: green;
    }
    .normal {
        background-color: aqua;
    }
</style>
<div class="basic" :class="mood" @click="changeMood">{{name}}</div> <br /><br/>
<script>
    data:{
        mood: ' normal"
    },
        methods: {
            changeMood(){
                const arr = ['happy','sad','normal']
                const index = Math.floor(Math.random()*3)
                this.mood = arr[index]
            }
        }
</script>
3.6.2.2数组
  • 要绑定的样式个数不确定、名字也不确定
<!--绑定class样式--数组写法,适用于:要绑定的样式个数不确定、名字也不确定-->
<div class="basic" :class="classArr">{{name}}</div>  <br /><br/>
<script>
    data:{
        classArr: [ 'atguigu1' , 'atguigu2' ,"atguigu3"]
    }
</script>
3.6.2.3对象
  • 要绑定的样式个数确定、名字也确定,但要动态决定用不用
<!--绑定class样式--对象写法,适用于:要绑定的样式个数确定、名字也确定,但要动态决定用不用-->
<div class="basic" :class="class0bj">{{name}}</div>
<script>
    data:{
        classobj:{atguigu1:false,atguigu2:false}
    }
</script>

3.6.3Style样式

3.6.3.1数组对象
<!--绑定style样式--数组写法-->
<div class="basic" :style="styleArr">{{name}}</div>
<script>
    data:{
        styleArr:[
            {
                fontSize: '40px',		
                color:'blue',
            },
            {
                backgroundColor:'gray'
            }
        ]
    }
</script>
3.6.3.2对象
<!--绑定style样式--对象写法-->
<div class="basic" :style="styleobj">{{name}}</div> <br/><br/>
<script>
    data:{
        styleObj:{
            fontSize: '40px',
                color:'red'
        }
    }
</script>

3.7条件渲染

笔记小结:

  • 概述:在 Vue 中,条件渲染是指根据特定的条件来决定是否渲染或展示特定的组件、元素或内容。
  • 分类:
    1. .v-if
      • 写法:v-if=“表达式”、v-else-if="表达式”、v-else="表达式”
      • 适用于:切换频率较低的场景。
      • 特点:DOM元素被移除,动态决定是否渲染
      • 注意:v-if可以和:v-else-if、v-else一起使用,但要求结构不能被“打断”。
    2. .v-show
      • 写法: v-show=“表达式”
      • 适用于:切换频率较高的场景。
      • 特点:不展示的DOM元素未被移除,仅仅是使用样式隐藏掉
  • 注意:使用v-if的时,元素可能无法获取到,而使用v-show一定可以获取到。

3.7.1概述

​ 在 Vue 中,条件渲染是指根据特定的条件来决定是否渲染或展示特定的组件、元素或内容。Vue 提供了一些指令来实现条件渲染,其中最常用的是 v-ifv-elsev-else-if

参考链接:条件渲染 | Vue.js (vuejs.org)

3.7.2基本用例v-show使用

  • 控制元素在页面是否显示
<!DOCTYPE html>
<html>
    <body>
        <div id="root">
            <h2 v-show="true">Hello,{{name}}!</h2>
        </div>	
    </body>

    <script type="text/javascript">
        const vm = new Vue({
            el:'#root',
            data:{
                name:'jojo',
                n:0
            }
        })
    </script>
</html>

说明:

​ v-show语法跟v-if语法不同,v-show,是将页面上的元素进行显示或隐藏

补充:

v-showfalse变为true的时候不会触发组件的生命周期

3.7.3基本用例v-if使用

  • 控制元素在页面是否渲染
<template v-if="n === 1">
    <h2>你好</h2>
	<h2>尚硅谷</h2>
    <h2>北京</h2>
</template>

说明:

​ v-if语法,是控制页面上的元素是否渲染

补充:

v-iffalse变为true的时候,触发组件的beforeCreatecreatebeforeMountmounted钩子,由true变为false的时候触发组件的beforeDestorydestoryed方法

3.8列表渲染

笔记小结:

  1. 概述:在 Vue 中,列表渲染是一种常见的操作,用于根据数据数组生成一系列相似的元素。Vue 提供了 v-for 指令来实现列表渲染

  2. 基本用例

    • 遍历数组

      <li v-for="(p,index) in persons" :key="p.id">{{p.name}}----{{p.age}}----{{index}}</li>
      <!--persons:[{id:Number,name:"",age:Number}]-->
      
    • 遍历对象

       <li v-for="(value,k) in car" :key="k">{{k}}----{{value}}</li>
      <!-- car:{name:"奥迪A8",price:"70W",color:"黑色"}-->
      
    • 遍历字符串

       <li v-for="(char,index) in str" :key="index">{{index}}----{{char}}</li>
      <!--str:"玥玥,你是最棒的!"-->
      

      补充:记住对象的遍历方式**(value,k)。其余数组字符串的遍历方式(value,index)**

  3. 列表过滤:filter,过滤不想要的,留下想要的。其实现思路是通过filter根据监听或计算来实现

  4. 列表排序:sort。其实现思路是联合使用计算属性来实现列表的过滤与列表的数据排序

  5. 列表更新:

    • 更新对象:可以直接更新某个属性,也可以更新整个对象
    • 更新数组:数组.splice(0,1,‘开车’)
  6. Key值的作用与原理:详细请查看本小节

3.8.1概述

​ 在 Vue 中,列表渲染是一种常见的操作,用于根据数据数组生成一系列相似的元素。Vue 提供了 v-for 指令来实现列表渲染。

3.8.2基本用例-v-for使用

<!-- 遍历数组-->
<h1>人员列表</h1>
<ul>
    <li v-for="(p,index) in persons" :key="p.id">{{p.name}}----{{p.age}}----{{index}}</li>
</ul>
<!-- 遍历对象 -->
<h1>车辆信息</h1>
<ul>
    <li v-for="(value,k) in car" :key="k">{{k}}----{{value}}</li>
</ul>
<!-- 遍历字符串 -->
<h1>字符串</h1>
<ul>
    <li v-for="(char,index) in str" :key="index">{{index}}----{{char}}</li>
</ul>
<script>
       Vue.config.productionTip = false;
       new Vue({
           el: '#root',
           data: {
            persons:[{
              id:001,
              name:"张三",
              age:18
            },{
              id:002,
              name:"王五",
              age:19
            },{
              id:003,
              name:"老六",
              age:20
            }],
            car:{name:"奥迪A8",price:"70W",color:"黑色"},
            str:"玥玥,你是最棒的!"
           }
       })
       
    </script>

说明:

​ 记住对象的遍历方式**(value,index)。其余数组字符串的遍历方式(value,k)**相似

说明:

​ key需要在v-for的遍历时使用。目的是标识数据,便于Vue内部的数据校验差异比较。详细请查看本小节,Key的作用与原理

3.8.3列表过滤

说明:

​ 需要将返回的数据,进行条件的过滤时可以使用。其实现思路是通过filter根据监听或计算来实现

<!DOCTYPE html>
<html lang="en">
	……
  <body>
    <div id="root">
    <h1>人员列表</h1>
      <input type="text" placeholder="请输入关键字" v-model="keyWord">
        <ul>
          <li v-for="(x,index) in filPersons" :key="index">{{x.name}}------{{x.sex}}</li>
        </ul>
    </div>
    <script>
       Vue.config.productionTip = false;
      // 方式一:通过监听来实现列表的过滤
      //  const vm=new Vue({
      //      el: '#root',
      //      data: {
      //         keyWord:"",
      //         persons:[
      //           {id:"01",name:"马冬梅",age:18,sex:"男"},
      //           {id:"02",name:"周冬雨",age:19,sex:"男"},
      //           {id:"03",name:"周杰伦",age:20,sex:"男"},
      //           {id:"04",name:"唐昕玥",age:18,sex:"女"}
      //         ],
      //         filPersons:[]
      //      },
      //      watch:{
      //       keyWord:{
      //         immediate:true,
      //         handler(val){
      //         this.filPersons=this.persons.filter((p)=>{   // 此处使用了filter函数
      //         return p.name.indexOf(val) !==-1
      //         })
      //       }
      //       }
      //      }
      //  })
      // 方式二:通过计算来实现列表的过滤
       const vm=new Vue({
           el: '#root',
           data: {
              keyWord:"",
              persons:[
                {id:"01",name:"马冬梅",age:18,sex:"男"},
                {id:"02",name:"周冬雨",age:19,sex:"男"},
                {id:"03",name:"周杰伦",age:20,sex:"男"},
                {id:"04",name:"唐昕玥",age:18,sex:"女"}
              ]
           },
            computed:{
              //过滤
              filPersons(){
                return this.persons.filter((p)=>{              // filter,过滤不想要的,留下想要的
                  // return p.age>18 //将年龄大于18岁的人过滤出来,并返回年龄大于18岁的人————周冬雨,周杰伦
                  return p.name.indexOf(this.keyWord)!==-1  //查看p.name中是否包含输入框的值,不包含返回-1,包含则返回此字符中的第几位索引
                  // return p.name.indexOf(this.keyWord)>=0
                }
                )
              }
            }
       })
    </script>
  </body>
</html>

3.8.4列表排序

说明:

​ 通过修改响应式数据的sortType,并联合使用计算属性来实现列表的过滤与列表的数据排序

<!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>
    <script src="../js/vue.js" type="text/javascript"></script>
  </head>
  </head>
  <body>
    <div id="root">
   
    <h1>人员列表</h1>
      <input type="text" placeholder="请输入关键字" v-model="keyWord">
      <button @click="sortType=0">原顺序</button></button></button>
      <button @click="sortType=1">升序</button>
      <button @click="sortType=2">降序</button>
        <ul>
          <li v-for="(x,index) in filPersons" :key="index">{{x.name}}---{{x.age}}---{{x.sex}}</li>
        </ul>
    </div>
    <script>
       Vue.config.productionTip = false;
       const vm=new Vue({
           el: '#root',
           data: {
              keyWord:"",
              persons:[
                {id:"01",name:"马冬梅",age:18,sex:"男"},
                {id:"02",name:"周冬雨",age:19,sex:"男"},
                {id:"03",name:"周杰伦",age:20,sex:"男"},
                {id:"04",name:"唐昕玥",age:18,sex:"女"}
              ],
              sortType:0,
           },
            computed:{
              filPersons(){
                const arr= this.persons.filter((p)=>{
                  return p.name.indexOf(this.keyWord)!==-1
                })
               arr.sort((a,b)=>{
                if(this.sortType){
                  return this.sortType===1 ?a.age-b.age:b.age-a.age
                }
               })
               return arr
              }
            }
       })
    </script>
  </body>
</html>

3.8.5列表更新

  • 更新对象

image-20221114195505414

说明:

​ 当进行列表数据的某个数组对象的属性更新时,可以直接更新某个属性,也可以更新整个对象

  • 更新数组
<script>
data:{
student:{
	hobby:["抽烟","喝酒","烫头"]
}

//数组
updateHobby(){
	 this.student.hobby.splice(0,1,'开车')
}
</script>

说明:

​ 当使用为数组内的splice替换第一个即可

3.8.6Key的作用与原理✳

笔记小结:

  1. 虚拟DOM中key的作用:
    • key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据【新数据】生成【新的虚拟DOM】,随后Vue进行【新虚拟DOM】与【旧虚拟DOM】的差异比较,比较规则如下:
  2. 对比规则:
    1. 旧虚拟DOM中找到了与新虚拟DOM相同的key:
      1. 若虚拟DOM中内容没变,直接使用之前的真实DOM !
      2. 若虚拟DOM中内容变了,则生成新的真实DOM,随后替换掉页面中之前的真实DOM.
    2. 旧虚拟DOM中未找到与新虚拟DOM相同的key:
      1. 创建新的真实DOM,随后渲染到到页面。
  3. 用index作为key可能会引发的问题:
    1. 若对数据进行:逆序添加、逆序删除等破坏顺序操作:
      • 会产生没有必要的真实DOM更新==>界面效果没问题,但效率低。
    2. 如果结构中还包含输入类的DOM:
      • 会产生错误DOM更新==>界面有问题。
  4. 开发中如何选择key?:
    1. 最好使用每条数据的唯一标识作为key,比如id、手机号、身份证号、学号等唯一值。
    2. 如果不存在对数据的逆序添加、逆序删除等破环顺序操作,仅用于渲染列表用于展示,使用index作为key是没有问题的。

​ key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据【新数据】生成【新的虚拟DOw】,随后Vue进行【新虚拟DOM】与【旧虚拟DOM】的差异比较

  • 遍历列表时key的作用(index作为key)

image-20230820113424832

说明:

​ 当使用index作为遍历列表的key时,新生成的数据只会随着对象的索引改变。因此会发生数据的偏移

  • 遍历列表时key的作用(id作为key)

image-20230820113411996

说明:

​ 当使用index作为遍历列表的key时,新生成的数据只会随着对象的id值改变。因此不会发生数据的偏移

3.9过滤器

笔记小结:

  1. 概述:Vue 过滤器(Filters)是一种用于格式化文本输出的方式。对要显示的数据进行特定格式化后再显示(适用于一些简单逻辑的处理)。
  2. 基本用例:
    • 步骤一:注册过滤器
      1. 全局过滤器:Vue.filter(name,callback)
      2. 局部过滤器:new Vue{filters:{}}
    • 步骤二:使用过滤器
      • 管道符使用:{{ xxx│过滤器名}}
      • 属性使用:v-bind:属性=“xxx│过滤器名"
  3. 备注:
    1. 过滤器也可以接收额外参数、多个过滤器也可以串联
    2. 并没有改变原本的数据,是产生新的对应的数据

3.9.1概述

​ Vue 过滤器(Filters)是一种用于格式化文本输出的方式。它可以用于在模板中对数据进行预处理,以便在显示之前对其进行格式化、过滤或转换。过滤器是 Vue 提供的一种轻量级功能,用于处理常见的文本转换需求。

3.9.2基本用例-过滤器使用

步骤一:使用

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <title>过滤器</title>
        <script type="text/javascript" src="../js/vue.js"></script>
        <script src="https://cdn.bootcdn.net/ajax/libs/dayjs/1.10.6/dayjs.min.js"></script>
    </head>
    <body>
        <div id="root">
            <h2>时间</h2>
            <h3>当前时间戳:{{time}}</h3>
            <h3>转换后时间:{{time | timeFormater()}}</h3>
            <h3>转换后时间:{{time | timeFormater('YYYY-MM-DD HH:mm:ss')}}</h3>
            <h3>截取年月日:{{time | timeFormater() | mySlice}}</h3>
        </div>
    </body>

    <script type="text/javascript">
        Vue.config.productionTip = false
        // 方式一 :全局过滤器
        Vue.filter('mySlice',function(value){
            return value.slice(0,11)
        })
        new Vue({
            el:'#root',
            data:{
                time:1626750147900,
            },
            // 方式二:局部过滤器
            filters:{
                timeFormater(value, str="YYYY年MM月DD日 HH:mm:ss"){
                    return dayjs(value).format(str)
                }
            }
        })
    </script>
</html>

说明:

通过插值语法的管道符来进行使用

步骤二:演示

image-20231026192231394

3.10生命周期✳

笔记小结:

  1. 概述:Vue 的生命周期钩子是在组件实例的不同阶段调用的特定函数。生命周期又叫回调函数、生命周期函数、生命周期钩子。
  2. 基本用例:new Vue({mounted(){ }})
  3. 生命周期流程图
  4. 生命周期细节:
    • 当使用生命周期时,均为函数式的写法
    • 生命周期函数的名字不可更改,但函数的具体内容是程序员根据需求编写的。
    • 生命周期函数中的this指向是vm组件实例对象。
  5. 补充:
    1. 常用的生命周期钩子
      1. mounted:发送ajax请求、启动定时器、绑定自定义事件、订阅消息等【初始化操作】。
      2. beforeDestroy:清除定时器、解绑自定义事件、取消订阅消息等【收尾工作】。
    2. 关于销毁Vue实例
      1. 销毁后借助Vue开发者工具看不到任何信息。
      2. 销毁后自定义事件会失效,但原生DOM事件依然有效。
      3. 一般不会在beforeDestroy操作数据,因为即便操作数据,也不会再触发更新流程了。

注意:在使用生命周期内的函数的时候写为函数的形式,不可写为对象!

3.10.1概述

​ Vue 的生命周期钩子是在组件实例的不同阶段调用的特定函数。这些生命周期钩子函数允许你在组件不同阶段执行特定的操作,比如初始化数据、监听事件、更新 DOM 等。

3.10.2基本用例-挂载

说明:

​ Vue完成模板的解析并把初始的真实DOM元素放入页面后(挂载完毕)调用mounted

<!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>
    <script src="../js/vue.js" type="text/javascript"></script>
  </head>
  </head>
  <body>
    <div id="root">
      <!-- 此处的opacity为简写形式 -->
      <h2 :style="{opacity}" >玥玥,在干嘛呢?</h2>
    </div>
    <script>
       Vue.config.productionTip = false;
       const vm=new Vue({
           el: '#root',
           data: {
            opacity:1
           },
          //  methods:{
          //   change(){
          //     setInterval(() => {
          //           this.opacity-=0.01
          //           if(this.opacity<=0)this.opacity=1
          //         }, 16);
          //   }
          //  },
           mounted(){
            setInterval(() => {
                    this.opacity-=0.01
                    if(this.opacity<=0)this.opacity=1
                  }, 16);
           },
       })
       //通过外部定时器的方式(不推荐)
      //  setInterval(() => {
      //   vm.opacity-=0.01
      //   if(vm.opacity<=0)vm.opacity=1
      //  }, 16);
    </script>
  </body>
</html>

说明:

​ 通过按钮点击来触发计时器,通过外部定时器来触发挂载,都可以达到相同的效果。但是通过Vue提供的生命周期钩子可以更加方便的挂载

注意:

​ 当使用生命周期时,均为函数式的写法

3.10.3生命周期流程图

image-20230820142156020

补充:

  • 在Mouted生命周期钩子中:Re-render重新加载虚拟DOM、Patch,重旧的虚拟DOM和新的虚拟DOM中进行比较
  • 在Destoryed生命周期钩子中:Terdown:移除废掉、Event lister:自定义的事件

3.10.4案例—透明度变换

<!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>
    <script src="../js/vue.js" type="text/javascript"></script>
  </head>
  </head>
  <body>
    <div id="root">
      
    <h2 :style="{opacity}" >欢迎学习Vue</h2>
    <button @click="opacity=1">点击将透明度设置为1</button>
    <button @click="stop">点击停止变换</button>

    
  </div>
    <script>
       Vue.config.productionTip = false;
       const vm=new Vue({
           el: '#root',
           data: {
            opacity:1
           },
           methods:{
            stop(){
              vm.$destroy()
            }
           },
           mounted(){
           this.timer= setInterval(() => {
                    this.opacity-=0.01
                    if(this.opacity<=0)this.opacity=1
                    console.log(this.timer)
                  }, 16);
           },
           beforeDestroy() { // 在实例被销毁之前需要清除计时器
            clearInterval(this.timer)
           },
       })
    </script>
  </body>
</html>

image-20230820143240064

3.11案例—信息表单

笔记小结

  1. 概述:表单是常用信息,这里展示常用的表单信息收集说明
  2. 补充知识点:
    • 若:,则v-model收集的是value值,用户输入的就是value值。
    • 若:,则v-model收集的是value值,且要给标签配置value值。
    • 若:
      • 没有配置input的value属性,那么收集的就是checked(勾选or未勾选,是布尔值)
      • 配置input的value属性;
        • v-model的初始值是非数组,那么收集的就是checked(勾选 or未勾选,是布尔值)
        • v-model的初始值是数组,那么收集的的就是value组成的数组
  3. 备注:v-model的三个修饰符
    • lazy:失去焦点再收集数据
    • number:输入字符串转为有效的数字
    • trim:输入首尾空格过滤
<!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>
    <script src="../js/vue.js" type="text/javascript"></script>
  </head>
  </head>
  <body>
    <div id="root">
      <form @submit.prevent="demo">
        账号:<input type="text"  v-model.trim="acount"><br><br>
        密码:<input type="password" v-model="password"><br><br>
        性别:男<input type="radio" name="sex" value="male" v-model="sex">女<input type="radio" name="sex" value="femal" v-model="sex"><br><br>
        爱好:抽烟<input type="checkbox" name="hobby" value="smoke" v-model="hobby">喝酒<input type="checkbox" checked name="hobby" value="drink" v-model="hobby">烫头<input type="checkbox" name="hobby" value="tou" v-model="hobby"><br><br>
        <select v-model="city">
          <option value="">请选择校区</option>
          <option value="beijing">北京</option>
          <option value="shanghai">上海</option>
          <option value="shenzhen">深圳</option>
          <option value="wuhan">武汉</option>
        </select><br><br>
        其他信息:
        <textarea v-model.lazy="other"></textarea><br><br>
          <input type="checkbox" v-model="submit"> <a href="http://www.baidu.com">《用户协议》</a><br><br>
          <button @click="ok">提交</button>
      </form>
    </div>

    <script>
       Vue.config.productionTip = false;
       new Vue({
           el: '#root',
           data: {
            acount:'',
            password:"",
            sex:"",
            hobby:[],//此时复选框接收为数组
            city:"",
            other:"",
            submit:"",

           },
           methods: {
            ok(){
              console.log(JSON.stringify(this._data))
              alert("ok!")
            }
           },
       })
    </script>
  </body>
</html>

说明:结果

image-20230820135219599

3.12MVVM模型✳

笔记小结:

​ 本小节重点,请仔细阅读

3.12.1概述

image-20230820144122051

说明:

  • M:Model 数据模型。数据层,data中的数据。数据可能是固定的思数据, 更多的是来自服务器, 从网络上请求下来的数据
  • V:View 视图模板。视觉层,模板代码。在前端开发中, 通常是DOM层。 是给用户展示各种信息
  • VM:View-Model。视图模型,Vue实例。是View和Model沟通的桥梁。一方面实现了Data Binding (数据绑定), 讲Model的改变实时的反应到View中,另一方面实现了DOM Listener (DOM监听), 当DOM发生一些时间 (点击, 滚动, touch等) 时, 可以监听到,并在需要的情况下改变对应的Data

3.12.2基本用例-模型演示

<!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>mvvm</title>
    <script src="../js/vue.js"></script>
</head>
<body>
    <div id="root"> <!--V层,模板代码-->
        <h2>名称:{{name}}</h2>
        <h2>战队:{{rank}}</h2>
        <h2>测试:{{$options}}</h2>
    </div>

    <script>
        Vue.config.productionTip = false
        new Vue({ // VM层,Vue实例
            el:'#root',
            data:{  // data层,data中数据
                name:'uzi',
                rank:'RNG'
            }
        })
    </script>
</body>
</html>

说明:结果

image-20230820101503025

补充:

  • data中所有的属性,最后都出现在vm身上
  • vm身上所有的属性vue原型身上所有的属性,在模板中都可以直接使用

3.13数据代理✳

笔记小结:

  1. 概述:Vue 数据代理是指在 Vue 组件中,通过特定的方式将数据的访问和修改映射到组件实例的属性上,从而实现对数据的访问和修改的操作。
  2. Vue中的数据代理通过vm对象来代理data对象中属性的操作(读/写)
  3. Vue中数据代理的好处:更加方便的操作data中的数据
  4. 基本原理:
    • 通过object.defineProperty()把data对象中所有属性添加到vm上。
    • 为每一个添加到vm上的属性,都指定一个getter/setter
    • getter/setter内部去操作(读/写)data中对应的属性。
  5. 补充:请详细查看本小节

3.13.1概述

​ Vue 数据代理是指在 Vue 组件中,通过特定的方式将数据的访问和修改映射到组件实例的属性上,从而实现对数据的访问和修改的操作。Vue 在组件中提供了一个 data 选项,你可以在这个选项中定义组件内部的数据。Vue 会自动将这些数据代理到组件实例上,使你可以通过组件实例来访问和修改这些数据

3.13.2Object.defineProperty方法

说明:

Object.defineProperty 是 JavaScript 中的一个方法,用于在对象上定义新的属性,或修改现有属性的特性(例如可写性、可枚举性、可配置性等)

方法一:属性配置

<script type="text/javascript">
    Object.defineProperty(person,"age",{
        value: 18,
        enumerable:true,//控制属性是否可以枚举,默认值是false
        writable:true,//控制属性是否可以被修改,默认值是false
        configurable:true //控制属性是否可以被删除,默认值是false
    })
</script>

补充:

​ 在 Vue.js 内部的响应式数据系统,就使用了 Object.defineProperty 来追踪属性的变化并触发视图更新

方法二:get、set定义

<script type="text/javascript">
    let number = 18
    let person = {name: "张三"sex:"男",}
    Object.defineProperty(person,"age",{
        //当有人读取person的age属性时,get函数(getter)就会被调用,且返回值就是age的值
        get(){
            console.1og('有人读取age属性了')
            return number
        },
        //当有人修改person的age属性时,set函数(setter)就会被调用,且会收到修改的具体值
        set(value){
            console.log('有人修改了age属性,且值是',value)
            number = value
        }
</script>

说明:

Object.defineProperty的使用方式跟watch监听的使用方式一致

3.13.3理解数据代理

<!--底层是通过 Object.defineProperty -->
<!-- 通过一个对象代理对另一个对象中属性的操作:(读/写)-->
<script>
	let obj = { x: 100};
	let obj2 = {y: 200};
      Object.defineProperty(obj2, "x", {
        get() {
          return obj.x;
        },
        set(value) {
          return (obj.x = value);
        },
      });
    
</script>

说明:

​ 数据代理,就是能在一个对象中,使用另一个对象中的属性

3.13.4Vue中的数据代理

  • MVVM模型数据展现流程

image-20221114201116339

说明:

​ 现在回忆一下MVVM模型,数据通过setter方法,进入Model数据模型data函数。通过VM来展示数据在视图V上面

  • Vue中数据代理图示

image-20230820162542485

说明:

​ vm 实例中的data数据,会加载到vm实例中,并通过Object.defineProperty函数vm层的实例进行升级

补充:

  • 此时,V层视图上展示的name与_data.name是一样的值

image-20221114201320751

  • Vue的数据响应式更新

image-20221114201648282

说明:

  • 升级,升级后完成一个响应式的操作,也就是VM里面的数据更改后,页面里面的数据瞬间检测到后就会马上更改(数据劫持)
  • 只有配置到data对象里面的值才会做数据代理,其余的都不行(也就是说,在data对象中的属性都有一个setter和getter方法)

补充:

​ 数据劫持(当student要修改一个值的时候,会被set student劫持住,然后执行修改以及渲染模板功能)

4.组件化编程

笔记小结:

  1. 概述:
    • 定义:Vue.js 是一个用于构建用户界面的渐进式框架,其中的一个核心概念就是组件化编程。组件化编程指的是将用户界面划分为独立的、可复用的组件,每个组件都包含自己的逻辑、样式和模板。
    • 模块化:当应用中的js都以模块编写的,那这个应用就是一个模块化应用
    • 组件化:组件就是用来实现局部(特定)功能效果的代码集合(html/css/js/image.…)。
  2. 非单文件组件:详细查看相应小节
  3. 单文件组件:详细查看相应小节(重点)

4.1概述

4.1.1定义

​ Vue.js 是一个用于构建用户界面的渐进式框架,其中的一个核心概念就是组件化编程。组件化编程指的是将用户界面划分为独立的、可复用的组件,每个组件都包含自己的逻辑、样式和模板。这种方式有助于管理复杂的应用程序,提高代码的可维护性和可复用性。

在 Vue 中,一个组件可以由以下三部分组成:

  1. 模板(Template): 模板是组件的 HTML 结构,用于定义组件的外观和布局。使用 Vue 的模板语法,你可以插入数据绑定、指令等来实现动态的视图展示。
  2. 脚本(Script): 脚本部分是组件的逻辑代码,使用 JavaScript 编写。在脚本中,你可以定义数据、计算属性、方法、生命周期钩子等。通过脚本,你可以控制组件的行为和交互。
  3. 样式(Style): 样式部分用于定义组件的样式,可以使用普通的 CSS 或预处理器(如 SASS、LESS)来编写。样式部分控制了组件的外观和样式。

image-20221116195140593

说明:

​ 当应用中的功能都是多组件的方式来编写的,那这个应用就是一个组件化的应用

4.1.2模块化

​ 模块就是向外提供特定功能的js程序,一般就是一个js文件。它的作用是复用js,简化js 的编写,提高js运行效率

说明:

​ 因为在传统编程中,JS文件众多,因此模块化就是为了减少简化JS

​ 模块化:当应用中的js都以模块编写的,那这个应用就是一个模块化应用

4.1.3组件化

​ 组件就是用来实现局部(特定)功能效果的代码集合(html/css/js/image.…)。它的作用是复用编码,简化项目编码,提高运行效率
说明:

​ 一个界面的功能很复杂

​ 组件化:当应用中的功能都是多组件的方式来编写的,那这个应用就是一个组件化应用

image-20230820172740078

说明:

​ 一个页面由多个组件组成。每个组件都是单独的模块化应用

补充:

image-20230820171510194

  • 传统编写应用的方式,样式引用非常的复杂。因此代码复用不高,而且关系依赖还混乱

4.2非单文件组件

笔记小结:

  1. 概述:非单文件组件顾名思义就是一个文件中包含多个组件

  2. 基本用例:

    1. 定义组件(创建组件)

      new Vue({}) 或者 Vue.extend({})
      
    2. 注册组件:

      1. 局部注册:components:{school:school}。new Vue的时候传入components选项
      2. 全局注册:Vue.component(“hi”,hello)。
    3. 使用组件(写组件标签)

      <div id="root"> 
          <school></school>
      </div>
      
  3. 组件名/组件标签规则:

    • 组件名:多个单词构成建议使用大驼峰写法
    • 注意:
      1. 组件名尽可能回避HTML中已有的元素名称,例如:h2、H2都不行。
      2. 可以使用name配置项指定组件在开发者工具中呈现的名字
  4. 组件的嵌套:将一个组件注册到另一个组件当中进行嵌套使用

  5. VueComponent构造函数:详细查看相应小节

  6. Vue实例与组件实例:详细查看相应小节

  7. 重要的内置关系:详细查看相应小节

  8. 补充:

    • 如何快速创建组件?
    <script>
        Const 组件名= Vue.extend({
            Data(){
                Return {}
            }
        })
    </script>
    
    • 如何定义一个组件?

      ​ 使用Vue.extend(options)创建,其中options和new Vue(options)时传入的那个options几乎一样,但也有点区别;

      区别如下:
      1.el不要写,为什么?—最终所有的组件都要经过一个vm的管理,由vm中的el决定服务哪个容器。
      2.data必须写成函数,为什么?——避免组件被复用时,数据存在引用关系。
      注意:使用template可以配置组件结构。

4.2.1概述

非单文件组件顾名思义就是一个文件中包含多个组件。在Vue中使用组件的三个步骤,

  • 定义组件(创建组件)
  • 注册组件
  • 使用组件(写组件标签)

4.2.2基本用例-组件使用(了解)

步骤一:创建组件Vue.extend

<script>
       //创建组件--学校
       const school =Vue.extend({
        template:`
        <div>
        <h1>学校名称:{{name}}</h1>
        <h1>学校地址:{{address}}</h1>
        </div>
        `,
        data(){
          return {
            name:"i工院",
            address:"德阳"
          }
        }
       })
</script>

注意:

​ 在Vue2中,template内为一个根元素也就是要指定div,轻则页面内容加载不出来,重则Vue报错

步骤二:注册组件Component

方式一:局部注册

说明:

​ 局部组件指的是未在全局组件中注册的组件,因此只能在注册它的组件上使用

<script>
       //注册组件(局部注册)
       new Vue({
           el: '#root',
           components:{
            school:school,//此处可以简写为school,因为 key 和value的值是一样的,参考 es6写法
            student,
           }
       })
</script>

注意:

​ 注册组件中,局部注册需要指定展示的视图 ,也是需要 el属性

补充:

​ 组件名,建议用大驼峰命名方式

方式二:全局注册

说明:

​ 全局组件指的是可以在应用程序中的任何位置使用的组件,包括在其他组件中

<script>
       //创建组件(为全局注册使用)
      const hello=Vue.extend({
        template:`
        <div><h1>{{message}}</h1></div>
        `,
        data(){
          return{
            message:"hello"
          }
        }
       })
       //注册组件(全局注册)
       Vue.component("hi",hello)
</script>

注意:

​ 注册一个全局组件语法格式如下:Vue.component(tagName,options),tagName为组件名,options为配置选项。

步骤三:使用组件

<!-- 编写组件 -->
<div id="root"> <!--此处需要与组件实例的属性el所指定的id名相同-->
    <school></school>
</div>

步骤四:演示

image-20230906084525596

4.2.3案例—组件理解

<!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>
    <script src="../js/vue.js" type="text/javascript"></script>
  </head>
  </head>
  <body>
    <!--3.使用组件 -->
    <div id="root">
      <school></school>
      <student></student>
      <hi></hi>
    </div>
    <script>
       Vue.config.productionTip = false;
       //1.创建组件--学校
       const school ={
        template:`
        <div>
        <h1>学校名称:{{name}}</h1>
        <h1>学校地址:{{address}}</h1>
        </div>
        `,
        data(){
          return {
            name:"i工院",
            address:"德阳"
          }
        }
       }
       //1.创建组件--学生
       const student =Vue.extend({
        template:`
        <div>
        <h1>学生名称:{{name}}</h1>
        <h1>学生地址:{{address}}</h1>
        </div>
        `,
        data(){
          return {
            name:"玥玥",
            address:"南充市顺庆区舞凤街道双女石路鸿升凯旋城"
          }
        }
       })
       //1.创建组件(为全局注册使用)
      const hello=Vue.extend({
        template:`
        <div><h1>{{message}}</h1></div>
        `,
        data(){
          return{
            message:"hello"
          }
        }
       })
       //2.注册组件(全局注册)
       Vue.component("hi",hello)
       //2.注册组件(局部注册)
       new Vue({
           el: '#root',
           components:{
            school:school,//此处可以简写为school,因为 key 和value的值是一样的,参考 es6写法
            student,
           }
       })
       
    </script>
  </body>
</html>

4.2.4组件名 / 组件标签

(1)一个单词组成:

  • 首字母小写:school

  • 首字母大写:School

(2)多个单词组成:

  • kebab-case命名:my-school

  • CamelCase命名:MySchool (需要Vue脚手架支持),否则会报错

(3)注意:

  • 组件名尽可能回避HTML中已有的元素名称,例如:h2、H2都不行。

  • 可以使用name配置项指定组件在开发者工具中呈现的名字

(4)组件标签:

  • 第一种写法:
  • 第二种写法:。若不在脚手架环境下使用,会导致后续组件不能渲染。

4.2.5组件的嵌套

说明:

先将组件A创建好,再放入组件B中进行注册与使用

<!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>
    <script src="../js/vue.js" type="text/javascript"></script>
  </head>
  </head>
  <body>
    <!-- 编写组件 -->
    <div id="root">
      <school></school>
    </div>
    <script>
       Vue.config.productionTip = false;

      //步骤一:创建组件--学生//嵌套//放置嵌套模板的前面
      const student2=Vue.extend({
        name:"student",
        template:`
        <div>
        <h1>学生姓名:{{name}}</h1>
        <h2>学生年龄:{{age}}</h2>
        </div>`,
        data(){
          return {
            name:"杰哥",
            age:20
          }
        }
      })
      
       //步骤二:创建组件--学校
      const school =Vue.extend({
        template:`
        <div>
        <h1>学校名称:{{name}}</h1>
        <h1>学校地址:{{address}}</h1>
        <student2></student2>
        </div>
        `,
        data(){
          return {
            name:"i工院",
            address:"德阳",  
          }
        },
        components:{
          student2, //步骤三:学校组件注册学生组件
        }
       })
      
       //步骤四:注册组件(局部注册)
      const vm= new Vue({
           el: '#root',
           components:{
            school,
           }
       })
       
       console.log(vm)
    </script>
  </body>
</html>

4.2.6VueComponent构造函数(掌握)

  1. school组件本质是一个名为VueComponent的构造函数,且不是程序员定义的,是Vue.extend生成的

  2. 我们只需要写或,Vue解析时会帮我们创建school组件的实例对象,即Vue帮我们执行的: new VueComponent(options)。

  3. 特别注意: 每次调用Vue.extend,返回的都是一个全新的VueComponent!!!

  4. 关于this指向:

    (1).组件配置中: data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是**[VueComponent实例对象]**(VC 实例对象)

    (2).new Vue(options)配置中: data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是**[Vue实例对象]**(VM 实例对象)

  5. VueComponent的实例对象,以后简称vc(也可称之为: 组件实例对象)。Vue的实例对象,以后简称vm

补充:

1.每次调用Vue.extend的时候,返回的都是一个全新的VC

image-20221117084319765

options为配置对象,也就是绿框里面的东西

image-20221117084612925

2.解析标签时,Vue帮我们创建新的VC

image-20221117085012666

image-20221117085034564

3.特别注意,每次调用都是返回全新的VC

image-20221117085625128

换句话说,在视图中使用标签时,会生成两个长得很像的VC但不是同一个VC

image-20221117085806070

补充:

  • VC是一个构造函数,构造函数通过New可以得到它的实例对象 。

image-20221117090739484

  • VC里面可以管理多个VC,通过嵌套关系可以发现!

4.2.7Vue实例与组件实例(掌握)

​ 因为组件是可复用的Vue实例,所以它们与new Vue 接收相同的选项,例如data、computed 、 watch 、methods以及生命周期钩子等。仅有的例外是像 el这样根实例特有的选项。

说明:

换句话说,组件实例没有el选项,创建data只可用函数式,Vue实例有el选项,创建data可用函数式、对象式

4.2.8重要的内置关系(掌握)

笔记小结:

  1. 一个重要的内置关系:VueComponent.prototype.proto == Vue.prototype

  2. 为什么要有这个关系:让组件实例对象(vc)可以访问到Vue原型上的属性、方法

  3. 总结:

    image-20231030155856441

1.理解组件实例对象的prototype和_proto_属性

<script>
//定义一个构造函数
function Demo(){
	this.a = 1
	this.b = 2
}
//创建一个Demo的实例对象
const d = new Demo()
console.log(Demo.prototype)  //显示原型属性//console.dir(Demo),可以打印Demo对象
console.log(d.__proto__)  //隐式原型属性
console.log(Demo. prototype === d.__proto__) //true
//程序员通过显示原型属性操作原型对象,追加一个x属性,值为99
Demo.prototype.x = 99
console.log('@',d)
</script>

说明:

image-20221117115155421

  • 从输出结果,可以看到,显示原型属性与隐式原型属性相同

注意:

显示原型属性只有函数才拥有,隐式原型属性只有实例对象才拥有!

补充:

一般程序员通过显示原型属性往程序上放东西,程序通过隐式原型属性读取该东西。比如

  • ​ 放:Demo.prototype.x = 99

  • ​ 读:Demo.proto.x

2.VueComponent.prototype.__proto__ == Vue.prototype

说明:

这条内置关系就是让组件实例对象(vc)可以访问到Vue原型上的属性、方法。

image-20221117222933070

  • 当文件中引入Vue时,就会生成Vue对象

image-20221117230403831

Vue.components("hello",hello)//全局注册组件
  • Vue身上一定有一个Vue的原型对象,因为Vue是一个构造函数。函数身上有显示原型属性

image-20221117230328820

  • Vue身上new出来的实例对象一定有一个Vue的原型对象,因为Vue new出来的实例是一个实例对象。实例对象上有隐式原型属性

image-20221118072652899

补充:vm.$mount挂载的另一种方式、vm.$watch监听的另一种方式

  • Vue实例对象的隐式原型属性指向自己缔造者的原型对象,因为 Vue原型对象也是一个对象,它的隐式原型属性指向Object原型对象

image-20221118152255033

验证:new Vue 实例对象,查看其属性

image-20221118153103916

  • VueComponet的原型对象的原型对象是Vue原型对象,因为这是Vue所干的这样一件事情,建立了一条重要的内置关系

image-20221118153609618

  • VueComponent.prototyoe.__proto__===Vue.prototype,换句话说,VueComponet.prototype === VueComponent的原型对象。这条内置关系就是让组件实例对象(vc)可以访问到Vue原型上的属性、方法。

image-20221118153950966

3.这个内置关系主要用途

  • 数据绑定与响应式更新:Vue 的响应式系统依赖于这个关系。当你在组件的 data 选项中定义数据属性时,这些属性会被添加到组件实例中,同时也会添加到 Vue 的原型上。这使得这些属性可以进行数据绑定,当数据发生变化时,视图会自动更新。
codevar vm = new Vue({
  data: {
    message: 'Hello, Vue!'
  }
});

// 访问数据属性
console.log(vm.message); // 输出 'Hello, Vue!'

// 修改数据属性,视图会自动更新
vm.message = 'Vue is awesome!';
  • 访问 Vue 的全局方法和属性:Vue 原型上包含了一些全局的方法和属性,例如 $mount$nextTick$emit 等,这些方法和属性是 Vue 提供的核心功能。通过组件实例可以访问这些全局方法和属性,以完成各种任务。
codevar vm = new Vue();

// 使用全局方法 $nextTick
vm.$nextTick(function () {
  // 在下一次 DOM 更新后执行
  console.log('DOM 更新完成');
});

// 触发全局事件 $emit
vm.$emit('custom-event', '参数1', '参数2');
  • 访问实例方法和生命周期钩子:Vue 实例提供了一些实例方法和生命周期钩子,通过组件实例可以访问这些方法和钩子,以实现自定义的逻辑。例如,created 钩子在组件实例被创建后立即调用,你可以在其中执行一些初始化操作。
codevar vm = new Vue({
  created: function () {
    console.log('组件实例已创建');
  },
  methods: {
    customMethod: function () {
      console.log('自定义方法被调用');
    }
  }
});

// 调用实例方法
vm.customMethod();

4.3单文件组件

笔记小结:

  1. 概述:一个文件中只包含有1个组件

  2. 目录结构:

    image-20231030164750681

  3. 组件内部结构:

    <template>
    <!-- 组件的结构 -->
    </template>
    
    <script>
    //组件交互相关的代码(数据、方法等等)
    </script>
    
    <style>
    /*组件的样式*/
    </style>
    

4.3.1概述

一个文件中只包含有1个组件

4.3.2组件目录(了解)

4.3.2.1组件
  • App组件

说明:

App组件又叫入口组件,便于整合展示其余组件

<template>
<div id="root">
    <School />
    <Student />
    </div>
</template>

<script>
    import School from './School.vue'
    import Student from './Student.vue'

    export default {
        name: 'App',
        components: {
            School,
            Student
        }
    }
</script>
  • School组件
<template>
<div class="demo">
    <h1>学校名称:{{ name }}</h1>
    <h1>学校地址:{{ address }}</h1>
    </div>
</template>

<script>
    export default {
        name: "School",
        data() {
            return {
                name: "i工院",
                address: "德阳",
            };
        },
    };
</script>

<style>
    .demo {
        background-color: aqua;
    }
</style>
  • Student组件
<template>
  <div>
    <h1>学生姓名:{{ name }}</h1>
    <h1>学生年龄{{ age }}</h1>
  </div>
</template>

<script>
export default {
  name: "Student",
  data() {
    return {
      name: "玥玥",
      age: 18,
    };
  },
};
4.3.2.2入口文件
  • main.js文件,又叫入口文件,决定了项目是否能够跑起来
import App from './App'
new Vue({
    template:`
  <App></App>
  `,
    el: '#root',
    data: {
    },
    components:{
        App
    }
})

4.3.2.3页面展示
  • index.html文件,配置Vue中App组件的展示位置,与整个页面中的展示信息
<body>
    <div id="root"></div>
    <script src="../js/vue.js"></script>
    <script src="./main.js"></script>
</body>

4.3.3组件内部结构

<template>
<!-- 组件的结构 -->
</template>

<script>
//组件交互相关的代码(数据、方法等等)
</script>

<style>
/*组件的样式*/
</style>

说明:

​ 组件使我们能够将一个 Vue 组件的模板、逻辑与样式封装在单个文件中

知识加油站

浏览器Vue开发插件

参考链接:

​ [Chrome浏览器安装Vue.js devtools插件_chrome.zzzmh.can/#/index-CSDN博客](https://blog.csdn.net/qq_46112274/article/details/123408370#:~:text=Chrome浏览器安装Vue.js devtools插件 1 1、浏览器访问极简插件 2 2、右上角搜索框搜索vue DevTools插件,3 3、在本地文件夹中解压刚刚下载的插件,解压后如下所示 4 4、打开谷歌浏览器–更多工具–拓展程序 5 5、将解压的文件夹拉到4中拓展程序页面 6 6、安装成功)

箭头函数

箭头函数:就是函数的一种简写形式,使用括号包裹参数,跟随一个=>,紧接着是函数体。

语法:【函数的参数=>函数体】

const sum = (a, b) => a + b。

箭头函数没有自己的this,因为箭头函数是指向外面的

注意:

​ 在Vue中,箭头函数里的this和Vue实例中的this是不同的

ES6扩展运算符

​ 在 ES6(ECMAScript 2015)中,...(三个点)被称为扩展运算符(Spread Operator)和剩余参数(Rest Parameters),具体取决于它在使用的上下文中。

Es6写法

<script>
getstudentName(name,...a){
	console.log('App收到了学生名: ',name,a)//App收到了学生名:张三3)[666,888,900]
}
</script>

…a 此刻讲传入的第一个参数作为正常值传入,而之后的数据作为数组存放

Vue有不同版本的js

vue.js 与vue.runtime.xxx.js的区别:
(1).vue.js是完整版的Vue,包含:核心功能+模板解析器。
(2) .vue.runtime.xxx.js是运行版的Vue,只包含:核心功能;没有模板解析器。
因为vue.runtime.xxx.js没有模板解析器,所以不能使用template配置项,需要使用render函数接收到的createElement函数去指定具体内容。

export暴露

补充:暴露形式export

image-20221119112329246