Vue 基础

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 数据的变化
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,277评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,689评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,624评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,356评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,402评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,292评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,135评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,992评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,429评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,636评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,785评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,492评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,092评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,723评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,858评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,891评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,713评论 2 354

推荐阅读更多精彩内容

  • 一、模版指令 通过模版指令(写在html中的),即是html和vue对象的粘合剂。 数据渲染 v-text、v-h...
    EndEvent阅读 2,402评论 3 56
  • Vue实例 Vue实例创建和作用 -- 1. app.$data -> 所有data的数据 [obj](app.d...
    胖太_91bf阅读 3,520评论 0 3
  • 相关概念 混合开发和前后端分离 混合开发(服务器端渲染) 前后端分离后端提供接口,前端开发界面效果(专注于用户的交...
    他爱在黑暗中漫游阅读 2,793评论 4 45
  • Vue简介 Vue是数据驱动组件,为现代化的Web页面而生,与ReactJS的中心思想一样,都是一切皆是组件。他是...
    Victor细节阅读 628评论 2 3
  • 每个 Vue 应用都是通过用 Vue 函数创建一个新的 Vue 实例开始的: 实例生命周期钩子 每个 Vue 实例...
    Timmy小石匠阅读 1,380评论 0 11