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

20、列表渲染加过滤
<!DOCTYPE html>
<html lang="en">
  <head>
    。。。
    <script type="text/javascript" src="../js/vue.js"></script>
  </head>

  <body>
    <div class="root">
      <h3>人员列表</h3>
      <input type="text" v-model="keyWord" :style="style1" /><br /><br />
      <!-- 最好这里设置key,且值是id -->
      <div v-for="p,index in filPersons" :key="p.id">
        {{p.name}}-{{p.age}}-{{p.sex}}
      </div>
    </div>
    <script type="text/javascript">
      // 练习使用计算属性
      const vm = new Vue({
        el: ".root",
        data: {
          keyWord: "",
          style1: {
            outline: "none",
            border: "2px solid red",
            borderRadius: "5px",
            width: "200px",
            height: "20px",
            colir: "#000",
            paddingLeft: "10px",
          },
          persons: [
            { id: "001", name: "张三", age: 18, sex: "男" },
            { id: "002", name: "李四", age: 19, sex: "男" },
            { id: "003", name: "王五", age: 20, sex: "男" },
            { id: "004", name: "赵六", age: 21, sex: "男" },
          ],
          filPersons: [],
        },
        // 通过计算属性来进行过滤。使用filter函数,filter不改变原数组
        // computed: {
        //   filPersons() {
        //     return this.persons.filter((item) => {
        //       return item.name.indexOf(this.keyWord) !== -1;
        //     });
        //   },
        // },
        watch: {
          keyWord: {
            // 因为设置keyWord初始值是空字符串,所以这里过过滤出来的是整个数组
            immediate: true,
            handler(value) {
              this.filPersons = this.persons.filter((item) => {
                return item.name.indexOf(value) !== -1;
              });
            },
          },
        },
      });
    </script>
  </body>
</html>
21、列表渲染和排序
<!DOCTYPE html>
<html lang="en">
  <head>
    。。。
    <script type="text/javascript" src="../js/vue.js"></script>
  </head>

  <body>
    <div class="root">
      <h3>人员列表</h3>
      <input type="text" v-model="keyWord" :style="style1" />
      <button @click="sortType=2">年龄升序</button>
      <button @click="sortType=1">年龄降序</button>
      <button @click="sortType=0">原顺序</button>
      <div v-for="p,index in filPersons">{{p.name}}-{{p.age}}-{{p.sex}}</div>
    </div>
    <script type="text/javascript">
      const vm = new Vue({
        el: ".root",
        data: {
          keyWord: "",
          style1: {
            outline: "none",
            border: "2px solid red",
            borderRadius: "5px",
            width: "200px",
            height: "20px",
            color: "#000",
            paddingLeft: "10px",
          },
          persons: [
            { id: "001", name: "张三", age: 18, sex: "男" },
            { id: "002", name: "李四", age: 19, sex: "男" },
            { id: "003", name: "王五", age: 20, sex: "男" },
            { id: "004", name: "赵六", age: 21, sex: "男" },
          ],
          sortType: 0, //0原顺序   1降序  2升序
        },
        computed: {
          filPersons() {
            // 先过滤
            const arr = this.persons.filter((item) => {
              return item.name.indexOf(this.keyWord) !== -1;
            });
            // 使用数组的sort函数进行排序
            // sort((a,b)=>{}) a-b的话就是从大到小 b-a的话就是从小到大
            if (this.sortType) {
              arr.sort((p1, p2) => {
                return this.sortType === 1 ? p2.age - p1.age : p1.age - p2.age;
              });
            }
            return arr;
          },
        },
      });
    </script>
  </body>
</html>
22、vue中对数组的特殊操作
数组中:
push()从尾部插入  
pop()从尾部删除
shift()从头部删除 
unshift()从头部插入

vue中也有类似数组的方法,但是vue中的插入push和删除pop等方法和数组中的插入和删除方法是不相同的
vue中的插入和删除方法是包装了数组中的插入和删除方法。例如,vue中的push()不仅调用了数组中push(),
但是还对页面进行解析才形成了vue中的push(),所以Vue.protoType.push()!==Array.protoType.push()

使用字符串中的方法
splice(索引值,长度,[可选的])是如果可选的参数位置不写,表示获取子字符串
如果第三个参数有写,表示在索引值和长度获取的内容被替换掉
(这里的内容可以是子字符串,可以是数组中指定的元素)

reverse()逆序操作

vue将被侦听的数组的变更方法进行了包裹,所以它们也将会触发视图更新。这些被包裹的方法包括:
push()、pop()、shift()、unshift()、splice()、sort()、reverse()

