2021.11.28 vue 实例的数据与方法(8)

Vue实例的数据与方法

当一个 Vue 实例被创建时,它将data 对象中的所有的属性加入到Vue 的响应式系统中。当这些属性的值发生改变时,视图将会产生“响应”,即匹配更新为新的值。对于值本身的操作咱们之前已经学过了, 现在我们在来学习一下实例属性和方法.

Vue 实例的实例属性与方法。它们都有前缀$,以便与用户定义的属性区分开来

<body>
  <div id='app'>
    {{a}}
    <button @click='fn'>按钮</button>
  </div>

  
  <script src='./js/vue.js'></script>
  <script>
    const data = { a: 1 }
    const app = new Vue({
      el: '#app',
      data: data,
      methods: {
        fn() {
          this.a += 1
        }
      }
    })
    console.log(app.$data === data);
    console.log(app.$el === document.getElementById('app'));
    // $watch是一个实例方法
    app.$watch('a', (new_value, old_value) => {
      console.log(new_value, old_value);
    })
  </script>
</body>

Vue的实例属性之data

属性: app.$data

  1. 对象必须是纯粹的对象 (含有零个或多个的 key/value 对)
  2. 一旦创建,vue不允许再次在数据对象上添加响应式属性。因此推荐在创建实例之前,就声明所有的根级响应式属性。
  3. 实例创建之后,可以通过vm. d a t a 访 问 原 始 数 据 对 象 。 V u e 实 例 也 代 理 了 d a t a 对 象 上 所 有 的 属 性 , 因 此 访 问 v m . a 等 价 于 访 问 v m . data访问原始数据对象。Vue 实例也代理了 data 对象上所有的属性,因此访问 vm.a 等价于访问 vm. data访Vuedata访vm.a访vm.data.a。
  4. 以 _ 或$ 开 头 的 属 性 不 会 被 V u e 实 例 代 理 , 因 为 它 们 可 能 和 V u e 内 置 的 属 性 、 A P I 方 法 冲 突 。 你 可 以 使 用 例 如 v m . 开头的属性 不会 被 Vue 实例代理,因为它们可能和 Vue 内置的属性、API 方法冲突。你可以使用例如 vm. VueVueAPI使vm.data._property($property) 的方式访问这些属性。
  5. 当一个组件被定义,data 必须声明为返回一个初始数据对象的函数,因为组件可能被用来创建多个实例。如果 data 仍然是一个纯粹的对象,则所有的实例将共享引用同一个数据对象!
<body>
  <div id='app'>
    {{num}}
    <input type="text">
    <button @click='fn'>btn</button>
  </div>

  <script src='./js/vue.js'></script>
  <script>
    const app = new Vue({
      el: '#app',
      // 1.对象必须是纯粹的对象
      data: {
        num: 2,
        _num1: 3,
        num2: 4,
        $data: 6,

      },
      methods: {
        // 2.不允许添加响应式属性
        fn() {
          this.a = 3
        }
      }
    })
    // 3.app.num和app.$data.num
    console.log(app.num === app.$data.num);

    // 4. data中使用_或$不会被实例代理
    console.log(app._num1);
    // 4.1可以使用app.$data.$data访问
    console.log(app.$data.$data);
  </script>
</body>

Vue的实例属性之props

属性: vm.$props;

props type可以是数组或对象,用于接收来自父组件的数据。props
可以是简单的数组,或者使用对象作为替代,对象允许配置高级选项,如类型检测、自定义验证和设置默认值。

props对象的语法可以使用以下选项:

  1. type: 可以是下列原生构造函数中的一种:String、Number、Boolean、Array、Object、Date、Function、Symbol、任何自定义构造函数、或上述内容组成的数组。会检查一个 prop 是否是给定的类型,否则抛出警告。
  2. default: any; 为该 prop 指定一个默认值。如果该 prop 没有被传入,则换做用这个值。对象或数组的默认值必须从一个工厂函数返回。
  3. required: Boolean; 定义该 prop 是否是必填项。在非生产环境中,如果这个值为 true 且该 prop 没有被传入的,则一个控制台警告将会被抛出。
  4. validator: Function; 自定义验证函数会将该 prop 的值作为唯一的参数代入。在非生产环境下,如果该函数返回一个 false 的值 (也就是验证失败),一个控制台警告将会被抛出。
