Vue篇:vue2基础部分学习的干货1

官网:Vue 实例 — Vue.js

1、第一个vue实例
 初始vue案例总结:
1、引入vue.js
2、创建一个vue实例对象,并且要传入一个配置对象(el:.root类的选择器)
3、准备root容器,用于写html结构和vue的data数据,root容器里的代码被称为是【vue模板】

案例:初写一个vue
<!DOCTYPE html>
<html lang="en">
  <head>
    ...
    // 注意:vue.js一定要引入
    <script type="text/javascript" src="../vue.js"></script>
  </head>

  <body>
    <!-- 准备容器 -->
    <div class="root">
      <!-- 写成:name = name形式的是指令语法,完整写法是 v-bind:name = name -->
      <!-- 写成{{ name }} 的是插值语法形式 -->
      <h3 :name="name">{{name}}</h3>
    </div>
    <script type="text/javascript">
      // 创建vue实例对象
      const x = new Vue({
        el: ".root",
        data: {
          name: "张三",
        },
      });
    </script>
  </body>
</html>
2、vue模板语法主要有两大类
vue模板语法主要有两大类:
1、插值语法
功能:用于解析标签体内容
写法:{{xxx}},xxx是js表达式,并且可以直接读取到data中的所有属性
2、指令语法:
功能:用于解析标签(包括标签属性、标签体内容、绑定事件等等)
举例:v-bind:href='xxx' 或者 简写为 :href='xxx' ,xxx同样要写js表达式并且可以直接读取到data中的所有属性。备注:vue中有很多的指令,并且形式都是 v-????,v-bind只是其中一个指令

<!DOCTYPE html>
<html lang="en">
  <head>
    ...
    <script type="text/javascript" src="../vue.js"></script>
  </head>

  <body>
    <div class="root">
      <h1>插值语法</h1>
      <h3>你好,我是{{name}}</h3>
      <hr />
      <h1>模板语法</h1>
      <a :href="url">点击前往百度</a>
    </div>
    <script type="text/javascript">
      new Vue({
        el: ".root",
        data: {
          name: "张三",
          url: "http://baidu.com",
        },
      });
    </script>
  </body>
</html>
3、v-bind和v-model
vue中有2种数据绑定的方式:v-bind和v-model
1、单向绑定v-bind:v-bind将html元素和vue实例中的数据进行绑定,数据只能从data流向页面
2、双向绑定v-model: v-model将表单元素中value数据和vue实例中的数据进行绑定,
                   数据不仅能从data流向页面,还可以从页面流向data
备注:
      1、双向绑定一般都应用在表单数据上(如: input  select 等)
      2、v-model:value可以简写成v-model,因为v-model默认绑定在表单的value属性上

注意:
1、v-model中除了绑定value上之外,还有多选框的checked属性
<input type="checkbox" v-model="isChecked">

2、v-model还可以绑定到绑定到自定义属性上
<custom-component v-model="selectedValue"></custom-component>
custom-component是后面会学到的自定义组件名称

<!DOCTYPE html>
<html lang="en">
  <head>
    ...
    <script type="text/javascript" src="../vue.js"></script>
  </head>

  <body>
    <div class="root">
      单向绑定v-bind:<input type="text" :value="name" /><br />
      双向绑定v-model:<input type="text" v-model="name" />
    </div>
    <script type="text/javascript">
      new Vue({
        el: ".root",
        data: {
          name: "张三",
        },
      });
    </script>
  </body>
</html>
4、data和el配置的两种写法
data和el的两种写法:

1、el两种写法:
1)、new Vue的时候配置el属性
2)、先创建Vue实例,随后用过vm.$mount('.root')制定el的值

2、data的两种写法:对象式、函数式

<!DOCTYPE html>
<html lang="en">
  <head>
   ...
    <script type="text/javascript" src="../vue.js"></script>
  </head>

  <body>
    <div class="root">
      <h1>你好,{{name}}</h1>
    </div>
    <script>
      const vm = new Vue({
        // el: ".root",
        // data: {
        //   name: "张三",
        // },
        data() {
          return {
            name: "张三",
          };
        },
      });

      // 异步挂载vue实例对象
      setTimeout(() => {
        vm.$mount(".root");
      }, 1000);
    </script>
  </body>
</html>
5、vue上的MVVM模型
MVVM(Model-View-ViewModel)是一种用于构建用户界面的软件架构模式,
而在Vue.js中,就采用了MVVM模型。

Model(模型):
在Vue中,模型可以被定义为Vue实例的data属性,即组件所依赖的数据。这些数据通常保存着应用程序的状态。

View(视图):
在Vue中,视图通常使用Vue的模板语法编写,可以通过指令、表达式等方式与数据绑定,使得数据变化会自动更新到视图上。