数组更新时的问题:就是原始的js对数组的增删等操作在页面中不能进行响应式,虽然可以修改数组内容
<!DOCTYPE html>
<html lang="en">
  <head>
    。。。
    <script type="text/javascript" src="../js/vue.js"></script>
  </head>

  <body>
    <div class="root">
      <h3>人员列表</h3>
      <button @click="updataZhang">点击按钮编辑张三信息</button>
      <!-- 这里最好使用id作为key标识符 -->
      <div v-for="p,index in persons" :key="p.id">
        {{p.name}}-{{p.age}}-{{p.sex}}
      </div>
    </div>
    <script type="text/javascript">
      // 练习使用计算属性
      const vm = new Vue({
        el: ".root",
        data: {
          persons: [
            { id: "001", name: "张三", age: 18, sex: "男" },
            { id: "002", name: "李四", age: 19, sex: "男" },
            { id: "003", name: "王五", age: 20, sex: "男" },
            { id: "004", name: "赵六", age: 21, sex: "男" },
          ],
        },
        methods: {
          updataZhang() {
            // 1、vue底层实现了对对象中每个属性进行响应式,所以这里修改成功
            // this.persons[0].name = "张老师";
            // 2、这里直接给数组修改元素是不成功的,数组数据是被修改的,但是vue没有给指定getter和setter,无法响应
            // 不成功原因:因为在vue中,数组元素是没有指定的getter和setter的,如果修改数组的内容,
            // 虽然数组元素内容被修改,但由于没有getter和setter,所以页面效果没有被响应
            // this.persons[0] = { id: "001", name: "张老师", age: 18, sex: "男" };
            // 3、上面数组中修改第一个元素的解决方法是:
            // 第一种:使用数组中的删除和插入方法
            // this.persons.shift(this.persons[0]);
            // this.persons.unshift({
            //   id: "001",
            //   name: "张老师",
            //   age: 18,
            //   sex: "男",
            // });
            // 4、splice()方法通过写上第三个参数也是可以对象数组元素中进行修改的,作用类似push和pop
            // this.persons.splice(0, 1, {
            //   id: "001",
            //   name: "张老师",
            //   age: 18,
            //   sex: "男",
            // });
            // 5、第二种:使用Vue.set()函数或者是vm.$set()函数用法一样
            // 这样是指定数组的索引值进行替换
            // Vue.set(this.persons, 0, {
            //   id: "001",
            //   name: "张老师",
            //   age: 18,
            //   sex: "男",
            // });
            this.$set(this.persons, 0, {
              id: "001",
              name: "张老师",
              age: 18,
              sex: "男",
            });
          },
        },
      });
    </script>
  </body>
</html>

23、使用Vue.set和vm.$set作用于对象和数组上
<!DOCTYPE html>
<html lang="en">
  <head>
    。。。
    <script type="text/javascript" src="../js/vue.js"></script>
  </head>

  <body>
    <div class="root">
      <h3>使用Vue.set和vm.$set作用于对象和数组上</h3>
      <button @click="addSex">给张三添加性别</button>
      <div v-for="(p, index) in person" :key="index">{{p}}</div>

      <button @click="addFriend">添加一个朋友</button>
      <button @click="updateFriend">修改一个朋友</button>
      <div v-for="(f, index) in friends" :key="f.id">{{f.name}}--{{f.age}}</div>
    </div>
    <script type="text/javascript">
      const vm = new Vue({
        el: ".root",
        data: {
          person: {
            name: "张三",
            address: "广州",
          },
          friends: [
            { name: "李四", age: 18 },
            { name: "王五", age: 19 },
          ],
        },
        methods: {
          addSex() {
            // 这里的sex必须使用引号,不然报错undefined
            // Vue.set(this.person, "sex", "男");
            this.$set(this.person, "sex", "男");
          },
          addFriend() {
            // 这里是在数组尾部加上人员信息,如果是在数组的索引0或1等已经存在人员信息的位置上,
            // 就表示修改数组的内容
            this.$set(this.friends, this.friends.length, {
              name: "赵六",
              age: 18,
            });
          },
          updateFriend() {
            this.$set(this.friends, 0, {
              name: "七七",
              age: 18,
            });
          },
        },
      });
      console.log(vm);
    </script>
  </body>