<body>
  <div id='app'>
    <cpn :info='name'></cpn>
  </div>

  <script src='./js/vue.js'></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        name: 123,
      },
      components: {
        cpn: {
          template: '<div><h1>{{info}}</h1></div>',
          // 数组语法
          // props: ['info'],
          // 对象语法
          props: {
            info: {
              // 类型检测
              type: Number,
              // 默认值
              default: '你没有数据给我,我是默认值',
              // 该prop是否必填
              required: false,
              // 自定义验证函数
              validator: function (value) {
                return value > 0
              }
            }
          }
        }
      }
    })
  </script>
</body>

Vue的实例属性之el

属性: vm.$el

提供一个在页面上已存在的 DOM 元素作为 Vue 实例的挂载目标。可以是 CSS 选择器,也可以是一个 HTMLElement 实例。

<body>
  <div id='app'>

  </div>

  <div class="app1"></div>

  <script src='./js/vue.js'></script>
  <script>
    const div = document.createElement('div')
    div.innerHTML = '你好'
    document.getElementById('app').append(div)
    const app = new Vue({
      // el: '#app',
      el: div,
      data: {
        msg: '哈哈哈'
      }
    })
  </script>
</body>

在实例挂载之后,元素可以用app.$el 访问。

console.log(app.$el);

如果在实例化时存在这个选项,实例将立即进入编译过程,否则,需要显式调用vm.$mount() 手动开启编译。

app.$mount('#app')
console.log(app.$el);

Vue的实例属性之options

属性: vm.$options

用于当前 Vue 实例的初始化选项。需要在选项中包含自定义属性时会有用处:

<body>
  <div id='app'>

  </div>

  <script src='./js/vue.js'></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        msg: '老王大帅逼'
      },
      // 当我们有自定义属性时可以用$options访问
      wyf: '凡凡',
    })

    console.log(app.$options.wyf);
  </script>
</body>

Vue的实例属性之组件逻辑关系

属性: vm.$parent; 数据类型: Vue instance;

父实例,如果当前实例有的话。

属性: vm.$root; 数据类型: Vue instance;

当前组件树的根Vue 实例。如果当前实例没有父实例,此实例将会是其自己。

属性: vm.$children; 数据类型:Arry

当前实例的直接子组件。

<body>
  <div id='app'>
    {{info}}
    <cpn></cpn>
  </div>

  <script src='./js/vue.js'></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        info: '我是父组件app'
      },
      components: {
        cpn: {
          data() {
            return {
              info: '我是子组件'
            }
          },
          template: '<div>{{info}}cpn <cpn1></cpn1><button @click="fn">btn_cpn</button></div>',
          methods: {
            fn() {
              // 子组件
              console.log(this.$children);
            }
          },
          components: {
            cpn1: {
              data() {
                return {
                  info: '我是孙子组件'
                }
              },
              template: '<div>{{info}}cpn1<button @click="fn">btn_cpn1</button></div>',
              methods: {
                fn() {
                  console.log('父组件', this.$parent);
                  console.log('根组件', this.$root);
                }
              }
            }
          }
        }
      }
    })
  </script>
</body>

Vue的实例方法之watch

vm.$watch( expOrFn, callback, [options] )

观察 Vue 实例变化的一个表达式或计算属性函数。回调函数得到的参数为新值和旧值。表达式只接受监视的键路径(即访问某个属性的方法)。对于更复杂的表达式,用一个函数取代。

<body>
  <div id='app'>
    {{num_obj.num}}
    <button @click='fn'>btn</button>
  </div>

  <script src='./js/vue.js'></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        num_obj: {
          num: 1
        }
      },
      methods: {
        fn() {
          this.num_obj.num += 1
        }
      }
    })
    console.log(app.$data.num_obj.num);
    // 键路径 (num_obj.num)
    app.$watch('num_obj.num', (new_value, old_value) => {
      console.log(old_value, new_value);
    })

    // 函数
    // app.$watch(function () { return this.num_obj.num }, (new_value, old_value) => {
    //   console.log(old_value, new_value);
    // })
  </script>
</body>

注意:在变异 (不是替换) 对象或数组时,旧值将与新值相同,因为它们的引用指向同一个对象/数组。Vue 不会保留变异之前值的副本。

app.$watch('num_obj.list', (new_value, old_value) => {
  console.log('watch:', old_value, new_value);
})

vm.$watch 返回一个取消观察函数,用来停止触发回调:

const unwatch = app.$watch('num_obj.num', (new_value, old_value) => {
  console.log(old_value, new_value);
  if (new_value >= 5) {
    unwatch()
  }
})

Vue的实例方法之watch的选项

选项:deep

为了发现对象内部值的变化,可以在选项参数中指定deep: true 。注意监听数组的变动不需要这么做。