ViewModel(视图模型):
在Vue中,视图模型指的是vue的实例对象,实例对象上存在data、methods等属性操作数据。
1、视图模型可以实现模型和视图之间相关数据之间的转换。
2、视图模型还可以通过观察模型的变化来更新视图,或者通过触发事件来与模型进行通信。

MVVM模型在Vue.js中的工作流程可以概括为以下几个步骤:
1、创建一个Vue实例,并定义数据模型。
2、在模板中使用Vue的指令和表达式将视图和数据进行绑定。
3、用户与视图进行交互时,触发视图模型中的操作行为。
4、视图模型根据用户的操作对数据进行处理或者更新。
5、数据变化时,视图模型会自动将变化更新到视图上。

<!DOCTYPE html>
<html lang="en">
  <head>
    ...
    <script type="text/javascript" src="../js/vue.js"></script>
  </head>

  <body>
    <!-- 在容器中的就是视图 -->
    <div class="root" :name="name">
      <h3>你好,我是{{name}},今年{{age}}岁</h3>
    </div>
    <script type="text/javascript">
      // 这里的vm就是vue实例对象,也就是进行模型和视图通信的视图模型
      const vm = new Vue({
        el: ".root",
        // data就是模型
        data: function () {
          return {
            name: "张三",
            age: 20,
          };
        },
      });
    </script>
  </body>
</html>
对象属性删除的常见方式:

扩展:
<!DOCTYPE html>
<html lang="en">
  <head>
    ...
  </head>
  <body>
    <script>
      const obj = {
        name: "张三",
        age: 20,
        sex: "男",
        info: "中国人",
        height: "190cm",
        weight: "69kg",
      };
      // 删除方式1:设置属性成undefined
      obj.name = undefined;
      console.log(obj);
      // 删除方式2:使用delete直接删除
      delete obj.age;
      console.log(obj);
      // 删除方式3:解构赋值,注意这里需要sex属性放在前面
      const { sex, ...obj1 } = obj;
      console.log(obj1);
      // 删除方式4:使用Reflect
      // ES6新增的方法,Reflect.deleteProperty(对象,属性名),返回一个布尔值。
      Reflect.deleteProperty(obj, "info");
      console.log(obj);
      // 删除方式5:使用Object.defineProperty()
      Object.defineProperty(obj, "height", {
        value: undefined,
        writable: false, //设置是否被修改
        enumerable: false, //设置是否被枚举(遍历的意思)
        configurable: false, //设置是否被删除
      });
      console.log(obj);
    </script>
  </body>
</html>
6、数据代理_Object.defineProperty()
<!DOCTYPE html>
<html lang="en">
  ...
  <body>
    <script type="text/javascript">
      let person = { name: "张三" };
      let number = 20;
      // 使用Object.Property()函数添加的对象的属性是不能被枚举的,也就是不能被用来进行遍历对象属性
      // 如果想要被枚举,可以使用enumerable配置为true
      Object.defineProperty(person, "age", {
        // value: number,
        //如果在直接以赋值的方式,number变量改变后,age的值是不会改变的,因为没有return值来改变age的值
        // enumerable: true, //控制属性是否可以被枚举,默认值是false
        // writable: true,//控制属性是否可以被修改,默认值是false
        // configurable: true,//控制属性是否可以被删除,默认值是false

        // 当有人读取person的age属性时,get函数(getter)就会被调用,并且返回就是age的值
        // 今后get()函数可以叫做getter,getter就是表示get()函数的意思
        // 如果想要动态的改变变量的值,使用return方式,变量number的值改变,return就可以随时改变age的值
        get() {
          return number;
        },
        // setter:set方法是age的值改变的话,通过number=value,number的值随时改变
        set(value) {
          console.log("有人修改age属性,且值为", value);
          number = value;
        },
      });
    </script>
  </body>
</html>
7、vue上的数据代理
1、vue中的数据代理:
   通过vm对象来代理data对象中的属性的操作(读和写)
2、vue中的数据代理的好处:
   更加方便的操作data中的数据
3、基本原理:
   通过Object.definePorperty()把data对象中的所有属性添加到vm上
   为每一个添加到vm上的属性都制定一个getter和setter
   在getter和setter内部去操作(读和写)data中对应的属性