</html>
24、收集表单数据
收集表单数据:
若:<input type = 'text'/>,则v-model收集的是value的值,用户输入的就是value的值
若:<input type = 'radio'/>,则v-model收集的是value的值,且要给标签配置value的值
若:<input type = 'checkbox'/>,
    1、没有配置input的value的属性,那么收集的就是checked(勾选或者未勾选的,是布尔值)
    2、配置input的value属性:
       1)、v-model的初始值是非数组,那么收集的就是checked(勾选或者未勾选,是布尔值)
       2)、v-model的初始值是数组,那么收集的就是value组成的数组的内容
        
备注:v-model的三个修饰符:
     lazy:失去焦点再收集数据
     number:输入字符串转为i有效的数字,对后端向数据库保存数据比较友好操作
     trim:输入首位空格过滤

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

  <body>
    <!-- 
        收集表单数据:
        若:<input type = 'text'/>,则v-model收集的是value的值,用户输入的就是value的值
        若:<input type = 'radio'/>,则v-model收集的是value的值,且要给标签配置value的值
        若:<input type = 'checkbox'/>,
            1、没有配置input的value的属性,那么收集的就是checked(勾选或者未勾选的,是布尔值)
            2、配置input的value属性:
                1)、v-model的初始值是非数组,那么收集的就是checked(勾选或者未勾选,是布尔值)
                2)、v-model的初始值是数组,那么收集的就是value组成的数组的内容
        
        备注:v-model的三个修饰符:
        lazy:失去焦点再收集数据
        number:输入字符串转为i有效的数字,对后端向数据库保存数据比较友好操作
        trim:输入首位空格过滤

     -->
    <div class="root">
      <h3>收集表单数据</h3>
      <form>
        <!-- 正常情况下,如果多个input不会相互影响到,直接使用v-model就行 -->
        账号:<input type="text" v-model.trim="student.username" /><br /><br />
        密码:<input type="password" v-model="student.password" /><br /><br />
        <!-- 在年龄input中,输入框是属于数字内容,为了防止用户输入其他错误信息,可以在v-model后面加上修饰符
            number表示内容只有是属于数字的才能被vue接收 -->
        年龄:<input type="number" v-model.number="student.age" /><br /><br />
        性别:
        <!-- 性别input中,radio单选框中,
                1、为了防止点击其中一个radio后影响到另外一个radio,
                可以在两者身上设置name属性来限制同时处于被点击状态。
                2、v-model="student.sex" value='male'
                当获取客户端的value和我们设置的value是一样的话,就会使管理的input处于点击状态-->
        <input type="radio" name="sex" v-model="student.sex" value="male" />男
        <input
          type="radio"
          name="sex"
          v-model="student.sex"
          value="female"
        />女<br /><br />
        爱好:
        <!-- 多选框和单选框的设置有些不同
            除了设置v-model获取客户端输入内容,设置value的值,v-model初始值的数据对象需要是数组类型,
            如果v-model初始值接收数据的对象不是数组类型,因为checkbox点击后,是返回布尔值值true,
            因为双向绑定数据导致所有的input都处于点击状态,所以需要使用数组来接收各个被点击对象的数据 -->
        <span
          ><input
            type="checkbox"
            v-model="student.hobby"
            value="smoke"
          />吸烟</span
        >
        <span
          ><input
            type="checkbox"
            v-model="student.hobby"
            value="drink"
          />喝酒</span
        >
        <span
          ><input
            type="checkbox"
            v-model="student.hobby"
            value="study"
          />学习</span
        >
        <br /><br />
        所属校区:
        <!-- select下拉框
            v-model中如果设置指定的值,作用和在指定的option标签身上设置selected的作用是一样的
            还有上面的,如果v-model初始值是数组形式,student.hobby如果指定某个值,
            例如student.hobby = ['smoke']可以使吸烟单选框处于点击状态 -->
        <select v-model="student.city">
          <option value="choose">请选择校区</option>
          <option value="beijing">广州</option>
          <option value="shanghai">深圳</option>
          <option value="shenzhen">佛山</option>
          <option value="wuhan">揭阳</option>
        </select>
        <br />
        <br />
        <!-- <textarea name="" id="" cols="30" rows="10"></textarea> -->
        <!-- v-model后面可以加上修饰符,lazy懒加载,加上去可以时效果更好些 -->
        其他信息:<textarea
          style="resize: none; vertical-align: top"
          cols="30"
          rows="10"
          placeholder="请输入内容"
          v-model.lazy="student.content"
        ></textarea
        ><br /><br />
        <input
          type="checkbox"
          v-model="student.agree"
          style="vertical-align: middle"
        />阅读并接收<a href.stop="http://baidu.com">《用户协议》</a><br /><br />
        <button @click.prevent="submit">提交</button>
      </form>
    </div>
    <script type="text/javascript">
      const vm = new Vue({
        el: ".root",
        data: {
          student: {
            username: "",
            password: "",
            age: "",
            sex: "",
            hobby: [],
            city: "choose",
            content: "",
            agree: "",
          },
        },
        methods: {
          submit() {
            console.log(JSON.stringify(this.student));
          },
        },
      });
    </script>
  </body>
