美文网首页
Vue 基础

Vue 基础

作者: YM雨蒙 | 来源:发表于2018-06-21 13:55 被阅读11次

Vue 实例

1. Vue实例

const app = new Vue({
  el: '#app',
  template: '<div ref="div">{{ num }}</div>'
  data: {
    num: 0
  },
  props: {

  },
  watch: {
    num (newNum, oldNum) {
      console.log(`${newNum} : ${oldNum}`)    // 1 : 0  自动注销
    }
  }
})

const app = new Vue({
})
app.$mount('#app')

setTimeout(function(){
  app.num += 1
}, 1000)

2. 实例属性

// Vue 实例观察的数据对象。Vue 实例代理了对其 data 对象属性的访问。
console.log(app.$data)    // num : 0

// 当前组件接收到的 props 对象。Vue 实例代理了对其 props 对象属性的访问。
console.log(app.$props)    // undefined

// Vue实例使用的根 DOM 元素
console.log(app.$el)    // <div>0</div>

// 用于当前 Vue 实例的初始化选项
console.log(app.$options)    // {components: {…}, directives: {…}, filters: {…}, _base: ƒ, el: "#app", …}

app.$options.render = (h) => {
  return h('div', {}, 'new render')    // 需重新渲染时才会生效
}

// 当前组件树的根 Vue 实例。如果当前实例没有父实例,此实例将会是其自己。
console.log(app.$root)
console.log(app.$root === app)    // true

// 当前实例的直接子组件。需要注意 $children 并不保证顺序,也不是响应式的。
console.log(app.$children)

// 用来访问被插槽分发的内容。每个具名插槽有其相应的属性 (例如:`slot="foo"` 中的内容将会在 `vm.$slots.foo` 中被找到)。default 属性包括了所有没有被包含在具名插槽中的节点。
console.log(app.$slots)
console.log(app.$scopedSlots)

// 一个对象,持有注册过 ref 特性的所有 DOM 元素和组件实例。
console.log(app.$refs)    // {div: div}

// 当前 Vue 实例是否运行于服务器。  一般服务端渲染才会用
console.log(app.$isServer)

3. 实例方法/数据

//  Vue 实例变化的一个表达式或计算属性函数。回调函数得到的参数为新值和旧值
const unwatch = app.$watch('num', (newNum, oldNum) => {
  console.log(`${newNum} : ${oldNum}`)    // 1 : 0
})
unwatch()    // 注销watch

// 键路径
vm.$watch('a.b.c', function (newVal, oldVal) {
  // 做点什么
})

// 函数
vm.$watch(
  function () {
    return this.a + this.b
  },
  function (newVal, oldVal) {
    // 做点什么
  }
)
全局 Vue.set 的别名
vm.$set( target, key, value )

全局 Vue.delete 的别名。
vm.$delete( target, key )

const app = new Vue({
  el: '#app',
  template: '<div ref="div">{{ num }} {{ obj.a }}</div>',
  data: {
    num: 0,
    obj: {}
  },
  watch: {
    num (newNum, oldNum) {
      console.log(`${newNum} : ${oldNum}`)
    }
  }
})

let i = 0
setTimeout(function(){
  i++
  app.$set('app.obj', 'a', i)

  app.$delete('app.obj', 'a')
  // app.obj.a = i
  // app.$forceUpdate()
}, 1000)

4. 实例方法/事件

// 监听当前实例上的自定义事件。事件可以由vm.$emit触发。回调函数会接收所有传入事件触发函数的额外参数。
app.$on('num', (a, b) => {
  console.log(`emit again ${a} ${b}`)
})
app.$emit('num', 1, 2)    // emit again 1 2

vm.$on('test', function (msg) {
  console.log(msg)
})
vm.$emit('test', 'hi')
// => "hi"
// 监听一个自定义事件,但是只触发一次,在第一次触发之后移除监听器
app.$once('num',() => {

})

5. 实例方法/生命周期

// 迫使 Vue 实例重新渲染。注意它仅仅影响实例本身和插入插槽内容的子组件,而不是所有子组件。
const app = new Vue({
  el: '#app',
  template: '<div ref="div">{{ num }} {{ obj.a }}</div>',
  data: {
    num: 0,
    obj: {}
  },
  watch: {
    num (newNum, oldNum) {
      console.log(`${newNum} : ${oldNum}`)
    }
  }
})

let i = 0
setTimeout(function(){
  i++
  app.obj.a = i
  app.$forceUpdate()  // 强制重新渲染
}, 1000)
将回调延迟到下次 DOM 更新循环之后执行。在修改数据之后立即使用它,然后等待 DOM 更新。
它跟全局方法 Vue.nextTick 一样,不同的是回调的 this 自动绑定到调用它的实例上。