<!DOCTYPE html>
<html lang="en">
  <head>
    ...
    <title>vue中的数据代理</title>
    <script type="text/javascript" src="../js/vue.js"></script>
  </head>

  <body>
    <!-- 
      在Vue中,数据代理是一种机制,它允许你将Vue实例的属性访问映射到其data对象中定义的属性上。
      这样一来,你可以直接通过Vue实例访问和修改data对象中的属性,而不需要通过额外的步骤。
      下面是一个示例,展示如何在Vue中使用数据代理:
     -->
    <div id="app">
      <p>{{ message }}</p>
      <button @click="updateMessage">更新消息</button>
    </div>
    <script type="text/javascript">
      var app = new Vue({
        el: "#app",
        data: {
          message: "Hello, Vue!",
        },
        methods: {
          updateMessage() {
            this.message = "Updated message"; // 直接修改message属性
          },
        },
      });
      /* 
        在上面的示例中,我们创建了一个Vue实例,并在data选项中定义了一个名为message的属性。
        通过数据代理,我们可以直接在Vue实例中访问message属性,而不需要通过data对象。

        通过Vue的响应式,当message属性的值发生变化时,相关的DOM会自动更新以反映这个变化。

        数据代理使得在Vue中操作数据变得更加简单和直观。
        你可以像操作普通JavaScript对象一样操作Vue实例的属性,而无需担心手动触发更新或其他复杂的步骤。
      */
    </script>
  </body>
</html>
8、vue中的事件处理
事件的基本使用:
    1、使用v-on:xxx 或者 @xxx 绑定事件,其中xxx是事件名称
    2、事件的回调需要配置在methods对象中,最终会在vm上
    3、methods中配置的函数,不要使用箭头函数,否则this指向就不是vm上
    4、methods中配置的函数,都是被vue所管理的函数,this的指向是vm或者组件实例对象
    5、@click = 'function' 或者是 @click = 'function($event)' 效果都是一样的,但是后者可以传入参数,建议使用

<!DOCTYPE html>
<html lang="en">
  <head>
   ...
    <script type="text/javascript" src="../js/vue.js"></script>
  </head>

  <body>
    <div class="root">
      <h1>事件处理</h1>
      <h1>点击前往{{name}}</h1>
      <!-- 这里的@click完整写法是 v-on:click -->
      <button @click="handleClick">点击提示信息</button>

      <!-- 触发事件试如果需要给函数传递参数,如果包含有需要获取事件对象,
           需要加上一个@event(位置写前后都行),如下 -->
      <button @click="handleClick(66,$event)">点击提示信息</button>
      <button @click="handleClick1($event,66)">点击提示信息</button>
    </div>
    <script type="text/javascript">
      const vm = new Vue({
        el: ".root",
        data: {
          name: "张三",
          // 在data中也是可以写上函数的,但是不规范
          handleClick1(event, num) {
            // event就是事件对象
            // console.log(event instanceof Event);//true
            console.log(event);
            // event.target就是页面中的dom元素
            // console.log(event.target instanceof HTMLElement);//true
            console.log(event.target);
          },
        },
        // 事件处理时需要使用多假methods配置项,虽然data也是可以写上函数,但是为了美观和规范
        methods: {
          handleClick(num, event) {
            // event就是事件对象
            // console.log(event instanceof Event);//true
            console.log(event);
            // event.target就是页面中的dom元素
            // console.log(event.target instanceof HTMLElement);//true
            console.log(event.target);
          },
        },
      });
    </script>
  </body>