</html>
25、过滤器
过滤器:
定义:对要显示的数据进行特定格式化后再显示(适用于一些简单逻辑的处理)
语法:
1、注册过滤器:Vue.filter(name,callback)或者是new Vue(filter:{}),
   注意,使用Vue.filter(name,callback)注册的过滤器是全局的过滤器
   使用new Vue(filter:{})注册的过滤器是局部的过滤器
2、使用过滤器:{{xxx | 过滤器名}} 或者是 v-bind:属性 = 'xxx | 过滤器名'

备注:
1、过滤器也可以接收额外参数、多个过滤器可以串联使用 xxx | 过滤器1 | 过滤器2 | ...
2、并没有改变原本的数据,是产生新的对应的数据


在 Vue.js 中,filter(过滤器)是一种用于格式化或转换数据的配置项。
它可以在模板中通过管道符 | 的方式应用于插值表达式或绑定指令上。

使用过滤器可以实现一些简单的数据处理操作,例如格式化日期、转换大小写、金额格式化等。
它们提供了一种在模板中对数据进行处理和格式化的便捷方式。

要使用过滤器,首先需要在 Vue 组件的 filters 配置项中定义过滤器函数。
过滤器函数可以接受一个或多个参数,并返回经过处理后的结果。过滤器函数应该被定义为 Vue 实例的方法。
<!DOCTYPE html>
<html lang="en">
  <head>
    。。。
    <script type="text/javascript" src="../js/vue.js"></script>
    <script src="../js/dayjs.min.js"></script>
  </head>

  <body>
    <div class="root">
      <h2>显示格式化后的时间</h2>
      <!-- 计算属性实现 -->
      <h3>现在是:{{fmttime}}</h3>
      <!-- methods实现 -->
      <h3>现在是:{{getFmttime()}}</h3>
      <!-- 过滤器实现 -->
      <h3>现在是:{{time | timeFormater}}</h3>
      <!-- 过滤器实现(传参) -->
      <h3>现在是:{{time | timeFormater('YYYY-MM-DD') | mySlice}}</h3>
      <h3 :x="msg | mySlice">{{info|mySlice1(6)}}</h3>
    </div>
    <script type="text/javascript">
      // 定义一个全局的过滤器
      Vue.filter("mySlice", function (value) {
        return value.slice(0, 4);
      });

      const vm = new Vue({
        el: ".root",
        data: {
          time: Date.now(),
          msg: dayjs(this.time).format("YYYY-MM-DD HH:mm:ss"),
          info: "你好,我是张三,我在广州",
        },
        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");
          },
        },
        filters: {
          // 每个过滤器中第一个参数都是传递过来的数据
          timeFormater(value, str = "YYYY-MM-DD HH:mm:ss") {
            return dayjs(this.time).format(str);
          },
          mySlice(value) {
            // 这里是value是过滤器获取上一个过滤器或者是vm中的其他属性的数据
            // 现在这里的value就是上一个过滤器timeFormater的返回值
            return value.slice(0, 4);
          },
          mySlice1(value, length) {
            return value.slice(0, length);
          },
        },
      });
    </script>
  </body>
</html>
26、vue的内置指令
v-bind单项绑定解析表达式,可以简写成 :xxx
v-model双向绑定数据
v-for遍历数组、对象、字符串、次数都行
v-on绑定事件监听,建议简写成@
v-if条件渲染(动态控制节点是否存在)
v-else条件渲染(动态控制节点时候存在)
v-show条件渲染(动态控制节点是否展示)

v-text指令:
1、作用:向其所在的节点中渲染文本内容
2、与插值语法的区别:v-text会替换掉节点中的所有内容,{{xxx}}则不会

v-cloak指令(没有值):
1、本质是一个特殊属性,Vue实例创建完毕并接管容器后,会删除掉v-cloak属性
2、使用css和v-cloak属性可以解决网速慢时页面展示出{{xxx}}的问题

先编写一个延迟服务器
1、下载依赖 npm install express -D
2、编写express.js文件,内容如下:
const express = require("express");
const app = express();
const path = require("path");