new Vue({
  // ...
  methods: {
    // ...
    example: function () {
      // 修改数据
      this.message = 'changed'
      // DOM 还没有更新
      this.$nextTick(function () {
        // DOM 现在更新了
        // `this` 绑定到当前实例
        this.doSomethingElse()
      })
    }
  }
})

Vue生命周期方法

new Vue({
  el: '#app',
  template: '<div>{{ text }}</div>',
  data: {
    text: 0
  },
  beforeCreate () {
    console.log(this, 'beforeCreate')     // =>1  "beforeCreate"
  },
  created () {
    console.log(this, 'created')    // =>2   "created"
  },
  beforeMount () {
    console.log(this, 'beforeMount')    // =>3   "beforeMount"
  },
  mounted () {
    console.log(this, 'mounted')     // =>4 "mounted"
  },
  beforeUpdate () {
    console.log(this, 'beforeUpdate')
  },
  updated () {
    console.log(this, 'updated')
  },
  activated () {
    console.log(this, 'activated')
  },
  deactivated () {
    console.log(this, 'deactivated')
  },
  beforeDestroy () {
    console.log(this, 'beforeDestroy')
  },
  destroyed () {
    console.log(this, 'destroyed')
  }
})

Ajax 操作赋值 最早也要在 created中
new Vue({
  // el: '#app',
  template: '<div>{{ text }}</div>',
  data: {
    text: 0
  },
  beforeCreate () {
    console.log(this, 'beforeCreate')    // => "beforeCreate"
  },
  created () {
    console.log(this, 'created')    // => "created"
  },
  beforeMount () {
    console.log(this, 'beforeMount')
  },
  mounted () {
    console.log(this, 'mounted')
  },
  beforeUpdate () {
    console.log(this, 'beforeUpdate')
  },
  updated () {
    console.log(this, 'updated')
  },
  activated () {
    console.log(this, 'activated')
  },
  deactivated () {
    console.log(this, 'deactivated')
  },
  beforeDestroy () {
    console.log(this, 'beforeDestroy')
  },
  destroyed () {
    console.log(this, 'destroyed')
  }
})


app.$mount('#app')

beforeMount  mounted 是在实例挂载的时候才开始执行的, 跟挂在到页面上显示的内容有关系

该钩子在服务器端渲染期间不被调用。 无DOM执行环境
const app = new Vue({
  el: '#app',
  template: '<div>{{ text }}</div>',
  data: {
    text: 0
  },
  beforeCreate () {
    console.log(this, 'beforeCreate')    // => "beforeCreate"
  },
  created () {
    console.log(this, 'created')    // => "created"
  },
  beforeMount () {
    console.log(this, 'beforeMount')    // => beforeMount
  },
  mounted () {
    console.log(this, 'mounted')    // => Mounted
  },
  beforeUpdate () {
    console.log(this, 'beforeUpdate')    // => beforeUpdate
  },
  updated () {
    console.log(this, 'updated')    // => updated
  },
  activated () {
    console.log(this, 'activated')
  },
  deactivated () {
    console.log(this, 'deactivated')
  },
  beforeDestroy () {
    console.log(this, 'beforeDestroy')
  },
  destroyed () {
    console.log(this, 'destroyed')
  }
})

setTimeout(()=> {
  app.text += 1
}, 1000)


每次数据更新时开始执行 beforeUpdate updated
beforeUpdate    数据更新时调用,发生在虚拟 DOM 打补丁之前。这里适合在更新之前访问现有的 DOM,比如手动移除已添加的事件监听器。
updated    当这个钩子被调用时,组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作
const app = new Vue({
  el: '#app',
  template: '<div>{{ text }}</div>',
  data: {
    text: 0
  },
  beforeCreate () {
    console.log(this, 'beforeCreate')    // => "beforeCreate"
  },
  created () {
    console.log(this, 'created')    // => "created"
  },
  beforeMount () {
    console.log(this, 'beforeMount')    // => beforeMount
  },
  mounted () {
    console.log(this, 'mounted')    // => Mounted
  },
  beforeUpdate () {
    console.log(this, 'beforeUpdate')    // => beforeUpdate
  },
  updated () {
    console.log(this, 'updated')    // => updated
  },
  activated () {
    console.log(this, 'activated')
  },
  deactivated () {
    console.log(this, 'deactivated')
  },
  beforeDestroy () {
    console.log(this, 'beforeDestroy')    // => beforeDestroy
  },
  destroyed () {
    console.log(this, 'destroyed')    // => destroyed
  }
})

setTimeout(()=> {
  app.text += 1
}, 1000)

setTimeout(()=> {
  app.$destroy()    // 销毁
},2000)

beforeDestroy    实例销毁之前调用。在这一步,实例仍然完全可用。
destroyed        Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
打印  this.$el