</html>
9、vue中的事件修饰符
<!DOCTYPE html>
<html lang="en">
  <head>
   ...
    <script type="text/javascript" src="../js/vue.js"></script>
  </head>
  <style>
    * {
      margin-top: 20px;
    }

    .demo {
      height: 50px;
      background-color: skyblue;
    }

    .demo1 {
      height: 30px;
      background-color: pink;
    }

    .demo2 {
      height: 200px;
      width: 200px;
      overflow: auto;
      background-color: pink;
    }

    li {
      height: 100px;
    }
  </style>

  <body>
    <!-- 
        Vue中的事件修饰符:
        1、prevent:阻止默认事件(常用)
        2、stop: 阻止事件冒泡(常用)
        3、once:事件只触发一次(常用)
        4、capture:使用事件的捕获模式
        5、self:只有evenet.target是当前操作的元素才触发事件
        6、passive:事件的默认行为立即执行,无需等待事件回调执行完毕

     -->
    <div class="root">
      <h1>事件修饰符</h1>
      <h1>点击前往{{name}}</h1>
      <!-- 1、阻止事件默认行为 -->
      <a :href="href" @click.prevent="handleClick" style="text-decoration: none"
        >点击我提示信息</a
      >
      <!-- 2、阻止事件冒泡 -->
      <div class="demo" @click="handleClick">
        <!-- 在标签中,如果在哪个对象上触发事件,不想要事件被往上冒泡的话,就需要在本标签身上设置stop禁止冒泡 -->
        <div class="demo" @click.stop="handleClick">
          <!-- stop在Vue中的写法,在js中是stopPropagation()方法-->
          <button @click.stop="handleClick">点击我提示信息1</button>
        </div>
      </div>
      <!-- 在这里,在事件上设置once表示代码执行后,被设置的事件只能被触发一次 -->
      <!-- <button @click.once='click'>点击事件,只触发一次</button> -->
      <!-- 3、设置事件触发一次 -->
      <div class="demo">
        <!-- 如果需要在事件上有多个修饰符,可以并列设置进行链式调用 -->
        <button @click.stop.once="handleClick">点击一次,并且阻止冒泡</button>
      </div>

      <!-- 4、设置事件触发是在捕获阶段 -->
      <div class="demo" @click.capture="handleClick1('div')">
        <button @click="handleClick1('button')">
          点击事件,使用事件捕获模式
        </button>
      </div>

      <!-- 5、self:只有event.target是当前操作的元素才触发事件 -->
      <!-- 注意:self使用是在对象被操作的时才会被触发事件,和stop阻止冒泡的作用的一样的 -->
      <div class="demo" @click.self='handleClick1(" demo")'>
        <button @click='handleClick1(" button")'>
          self修饰符,点击提示信息
        </button>
      </div>

      <!-- 6、passive:事件的默认行为立即执行,无需等待事件回调执行完毕 -->
      <!-- scroll事件触发后,效果直接执行 -->
      <ul class="demo2" @scroll="func">
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
      </ul>
      <!-- wheel事件触发后,需要代码执行的复杂的话,效果会出现停顿现象,这时可以设置passive来解决停顿的问题 -->
      <ul class="demo2" @wheel.passive="func">
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
      </ul>
    </div>
    <script type="text/javascript">
      const vm = new Vue({
        el: ".root",
        data: {
          name: "张三",
          href: "http://baidu.com",
        },
        methods: {
          handleClick(event) {
            // event.preventDefault();
            alert(`你好,我是${this.name}`);
          },
          handleClick1(str) {
            alert(str);
          },
          func() {
            for (let i = 0; i < 10000; i++) {
              console.log("@");
            }
          },
        },
      });
    </script>
  </body>
</html>
10、事件修饰符的链式调用
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <script src="../vue.js"></script>
  <body>
    <div class="root">
      <div class="div" @click="getinfo($event,100)">
        <!-- 事件修饰符可以链式调用 -->
        <a :href="href" @click.stop.prevent="toOther">点击跳转链接</a>
      </div>
    </div>
    <script>
      new Vue({
        el: ".root",
        data: { href: "http://baidu.com" },
        methods: {
          toOther() {
            alert("正在跳转");
          },
          getinfo(e, a) {
            console.log(e.target);
            alert("获取数据", a);
          },
        },
      });
    </script>
  </body>