app.get("/resource", function (req, res) {
  setTimeout(() => {
    res.sendFile(path.join(__dirname, "./vue.js"));
  }, 5000);
});

app.listen(8080, () => {
  console.log("http://127.0.0.1:8080");
});
3、启动服务器 node express.js

4、html结构中使用
<!DOCTYPE html>
<html lang="en">
  <head>
    ...
    <!-- 在这里,如果出现获取js文件延迟的情况,叫做js阻塞 -->
    <script
      type="text/javascript"
      src="http://127.0.0.1:8080/resource"
    ></script>
  </head>
  <style>
    [v-cloak] {
      display: none;
    }
  </style>

  <body>
    <div class="root">
      <h3 v-cloak>{{name}}</h3>
    </div>
    <script
      type="text/javascript"
      src="http://127.0.0.1:8080/resource"
    ></script>

    <script type="text/javascript">
      const vm = new Vue({
        el: ".root",
        data: {
          name: "张三",
        },
      });
    </script>
  </body>
</html>

v-html指令:
1、作用:向指定的节点中渲染包含html结构的内容
2、与插值语法的区别:
   1)、v-html会替换掉节点中的所有的内容,{{xxx}}则不会
   2)、v-html可以识别html结构
3、严重注意:v-html有安全性问题!
   1)、再网站上动态渲染任意html是非常危险的,容易导致XSS攻击
   2)、一定要在可信的内容上使用v-html,永远不要用在用户提交的内容上

v-once指令:
1、v-once所在节点在初次动态渲染后,就是为静态内容了
2、以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能

v-pre指令:
1、跳过其所在节点的编译过程
2、可以利用它跳过:前提是没有使用指令语法和没有使用插值语法的节点,会加快编译
27、自定义指令
<!DOCTYPE html>
<html lang="en">
  <head>
    。。。
    <script type="text/javascript" src="../js/vue.js"></script>
  </head>

  <body>
    <!-- 在directives中定义的函数的this都是指向window对象 -->
    <div class="root">
      <h3>
        自定义指令中的this指向<br />
        directives中this的指向是window,因为指令绑定在标签上,标签的this又是window,所以指向window
      </h3>
      <div><span v-big="n"></span></div>
      <button @click="n++">点击n+1</button>
      <div><input v-fbind:value="n" /></div>
      <button @click="a++">点击n+1</button>
      <!-- 多单词的自定义指令 -->
      <div><span v-f-bind:value="a"></span></div>
    </div>
    <script type="text/javascript">
      const vm = new Vue({
        el: ".root",
        data: {
          n: 1,
          a: 1,
        },
        directives: {
          // 自定义指令中的this,正常情况都是指向window的,所以使用箭头函数也是
          // element, binding分别是真实dom对象,用于传递相关的信息对象
          big(element, binding) {
            element.innerHTML = binding.value;
            console.log(this);
          },
          fbind: {
            // 指令和元素绑定成功时
            bind(element, binding) {
              element.value = binding.value;
              console.log(this);
            },
            // 指令所在元素被插入页面中时
            inserted(element, binding) {
              element.focus();
              console.log(this);
            },
            // 指令所在元素内容被修改时
            update(element, binding) {
              element.value = binding.value;
              console.log(this);
            },
          },
          // 多单词的自定义指令书写形式
          "f-bind": (element, binding) => {
            element.innerHTML = binding.value * 10;
          },
        },
      });

      // 定义全局指令
      // Vue.directive("big", (element, binding) => {
      //   element.innerHTML = binding.value;
      //   console.log(this);
      // });
    </script>
  </body>
</html>
28、vue的生命周期
生命周期:
1、又名生命周期回调函数、生命周期函数、生命周期钩子
2、是什么:vue在关键时刻榜我们调用的一些特殊名称的函数
3、生命周期函数的名字不可更改,但是函数的具体内容是程序员根据需求编写的
4、生命周期函数中的this指向是vm或者是组件实例对象

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

  <body>
    <div class="root">
      <h3 :style="{opacity}">vue生命周期</h3>
    </div>
    <script type="text/javascript">
      Vue.config.productionTip = false;
      vm = new Vue({
        el: ".root",
        data: {
          opacity: 1,
        },
        // vue完成模板的解析并把初始的真实dom元素放入页面后(挂载完毕)调用mounted
        // (也就是mounted在整个过程中制备调用一次)
        // 这里的mounted函数名是vue给我们命名好的,如果写成其他的单词,不会报错但是也不会执行这里
        mounted() {
          console.log("mounted");
          setInterval(() => {
            this.opacity -= 0.01;
            if (this.opacity < 0) this.opacity = 1;
          }, 10);
        },
      });
    </script>
  </body>