const app = new Vue({
  el: '#app',
  template: '<div>{{ text }}</div>',
  data: {
    text: 0
  },
  beforeCreate () {
    console.log(this.$el, 'beforeCreate')    // undefined  "beforeCreate"
  },
  created () {
    console.log(this.$el, 'created')    // undefined  "created"
  },
  beforeMount () {
    console.log(this.$el, 'beforeMount')     // <div id="app"></div>   "beforeMount"
  },
  mounted () {
    console.log(this.$el, 'mounted')    //  <div>0</div>  "mounted"
  },
  beforeUpdate () {
    console.log(this, 'beforeUpdate')
  },
  updated () {
    console.log(this, 'updated')
  },
  activated () {
    console.log(this, 'activated')
  },
  deactivated () {
    console.log(this, 'deactivated')
  },
  beforeDestroy () {
    console.log(this, 'beforeDestroy')
  },
  destroyed () {
    console.log(this, 'destroyed')
  }
})

跟 DOM 有关的操作一般放在 mounted 中
跟数据有关的操作可以放在 created 或者 mounted

Vue 数据绑定

const app = new Vue({
  el: '#app',
  template: `
          <div>
            {{ isActive ? 'active' : 'not active' }}
            {{ arr.join('*') }}
            {{ Date.now() }}
            {{ html }}
            <p v-html="html"></p>
          </div>
  `,
  data: {
    isActive: false,
    arr: [1,2,3],
    html: '<span>123<span>'
  },
})


const app = new Vue({
  el: '#app',
  template: `
          <div :class="{ active : !isActive}" @click="handler" :id="aaa">
           <p v-html="html"></p>
          </div>
  `,
  data: {
    isActive: false,
    arr: [1,2,3],
    html: '<span>123<span>',
    aaa: 'main'
  },
  methods: {
    handler: function() {
      console.log('123')
    }
  }
})

computed & watch & methods

new Vue({
  el: '#app',
  template: `
    <div>
      <span>Name: {{name}}</span>
      <br/>
      <span>Name: {{getName()}}</span>
      <br/>
      <span>Number: {{num}}</span>
      <p><input type = "text" v-model="num"></p>
      <p>firstName: <input type = "text" v-model="firstName"></p>
      <p>lastName: <input type = "text" v-model="lastName"></p>
    </div>
  `,
  data: {
    firstName: 'yym',
    lastName: 'Hello',
    num: 0
  },
  computed: {
    name () {
      console.log('new Name')
      return `${this.firstName} ${this.lastName}`
    }
  },
  methods: {
    getName () {
      console.log('getName invoked')
      return `${this.firstName} ${this.lastName}`
    }
  }
})

computed 计算属性是基于它们的依赖进行缓存的,计算属性只有在相关依赖发生改变时才会重新求值, 计算属性缓存

// 计算属性缓存
计算属性的值会被缓存, 只有在其某个反应依赖改变时才会重新计算

// 计算setter
计算属性computed 默认只有getter , 不过在需要时也可以提供一个 setter

  computed: {
    name : {
      // getter
      get: function () {
        return `${this.firstName} ${this.lastName}`
      }
      // setter
      set: function (newValue) {
        const name = newValue.split(' ')
        this.firstName = names[0]
        this.lastName = names[names.length - 1]
      }
    }
  },
new Vue({
  el: '#app',
  template: `
    <div>
      <span>Name: {{name}}</span>
      <br/>
      <span>Name: {{getName()}}</span>
      <br/>
      <span>fullName: {{ fullName }}</span>
      <br/>
      <span>Number: {{num}}</span>
      <p><input type = "text" v-model="num"></p>
      <p>firstName: <input type = "text" v-model="firstName"></p>
      <p>lastName: <input type = "text" v-model="lastName"></p>
    </div>
  `,
  data: {
    firstName: 'yym',
    lastName: 'Hello',
    num: 0,
    fullName: ''
  },
  computed: {
    name () {
      console.log('new Name')
      return `${this.firstName} ${this.lastName}`
    }
  },
  methods: {
    getName () {
      console.log('getName invoked')
      return `${this.firstName} ${this.lastName}`
    }
  },
  watch:{
    firstName (newName,oldName) {
      this.fullName = newName + '' + this.lastName
    }
  }
})


watch 的数据开始是没有变化的, 当相应其他数据发生变化,watch数据的值才会变化

  watch:{
    firstName : {
      handler (newName,oldName) {
        this.fullName = newName + '' + this.lastName
      },
      immediate: true,
      deep:true
    }
  }

数据立即执行  immediate: true
为了发现对象内部值的变化,可以在选项参数中指定 deep: true

watch 主要场景监听到某一数据变化,要去做某一个指定的变化, 需要watch 数据的变化

相关文章