</html>
11、键盘事件
<!DOCTYPE html>
<html lang="en">
  <head>
    ...
    <title>键盘事件</title>
    <script type="text/javascript" src="../js/vue.js"></script>
  </head>

  <body>
    <!-- 
        1、vue中常用的按键别名:
        回车enter/Enter
        删除delete(捕获删除delete和退格键backspace)
        退出esc
        空格space
        换行tab(特殊键,需要在绑定keydown下触发)
        上up 
        下down
        左left
        右right

        2、vue未提供别名的按键,可以使用按键原始的key值去绑定,但是注意要转为kebab-case(短横线命名)
        3、系统修饰符(用法特殊):ctrl键、alt键、shift键、meta键
            1)、配合keyup使用:按下修饰键的同时,再按下其他键,随后释放其他键,事件才能被触发
            2)、配合keydown使用:正常触发事件
        4、也可以使用keyCode去指定具体的按键(已被废弃)
        5、vue.config.keyCodes.自定义键名 = 键码,可以去定制按键别名

     -->
    <div class="root">
      <h1>键盘事件</h1>
      <h2>学校:{{name}}</h2>
      <!-- 注意,如果在键盘弹起需要获取input中的内容的话,需要使用value,不然使用placeholder的内容会直接被清空,
           因为placeholder属性是键盘一输入,placeholder内容就会被清空 -->
      <input type="text" value="keyup键盘事件" @keyup="keyup" />
      <br />

      <!-- 在键盘事件绑定上设置按键时,不需要区分大小写的 -->
      <input type="text" value="keyup.enter键盘事件" @keyup.enter="keyup1" />

      <!-- vue中常用的按键:enter  delete  esc  space  tab(特殊键,需要绑定keydown事件)  up  down left  right -->
      <div><input type="text" value="按下enter键" @keyup.enter="keyup1" /></div>
      <div>
        <input type="text" value="按下delete键" @keyup.delete="keyup1" />
      </div>
      <div><input type="text" value="按下esc键" @keyup.esc="keyup1" /></div>
      <div><input type="text" value="按下space键" @keyup.space="keyup1" /></div>
      <div>
        <input
          type="text"
          value="按下tab键,绑定的时keydown事件"
          @keydown.tab="keydown1"
        />
      </div>
      <div><input type="text" value="按下up键" @keyup.up="keyup1" /></div>
      <div><input type="text" value="按下down键" @keyup.down="keyup1" /></div>
      <div><input type="text" value="按下left键" @keyup.left="keyup1" /></div>
      <div><input type="text" value="按下right键" @keyup.right="keyup1" /></div>

      <hr />
      <!-- ctrl  alt  shift  meta  -->
      <div>
        <input type="text" value="按下ctrl键,在按下任意键" @keyup="keyup1" />
      </div>
      <div>
        <input
          type="text"
          value="按下ctrl键,在按下a键,相对于上面,这里是设置了需要按下a键才触发"
          @keyup.a="keyup1"
        />
      </div>

      <div>
        <input
          type="text"
          value="按下alt键,这里绑定的是keydown事件,这样在键按下时就触发"
          @keydown="keydown1"
        />
      </div>
      <div>
        <input
          type="text"
          value="按下shift键,这里绑定的是keydown事件,这样在键按下时就触发"
          @keydown="keydown1"
        />
      </div>
      <!-- <div><input type="text" value="按下meta键,这里绑定的是keydown事件,这样在键按下时就触发" @keydown='keydown1'></div> -->
      <!-- <div><input type="text" value="按下meta键,再按下其他键" @keyup='keyup1'></div> -->

      <hr />
      <h2>这里是自定义的键名</h2>
      <div>
        <input type="text" value="自定义的键名" @keyup.huiche="keyup1" />
      </div>
    </div>
    <script type="text/javascript">
      Vue.config.keyCodes.huiche = 13; //自定义键名

      const vm = new Vue({
        el: ".root",
        data: {
          name: "张三",
        },
        methods: {
          keyup(e) {
            if (e.keyCode !== 13) return;
            console.log(e.target.value);
          },
          keyup1(e) {
            console.log(e.target.value);
          },
          keydown1(e) {
            console.log("你出发的keydown事件");
          },
        },
      });
    </script>
  </body>
</html>
12、计算属性
计算属性:
1、定义:是一种特殊的属性,它的值是根据其他响应式数据计算得出的,并且会缓存计算结果。
        计算属性通常用于从已有的数据派生出新的数据。
2、原理:底层借助了Object.defineProperty()方法提供的getter和setter
3、get函数什么时候执行?
   1)、初次读取时会执行一次
   2)、当依赖的数据发生改变时会被再次调用
4、优势:与methods实现相比,内部有缓存机制(复用),效率更高,调式方便
5、备注:
   1)、计算属性最终会出现在vm上,和直接读取data数据中的数据一样即可
   2)、如果计算属性要被修改,必须写set函数去响应修改,并且set中要引起计算时依赖的数据发生改变,
        就是如果set中依赖data中的数据属性,如果set响应修改,需要对data中的数据修改

补充:

1、计算属性具有缓存机制,只有依赖的响应式数据发生改变时,才会重新计算计算属性的值。
这意味着多次访问同一个计算属性时,只会执行一次计算操作,后续访问将直接返回缓存的结果。

2、通过使用计算属性,可以更加方便地处理复杂的逻辑和数据派生。
在模板中可以像访问普通属性一样访问计算属性,而无需手动调用它们的函数。

<!DOCTYPE html>
<html lang="en">
  <head>
    ...
    <script type="text/javascript" src="../js/vue.js"></script>
  </head>

  <body>
    <div class="root">
      <h1>计算属性</h1>
      姓:<input type="text" v-model="firstname" /><br /><br />
      名:<input type="text" v-model="lastname" /><br /><br />
      全名:<span>{{fullname}}</span>
    </div>
    <script type="text/javascript">
      const vm = new Vue({
        el: ".root",
        data: {
          firstname: "张",
          lastname: "三",
        },
        // 注意:computed属性的数据不能写在data中
        computed: {
          fullname: {
            // getter是当模板中数据发生变化,模板重新检验执行fullname,vue自动调用getter来获取数据显示在页面上
            get() {
              return this.firstname + "-" + this.lastname;
            },
            // setter是当模板中fullname的数据改变时,修改data中的数据
            set(value) {
              const arr = value.split("-");
              this.firstname = arr[0];
              this.lastname = arr[1];
            },
          },
        },
      });
    </script>
  </body>