</html>
29、vue的生命周期的分析
首先,创建new Vue({})
1)、初始化:生命周期、事件、单数数据代理还没有开始。这个过程中调用beforeCreate()函数,次数无法通过vm对象访问到data中的数据和methods中的函数,因为都还没有数据代理。
2)、初始化:数据监测和数据代理。这个过程中调用created()函数,此时可以通过vm访问到data中的数据和methods中配置的函数,这个时候已经进行数据代理和数据检测了。
3)、进行判断。判断是否配置对象,el = '.root'表示配置root对象
4)、判断成功后,再进行判断时候包含template属性,如果没有九江上面el配置的root对象都放置在template中
注意:在3和4的阶段中,Vue开始解析模板,生成虚拟DOM(放在内存中),页面还不可以显示解析好的内容
5)、此时调用beforeMount(),页面显示的是未经过Vue编译的DOM结构,其实到这一步得时候,vue已经把模板解析完成了,就是没来得及放上去,所有对DOM的操作,最终都不奏效
6)、将内存中的虚拟DOM转未真实DOM插入页面中
7)、此时调用mounted()函数,页面中呈现的是经过vue编译的DOM,对DOM的操作是有效的了,但是最好不要操作DOM。至此初始化过程结束,一般在此进行开启定时器、发送网络请求、订阅消息、绑定自定义事件等初始化操作。
            
当页面数据发生变化时:
8)、beforeUpdate()函数调用,此时数据是最新得,但是页面是旧的。即页面尚未和数据保持同步
9)、根据新数据,生成新的虚拟DOM,随后与旧的虚拟DOM进行比较,最终完成页面更新,即完成了model到view的更新
10)、调用updated()函数,此时数据是最新的,页面也是最新的,即页面和数据保持同步
11)、调用beforeDestroy()此时vm中的所有的数据:data、methods、指令等等,都处于可用状态(但是使用其中的数据之后不会被重新更新),马上要执行销毁过程。一般在此阶段:关闭定时器、取消订阅消息、解绑自定义事件等收尾操作取消数据监视watch  子组件  和  自定义事件监听(系统定义的监听事件是不会被取消的,会一直存在)
12)、调用destroyed()函数,做到最后销毁

vm.$destroyed()用法:完全销毁一个实例,清理与其他的连接(比如将来的vm的子组件,也可以看成是微型的vm实例对象),解绑它的全部指令(不管是系统指令还是自定义指令),和自定义事件监听器(系统监听器解绑不了)

触发beforeDestroy()和destroy()的钩子,在大多数场景中不应该调用这个方法,最好使用v-if和v-for指令以外指令以数据驱动的方式控制组件的生命周期