<body>
  <div id='app'>
    {{info.name}}
    <button @click='fn'>btn</button>
  </div>

  <script src='./js/vue.js'></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        info: {
          name: 'kobe',
          num: 8
        }
      },
      methods: {
        fn() {
          this.info.num = 24
        }
      }
    })
    app.$watch('info', (new_value, old_value) => {
      console.log('数据被修改了');
    }, { deep: true })
  </script>
</body>
选项:immediate

在选项参数中指定immediate: true 将立即以表达式的当前值触发回调:简单来说, 在Vue实例加载的一瞬间就执行一次回调函数

app.$watch('info', (new_value, old_value) => {
  console.log('数据被修改了');
}, { deep: true, immediate: true })

注意在带有 immediate选项时,你不能在第一次回调时取消侦听

const unwatch = app.$watch('info', (new_value, old_value) => {
  console.log('数据被修改了');
  unwatch()
}, { deep: true, immediate: true })

Vue的实例方法之set/delete

vm.$set(target, propertyName/index, value )

向响应式对象中添加一个属性,并确保这个新属性同样是响应式的,且触发视图更新。它必须用于向响应式对象上添加新属性,因为Vue 无法探测普通的新增属性

fn() {
  // 数据有更改但是页面没有响应式
  // this.div.color = 'main'
  // 数据更新,并且响应式更新
  this.$set(this.div, 'color', 'main')
},

vm.$delete( target, propertyName/index )

删除对象的属性。如果对象是响应式的,确保删除能触发更新视图。这个方法主要用于避开Vue 不能检测到属性被删除的限制

del() {
  // 删除,视图没有更新
  // delete this.div.color
  // 删除,并且响应式更新
  this.$delete(this.div, 'color')
}

Vue的实例方法之on监听自定义事件

vm.$on( eventName, callback )

监听当前实例上的自定义事件。事件可以由vm.$ e m i t 触 发 ( 在 示 例 内 部 方 法 中 可 以 用 t h i s . emit触发(在示例内部方法中可以用this. emit(this.emit)。回调函数会接收所有传入事件触发函数的额外参数。

<script>
  const app = new Vue({
    el: '#app',
    data: {
      info: {

      }
    }
  })
  app.$on('player', (name) => {
    console.log(name);
  })
  app.$watch('info', function (new_value, old_value) {
    // 页面刷新就会执行一次
    this.$emit('player', '老王')
  }, { immediate: true, deep: true })
</script>

Vue的实例方法之once监听自定义事件

vm.$once( eventName, callback )

监听一个自定义事件,但是只触发一次,在第一次触发之后移除监听器。

app.$once('player', (name) => {
  console.log(name);
})

Vue的实例方法之off移除监听事件

vm.$off( [eventName, [callback]] )移除自定义事件监听器。

// 没有参数,移出所有监听
app.$off()
// 移除指定事件监听
app.$off('player')

生命周期的基本概念

我们一起回顾一下上节课讲到的,过渡的几个钩子函数:

<body>
  <div id='app'>
    <button @click='show=!show'>btn</button>
    <transition :css=false @before-enter='fn1' @enter='fn2' @after-enter='fn3'>
      <h1 v-if='show'>嘿嘿嘿</h1>
    </transition>
  </div>

  <script src='./js/vue.js'></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        show: false
      },
      methods: {
        fn1(el) {
          el.style.color = 'red'
        },
        fn2(el, done) {
          const id = setInterval(() => {
            if (el.style.color === 'red') {
              el.style.color = 'green'
            } else {
              el.style.color = 'red'
            }
          }, 1000);
          setTimeout(() => {
            clearInterval(id)
            done()
          }, 3000);
        },
        fn3() {
          alert(666)
        }
      }
    })
  </script>
</body>

以上的3个过渡的钩子函数,就是在我们的动画这个周期内,在每个时间段,我们都可以去设置不同的代码去完成相对应的事,比如在动画开始之前我们需要什么操作,在动画执行过程中我们需要什么操作,动画执行完后我们需要什么操作,都可以写在函数里面去完成

vue的生命周期也是同样的道理,每个 Vue 实例在被创建时都要经过一系列的初始化过程

例如,需要设置数据监听、编译模板、将实例挂载到DOM 并在数据变化时更新DOM 等。同时在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会。

比如created钩子可以用来在一个实例被创建之后执行的代码:

<script>
  const app = new Vue({
    el: '#app',
    data: {
      msg: '哈哈哈'
    },
    created: function () {
      console.log(this.msg);
    }
  })
</script>

生命周期的基本概念

请添加图片描述

;
请添加图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值