</html>
13、监视属性
监视属性watch:
1、当被监视的属性变化时,回调函数自动调用,进行相关操作
2、监视的属性必须存在,才能进行监视
3、监视的两种方法:
   1)、new Vue()时传入watch配置
   2)、通过vm.$watch()函数接口监视
        vm.$watch('监视的属性,这里必须加上引号',{监视的内容,就是执行代码})

<!DOCTYPE html>
<html lang="en">
  <head>
    ...
    <script type="text/javascript" src="../js/vue.js"></script>
  </head>

  <body>
    <div class="root">
      <h1>监视属性</h1>
      姓:<input type="text" v-model="firstname" /><br /><br />
      名:<input type="text" v-model="lastname" /><br /><br />
      全名:<span>{{fullname}}</span>
      <hr />
      <h3>为了测试watch属性的完整写法:{{name}}</h3>
    </div>
    <script type="text/javascript">
      const vm = new Vue({
        el: ".root",
        data: {
          //vue中认为data中的属性就是vue中的属性
          firstname: "张",
          lastname: "三",
          fullname: "张-三",
          name: "李四",
        },
        // 监视属性是监视的数据(data或者是computed中的数据)发生变化时,进行代码操作
        watch: {
          // 这里监视data中两个数据
          // newValue, oldValue分别是修改之后和修改之前的数据
          // 这里是watch的简写形式,如果监视属性中不需要使用immediate和deep配置项的话就可以这样
          firstname(newValue, oldValue) {
            return (this.fullname = newValue + "-" + this.lastname);
          },
          lastname(newValue, oldValue) {
            return (this.fullname = this.firstname + "-" + newValue);
          },
          // 第一种写法
          // name: {
          //   immediate: true,
          //   handler(newValue, oldValue) {
          //     this.name = newValue;
          //     console.log("发生变化了");
          //   },
          // },
        },
      });

      // 监视属性的第二种写法
      vm.$watch("name", {
        immediate: true,
        handler(newValue, oldValue) {
          this.name = newValue;
          console.log("发生变化了");
        },
      });
    </script>
  </body>
</html>
14、深度监视
深度监视:deep属性

1)、vue中的watch默认不监视对象内部值的改变(一层)
2)、配置deep:true可以监视对象内部值的改变(多层)

备注:
1)、vue自身可以监视对象内部值的改变,但是vue提供的watch默认不可以监视对象内部值
2)、使用watch时根据数据得具体结构,决定是否采用深度监视

<!DOCTYPE html>
<html lang="en">
  <head>
    ...
    <script type="text/javascript" src="../js/vue.js"></script>
  </head>

  <body>
    <div class="root">
      <h1>深度属性</h1>
      <button @click="numbers.a++">点击a自增{{numbers.a}}</button><br /><br />
      <button @click="numbers.b++">点击b自增{{numbers.b}}</button><br /><br />
    </div>
    <script type="text/javascript">
      const vm = new Vue({
        el: ".root",
        data: {
          numbers: {
            a: 100,
            b: 200,
          },
        },
        watch: {
          numbers: {
            //在watch中,默认是不能监视到对象得内部值的,如果需要监视的话,需要给deep值改成true
            deep: true,
            handler() {
              console.log("numbers中发生改变");
            },
          },
        },
      });
    </script>
  </body>
</html>


15、计算属性和监视属性的比较
1、计算属性:

计算属性是根据已有的响应式数据计算得出的属性。它定义在 computed 选项中,通常是一个函数。
计算属性具有缓存特性,只有当计算属性依赖的响应式数据发生变化时,才会重新计算该属性的值。这意味着在多次访问该计算属性时,如果其依赖未发生变化,则会直接返回缓存的值,避免重复计算。
计算属性适用于需要根据其他数据进行计算或处理逻辑的场景。例如,根据数组的长度动态计算出列表的个数。

2、监视属性:

监视属性用于监听某个数据的变化并执行相应操作。它定义在 watch 选项中,通常是一个对象。
监视属性通过配置要监听的数据以及相应的回调函数,当被监听的数据发生变化时,监视属性的回调函数会被触发执行。
监视属性适用于需要在数据变化时进行自定义操作或执行异步请求的场景。例如,监听搜索关键字的变化并发送网络请求获取搜索结果。
16、样式绑定
绑定样式:
1、class绑定样式:
   写法:class='xxx' xxx可以是字符串、对象、数组
   字符串写法适用于:类名不确定,要动态获取
   对象写法适用于:要绑定多个样式,个数不确定,名字也不确定
   数组写法适用于:要绑定多个样式,个数却ing,名字也确定,但是不确定用不用
        
2、style样式:
   :style="{fontSize:xxx}"其中xxx是动态值
   :style="[a,b]"其中a,b是样式对象