代码演示
<!DOCTYPE html>
<html lang="en">
  <head>
    。。。
    <script type="text/javascript" src="../../js/vue.js"></script>
  </head>

  <body>
    <div class="root">
      <h3>当前的n的值是:{{n}}</h3>
      <button @click="add">点击n+1</button>
      <button @click="bye">点击销毁</button>
      <input type="text" value="haha" />
    </div>
    <script type="text/javascript">
      new Vue({
        el: ".root",
        // 使用template是在vue组件中常用
        // template: `
        //     <div>
        //         <h3>当前的n的值是:{{n}}</h3>
        //         <button @click='add'>点击n+1</button>
        //         <input type="text" :value='n'>
        //     </div>`,
        data: {
          n: 1,
        },
        methods: {
          add() {
            this.n++;
          },
          bye() {
            // 想要销毁数据,必须调用下面这句代码
            console.log("bye");
            this.$destroy();
          },
        },
        // 在beforeCreated之前,初始化:生命周期、事件,但是数据代理未开始
        // 在beforeCreated的时候,无法通过vm访问到data中的数据、method的方法
        beforeCreate() {
          console.log("beforeCreate");
          // console.log(this);//挂载的this指向是vue,指令的this指向是window
          // debugger;//断点,可以用于调试
        },

        // 在created之前,初始化:数据检测、数据代理
        // 在created,此时可以通过vm访问到data中的数据、methods中配置的方法
        created() {
          console.log("created");
          // console.log(this);//挂载的this指向是vue
          // debugger;
        },

        /* 
            created函数和beforeMount函数中间:
            此阶段Vue开始解析模板,生成虚拟dom(内存中),页面还不能显示解析好的内容
        */

        // 在beforeMount:
        // 页面呈现的是未经过Vue编译的dom结构
        // 所有对dom的操作,最终都不奏效
        // 将内存中的虚拟dom转为真实dom插入页面中
        beforeMount() {
          console.log("beforemount");
          // console.log(this);
          // document.querySelector('input').focus();
          debugger;
        },

        // 在beforeMount()和mounted()函数之间内存把虚拟DOM变为真实DOM,
        // 并且保存一份在$el()对象中

        // mounted:
        // 页面中呈现的是经过Vue编译的dom
        // 对dom的操作均有效
        // 至此初始化过程结束,一般在此进行:开启定时器、发送网络请求、订阅消息、绑定自定义事件、等初始化操作
        mounted() {
          console.log("mounted");
          // console.log(this);
          // debugger;
        },

        // 生命周期的更新流程
        // beforeUpdate:
        // 数据是新的,但是页面是旧的数据,就是页面尚未和数据保持同步
        // 数据更新时,数据和页面中还没有保持同步,这时数据改变了,但是页面还没有改变
        beforeUpdate() {
          console.log("beforeUpdate");
          // console.log(this.n)
          // console.log(this);
          // debugger;
        },

        /* 
        根据新数据,生成新的虚拟dom,随后和旧的虚拟dom进行比较,最终完成页面更新,就是完成了model--view的更新
        */

        // updated:
        // 数据是新的,页面也是新的,就是页面和数据保持同步
        // 数据更新后,页面和数据保持同步,都是改变的了
        updated() {
          console.log("Updated");
          // console.log(this.n)
          // console.log(this);
          // debugger;
        },

        // beforeDestroy:
        // vm中所有的:data、methods、指令等等,都处于可用状态,马上要执行销毁过程,一般在此阶段中:
        // 关闭定时器、取消订阅消息、解绑自定义事件等收尾操作
        // 生命周期中销毁流程
        beforeDestroy() {
          console.log("beforeDestroy");
          // console.log(this.n);//在这里的n虽然被调用,但是没有被更新
          // debugger;
        },

        // 这里销毁
        destroy() {
          console.log("destroy");
        },
      });
    </script>
  </body>
</html>
简单说明钩子的使用

vm的生命周期:
1、将要创建调用beforeCreate()函数
2、创建完毕调用created()函数
3、将要挂载调用beforeMount()函数
4、重点:挂载完毕调用mount()函数,这个用的比较多
5、将要更新调用beforeUpdate()函数
6、更新完毕调用update()函数
7、重点:将要销毁调用beforeDestroy()函数
8、销毁完毕调用destroyed()函数

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

关于销毁vue实例:
1、销毁后借助vue开发者工具看不到任何消息
2、销毁后自定义事件会失效,但是原生DOM事件依然有效
3、一般不会再beforeDestroy()操作数据,因为即便操作数据,也不会再触发更新流程了。

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

  <body>
    <div class="root">
      <h3 :style="{opacity}">vue生命周期</h3>
      <button @click="stop">点击停止变化</button>
    </div>
    <script type="text/javascript">
      Vue.config.productionTip = false;
      vm = new Vue({
        el: ".root",
        data: {
          opacity: 1,
        },
        methods: {
          stop() {
            console.log("停止");
            this.$destroy();
          },
          setTime() {
            clearInterval(this.timer);
            this.timer = null;
            this.timer = setInterval(() => {
              this.opacity -= 0.01;
              if (this.opacity < 0) this.opacity = 1;
            }, 10);
          },
        },
        mounted() {
          this.setTime();
        },
        beforeDestroy() {
          clearInterval(this.timer);
        },
        destroy() {
          console.log("destroy");
        },
      });
    </script>
  </body>
</html>
30、非单文件的组件化编程
<!DOCTYPE html>
<html lang="en">
  <head>
    。。。
    <script type="text/javascript" src="../js/vue.js"></script>
  </head>

  <body>
    <div class="root">
      <h3 v-pre>简单组件化编程</h3>
      <h3>{{name}}</h3>
      <person></person>
    </div>
    <script type="text/javascript">
      // 定义子组件
      const person = Vue.extend({
        name: "person",
        data() {
          return {
            name: "张三",
            address: "广州",
          };
        },
        // 模板
        template: `
              <div>
                <h3>你好,我是{{name}},我在{{address}}</h3>
              </div>
            `
      });
      // 注册全局组件
      // Vue.component("person", person);
      const vm = new Vue({
        el: ".root",
        data: {
          name: "李四",
        },
        // 注册局部组件,对象形式
        components: {
          person,
        },
      });
    </script>
  </body>
</html>
1、一个重要的内置关系:VueComponent.prototype.__proto__ === Vue.prototype
2、为什么要有这个关系?让组件实例对象(vc)可以访问到Vue实例对象上的属性和方法
vue组件化编程:
        模块和组件、模块化和组件化
        1、模块:
        理解:向外提供特定功能的js程序,一般就是一个js文件
        为什么:js文件很多很复杂
        作用:复用js,简化js的编程,提高js运行效率
        注意:但是传统的js编程存在问题,依赖关系混乱,不好维护。
        代码复用率不高

        2、组件:
        理解:用来实现局部特定的功能效果的代码集合(html css js 等等文件类型)
        为什么:一个界面的功能是很复杂的
        作用:复用编码,简化项目代码,提高运行效率
        定义:实现应用中局部功能代码和资源的集合

        3、模块化:(就是把整个js文件分成几个小的js文件编写)
        当应用中的js都以模块来编写,那这个应用就是一个模块化的应用

        4、组件化:(就是把页面分成很多部分编写,每部分基本都存在html css js等内容)
        当应用的功能都是多个组件的方式编写的,那这个应用就是一个组件化的应用

        非单文件组件:一个文件中包含有n个文件(n不能是1)
        单文件组件:一个文件中只包含有1个文件
几个注意点:
       1、关于组件名:
       一个单词组成时:
            第一种写法(首字母小写):school
            第二种写法(首字母大写):School

        多个单词组成:
            第一种写法(kebab-case命名):my-school
            第二种写法(CamelCase命名):MySchool(需要在Vue脚手架支持下才能使用)

        备注:
            1、组件名尽可能回避html中已经存在的元素的名称,例如:h2  span
            2、可以使用name配置项指定组件在开发者工作中呈现的名称

        2、关于组件标签的使用:
            第一种写法:<school></school>
            第二种写法:<school/>
            备注:不用使用脚手架时,<school/>会导致后续组件不能被渲染
            
        3、一个简写方式:
        const school = Vue.extend(options)可以简写成const school = options
vue中使用组件的三大步骤:
        一、定义组件,创建组件
        二、注册组件
        三、使用组件,写组件标签

        一、如何定义一个组件?
        使用Vue.extend({options})创建,其中options和new Vue(options)时传入的哪个options时一样的,
        但是也有区别:
        1、el不要写?最终所有的组件都要经过一个vm的管理,由vm中的el决定服务哪个容器
        2、data必须协会曾函数?避免组件被复用时,数据存在引用关系

        二、如何注册组件?
        1、局部组件:使用new Vue时候传入的components选项
        2、全局组件:使用Vue.component('组件名称',组件)
        组件名称是注册时命名的组件名称,组件是创建完毕组件之后的组件中转对象

        三、编写组件标签:
        <school></school>
关于VueComponent:
1、school组件本质是一个名为VueComponent的构造函数,且不是程序员定义的,是Vue.extend生成的
2、我们只需要写<school></school>或者是<school/>,Vue解析时会创建school组件的实例对象,
   即Vue帮助我们执行的:new VueComponent(options)
3、特别注意:每次调用Vue.extend(),返回的都是一个全新的VueComponent
4、关于this指向:
1)、组件配置中:
data函数、methods中的函数、watch中的函数、computed中的函数,它们的this都是指向VueComponent实例对象,比如school
2)、new Vue()配置中:data函数、methods中的函数、watch中的函数、computed中的函数,它们的this都是指向Vue实例对象
5、VueComponent的实例对象,以后简称vc(也可以称为:组件实例对象),但是在工作中不叫vc,叫做组件实例对象,Vue的实例对象,以后简称是vm
31、单文件组件
使用vue脚手架
1、初始化脚手架
说明
1)、vue脚手架是vue官方提供的标准化开发工具(开发平台)

具体实现步骤:
第一步:全局安装@vue/cli
npm install @vue/cli -g

第二步:切换到你要创建项目的目录,然后使用命令创建项目
vue create 项目名称

第三步:启动项目
cd 项目名称(这一步是为路径跳到项目下)
npm run serve

备注:
如果出现下载缓慢请配置npm淘宝镜像:
npm config set registry https://registry.npm.taobao.org

如果需要脚手架帮忙配置文件的话,可以执行npm create vue@latest然后具体要求根据项目来旋转

后续前往CSDN

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值