<!DOCTYPE html>
<html lang="en">
  <head>
    ...
    <script type="text/javascript" src="../js/vue.js"></script>
  </head>
  <style>
    .basic {
      box-sizing: border-box;
    }

    .basic {
      width: 300px;
      height: 100px;
      border: 4px solid #333;
      padding: 20px;
    }

    .happy {
      border: 4px solid red;
      background-color: rgba(255, 255, 0, 0.644);
      background: linear-gradient(30deg, yellow, pink, orange, yellow);
    }

    .sad {
      border: 4px dotted green;
      background-color: #666;
    }

    .normal {
      border: 4px solid #000;
      background-color: skyblue;
    }

    .style1 {
      font-size: 28px;
    }

    .style2 {
      font-weight: 600;
    }

    .style3 {
      border-radius: 20px;
    }
  </style>

  <body>
    <div class="root">
      <h3>绑定class样式</h3>
      <hr />
      <!-- 绑定class样式--字符串写法,适用于:样式的类名不确定,需要动态指定 -->
      <div class="basic" :class="mood" @click="changeMood">{{content}}</div>
      <br /><br />

      <!-- 绑定class样式--数组写法,适用于:要绑定的样式个数不确定几个,需要绑定样式的名字也不确定 -->
      <!-- <div class="basic" :class="[' style1', 'style2' , 'style3' ]">{{content}}</div> -->
      <!-- <div class="basic" :class="[a,b,c]">{{content}}</div> -->
      <div class="basic" :class="classArr">{{content}}</div>
      <br /><br />

      <!-- 绑定class样式--对象写法,适用于:要绑定的样式个数确定、名字也确定,但是要动态指定用不用 -->
      <div class="basic" :class="classObj">{{content}}</div>
      <br /><br />

      <!-- 在样式绑定中,写的是表达式就可以,也是使用对象的形式给style绑定 -->
      <div class="basic" :style="{fontSize:'40px'}">{{content}}</div>
      <br /><br />
      <!-- 绑定style样式,使用的是对象的形式 -->
      <div class="basic" :style="styleObj">{{content}}</div>
      <br /><br />

      <!-- 使用数组的形式给style绑定样式 -->
      <div class="basic" :style="styleArr">{{content}}</div>
      <br /><br />
    </div>
    <script type="text/javascript">
      const vm = new Vue({
        el: ".root",
        data: {
          content: "test",
          mood: "normal",
          classArr: ["style1", "style2", "style3"],
          // a: 'style1',
          // b: 'style2',
          // c: 'style3',
          classObj: {
            style1: true,
            style2: true,
          },
          styleObj: {
            fontSize: "40px",
            backgroundColor: "pink",
          },
          styleArr: [
            {
              fontSize: "40px",
              // backgroundColor: 'pink',
            },
            {
              backgroundColor: "pink",
            },
          ],
        },
        methods: {
          changeMood() {
            const arr = ["happy", "sad", "normal"];
            const index = Math.floor(Math.random() * 3);
            this.mood = arr[index];
          },
        },
      });
    </script>
  </body>
</html>
17、条件渲染
条件渲染的指令:
1、v-if v-else-if v-else 
2、v-show

比较v-if和v-show的区别:
1、如果需要频繁的切换的话,使用v-show比较好,因为不展示的dom元素节点没有被移除,仅仅时使用样式隐藏
2、v-if适用于切换频率比较低的场景,因为不展示的dom元素节点直接被移除
3、当条件不成立时,v-if的所有子节点不会被解析(项目中使用)
4、如果使用v-if来条件渲染,过程中不能被打断,打断就是在代码中间插入其他的代码语句
5、优化:使用remplate和v-if的结合使用,注意:template只能和v-if使用。不能和v-show使用

<!DOCTYPE html>
<html lang="en">
  <head>
    ...
    <script type="text/javascript" src="../js/vue.js"></script>
  </head>
  <body>
    <div class="root">
      <h1>条件渲染</h1>
      <h3 @mouseover="func" :style="style">
        <span v-show="boolean">{{info}}</span>
      </h3>
      <br /><br />
      <h3>
        <button @click="click">点击我</button><br /><br />
        <span v-if="1==n">是1就显示</span>
        <span v-else-if="2==n">是2就显示</span>
        <span v-else="3==n">是3就显示</span>
      </h3>
      <br /><br />
      <template v-if="1===n">
        <span>你好</span><br /><br />
        <span>张三</span><br /><br />
        <span>广州</span><br /><br />
      </template>
    </div>
    <script type="text/javascript">
      const vm = new Vue({
        el: ".root",
        data: {
          info: "显示和隐藏",
          boolean: "false",
          style: {
            backgroundColor: "pink",
            height: "40px",
          },
          n: 1,
        },
        methods: {
          func() {
            this.boolean = !this.boolean;
          },
          click() {
            this.n++;
          },
        },
      });
    </script>
  </body>
</html>
18、列表渲染
v-for指令
1、用于展示列表数据
2、语法:v-for='(irem,index) in xxx' :key = 'yyy'
3、可便利:数组、对象、字符串(用的少)、指定次数(用的少)

<!DOCTYPE html>
<html lang="en">
  <head>
    ...
    <script type="text/javascript" src="../js/vue.js"></script>
  </head>

  <body>
    <div class="root">
      <h1>列表渲染</h1>
      <ul>
        <div>人员列表</div>

        <!-- 遍历数组 -->
        <button @click="add">点击添加人数</button>
        <li v-for="p of personArr" :key="p.id">
          {{p.name+'-'+p.age}}
          <input type="text" :value='p.name+"-"+p.age' />
        </li>
        <hr />
        <!-- 遍历对象 -->
        <li v-for="p in carObj">{{p}}</li>
        <hr />
        <!-- 遍历字符串 -->
        <li v-for="p,index in str">{{p}}---{{index}}</li>
        <hr />
        <!-- 遍历次数 -->
        <li v-for="(p,index) in numbers">{{p}}---{{index}}</li>
      </ul>
    </div>
    <script type="text/javascript">
      const vm = new Vue({
        el: ".root",
        data: {
          personArr: [
            { id: "001", name: "张三", age: 18 },
            { id: "002", name: "李四", age: 19 },
            { id: "003", name: "王五", age: 20 },
          ],
          carObj: {
            name: "奥迪A8",
            price: "70万",
            color: "黑色",
          },
          str: "hello",
          numbers: 10,
        },
        methods: {
          add() {
            const person = { id: "004", name: "老刘", age: 40 };
            return this.personArr.unshift(person);
          },
        },
      });
    </script>
  </body>
</html>
19、列表渲染中keys的原理和作用
key有什么作用?(key的内部原理)
1、虚拟dom中的key的作用:
key是虚拟dom对象的标识,当状态中的数据发生变化时,vue会根据【新数据】生成【新的虚拟dom】
随后vue进行【新虚拟dom】与【旧的虚拟dom】的差异相比(虚拟dom对比算法diff),比较规则如下:

2、对比规则:
1)、旧虚拟dom中找到了与新建虚拟dom相同的key:
     若虚拟dom中内部改变,直接使用之前的真实dom,叫做复用
     若虚拟dom中的内容变了,则生成新的真实dom,随后替换掉页面中之前的真实dom

2)、旧虚拟dom中未找到与新虚拟dom相同的key
     创建新的真实dom,随后渲染到页面

3、用index作为key可能会引起的问题:
   1)、若对数据进行:逆序添加、删除等破坏顺序的操作
        会产生没有必要的真实dom更新==>界面效果没有问题,但是效率低

   2)、如果结构中还包含输入类的dom:
        会产生错误dom更新==>界面有问题,就是会到值导致数据对应不上

<!DOCTYPE html>
<html lang="en">
  <head>
    ...
    <script type="text/javascript" src="../js/vue.js"></script>
  </head>

  <body>
    <div class="root">
      <h3>列表渲染重点</h3>
      <!-- 遍历数组,遍历的是数组的元素,并且点击按钮添加数据 -->
      <button @click="add">遍历数组,并且点击按钮添加数据</button><br /><br />
      <!-- :key='p.id'中不管是数组元素中的id属性或者是name属性,只要能够区分数组元素,都是可以使用的 -->
      <div v-for="(p,index) in persons" :key="p.id">
        {{p.name}}---{{p.age}}
        <input type="text" :value='p.name+"-"+p.age' />
      </div>
      <!-- 使用index索引作为key,如果是push和pop的按照顺序的方式操作数组,对数组印象不大
      但是如果使用unshift和shift来操作元素的话就会影响效率 -->
      <div v-for="(p,index) in persons" :key="index">
        {{p.name}}---{{p.age}}
        <input type="text" :value='p.name+"-"+p.age' />
      </div>
    </div>
    <script type="text/javascript">
      const vm = new Vue({
        el: ".root",
        data: {
          persons: [
            { id: "001", name: "张三", age: 18 },
            { id: "002", name: "李四", age: 19 },
            { id: "003", name: "王五", age: 20 },
          ],
        },
        methods: {
          add() {
            return this.persons.unshift({ id: "004", name: "老刘", age: 40 });
          },
        },
      });
    </script>
  </body>
</html>

后续前往CSDN

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值