Skip to content

Instantly share code, notes, and snippets.

@pjchender
Last active April 30, 2017 14:55
Show Gist options
  • Select an option

  • Save pjchender/063aff2b057374e3eac4eb4f6ebb89ec to your computer and use it in GitHub Desktop.

Select an option

Save pjchender/063aff2b057374e3eac4eb4f6ebb89ec to your computer and use it in GitHub Desktop.
[Vue] 生命週期與 AJAX 使用說明
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Demo Vue</title>
<script src="https://unpkg.com/vue@2.3.0/dist/vue.js"></script>
<script src="https://unpkg.com/axios@0.16.1/dist/axios.js"></script>
</head>
<body>
<div id="app">
<h1>{{ posts[currentId].title }}</h1>
<h2>{{ posts[currentId].body }}</h2>
<h3>{{ id }}</h3>
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
// 這時候因為 posts 沒有資料,但是 render 要顯示,所以會出現錯誤
// TypeError: Cannot read property 'title' of undefined
currentId: 0,
body: '',
title: '',
posts: []
},
computed: {
// computed 的屬性在 vm 初次 create 時不會先被執行一次,
id () {
console.log('id computed')
return `post${this.currentId}`
}
},
methods: {
getCurrentId () {
console.log('getCurrentId', this.currentId)
}
},
beforeCreate () {
// 在 berforeCrate 資料沒 bind 上 vm,所以 this 拿不到資料
console.log('beforeCreate')
},
created () {
// created 之後可以 data bind 上 vm ,可以透過 this 拿到資料
console.log('created')
let self = this
// 這裡面用 AJAX 取得資料
axios({
method: 'get',
url: 'https://jsonplaceholder.typicode.com/posts/'
})
.then(function (response) {
// 把 AJAX 取得的資料代入 Vue 中
self.posts = response.data
console.log('getResponse')
})
.catch(function (error) {
console.log('err', error)
})
},
beforeMount () {
console.log('beforeMount')
},
mounted () {
// vm 初次 create 時,會從 beforeCreate 執行到這裡(mounted)
console.log('mounted')
},
beforeUpdate () {
console.log('beforeUpdate')
},
updated () {
console.log('updated')
}
})
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Demo Vue</title>
<script src="https://unpkg.com/vue@2.3.0/dist/vue.js"></script>
<script src="https://unpkg.com/axios@0.16.1/dist/axios.js"></script>
</head>
<body>
<div id="app">
<!-- title 和 body 是透過 computed 取得,
- 使得 computed 會在 beforeMount 和 mounted 被觸發,
- 但是這時候 this.posts 仍然還沒有資料
-->
<h1>{{ title }}</h1>
<h2>{{ body }}</h2>
<h3>{{ id }}</h3>
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
// 這時候因為 posts 沒有資料,但是 render 要顯示,所以會出現錯誤
// TypeError: Cannot read property 'title' of undefined
currentId: 0,
posts: []
},
computed: {
// computed 的屬性在 vm 初次 create 時不會先被執行一次,
id () {
console.log('id computed')
return `post${this.currentId}`
},
/**
* 因為在 template 中有 {{ title }}
* 促使 computed 在 beforeMount 和 mounted 之間執行
* 但這時候 this.posts 仍沒有資料,出現錯誤
* Error in render function: "TypeError: Cannot read property 'title' of undefined"
**/
title () {
console.log('title computed')
return this.posts[this.currentId].title
},
body () {
console.log('body computed')
return this.posts[this.currentId].body
}
},
methods: {
getCurrentId () {
console.log('getCurrentId', this.currentId)
}
},
beforeCreate () {
// 在 berforeCrate 資料沒 bind 上 vm,所以 this 拿不到資料
console.log('beforeCreate')
},
created () {
// created 之後可以 data bind 上 vm ,可以透過 this 拿到資料
console.log('created')
let self = this
// 這裡面用 AJAX 取得資料
axios({
method: 'get',
url: 'https://jsonplaceholder.typicode.com/posts/'
})
.then(function (response) {
// 把 AJAX 取得的資料代入 Vue 中
self.posts = response.data
console.log('getResponse')
})
.catch(function (error) {
console.log('err', error)
})
},
beforeMount () {
console.log('beforeMount')
},
mounted () {
// vm 初次 create 時,會從 beforeCreate 執行到這裡(mounted)
console.log('mounted')
},
beforeUpdate () {
console.log('beforeUpdate')
},
updated () {
console.log('updated')
}
})
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Demo Vue</title>
<script src="https://unpkg.com/vue@2.3.0/dist/vue.js"></script>
<script src="https://unpkg.com/axios@0.16.1/dist/axios.js"></script>
</head>
<body>
<div id="app">
<h1>{{ title }}</h1>
<h2>{{ body }}</h2>
<h3>{{ id }}</h3>
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
currentId: 0,
posts: [],
title: '',
body: ''
},
computed: {
// 除非有需要,否則 computed 的屬性在 vm 初次 create 時不會先被執行一次
// 如果有需要,則 computed 會在 beforeMound 和 mounted 之間執行
id () {
console.log('id computed')
return `post${this.currentId}`
}
},
methods: {
getCurrentId () {
console.log('getCurrentId', this.currentId)
}
},
beforeCreate () {
// 在 berforeCrate 資料沒 bind 上 vm,所以 this 拿不到資料
console.log('beforeCreate')
},
created () {
// created 之後可以 data bind 上 vm ,可以透過 this 拿到資料
console.log('created')
let self = this
// 這裡面用 AJAX 取得資料
axios({
method: 'get',
url: 'https://jsonplaceholder.typicode.com/posts/'
})
.then(function (response) {
// 把 AJAX 取得的資料代入 Vue 中
self.posts = response.data
// 更新需要初始化的資料
self.title = self.posts[self.currentId].title
self.body = self.posts[self.currentId].body
console.log('getResponse')
})
.catch(function (error) {
console.log('err', error)
})
},
beforeMount () {
console.log('beforeMount')
},
mounted () {
// vm 初次 create 時,會從 beforeCreate 執行到這裡(mounted)
console.log('mounted')
},
beforeUpdate () {
console.log('beforeUpdate')
},
updated () {
console.log('updated')
}
})
</script>
</body>
</html>
@pjchender
Copy link
Copy Markdown
Author

pjchender commented Apr 30, 2017

搭配 AJAX 較好的使用方法

[示範]程式碼與畫面

在 template 中寫每次 render 時要顯示的資料

<div id="app">
    <h1>{{ title }}</h1>
    <h2>{{ body }}</h2>
    <h3>{{ id }}</h3>
  </div>

把 template 有用到的 data 直接寫到 vm.data 中

  1. 在 created 拿到 request 回來的資料後,若有需要,把 request 取得的資料寫入 vm.data 中
  2. 更新需要透過 AJAX 取的資料後,才能初始化的資料。這時候因為我們有更新資料的關係(原本在 data 已經有給值),因此 vm 在建立時,除了從 beforeCreate 跑到 mounted 之外,會進一步促發 beforeUpdateupdated 的 hook
const vm = new Vue({
      el: '#app',
      data: {
        currentId: 0,
        posts: [],
        title: '',
        body: ''
      },
// ...
      created () {
        // created 之後可以 data bind 上 vm ,可以透過 this 拿到資料
        console.log('created')
        let self = this
        // 這裡面用 AJAX 取得資料
        axios({
          method: 'get',
          url: 'https://jsonplaceholder.typicode.com/posts/'
        })
        .then(function (response) {
          // STEP1: 把 AJAX 取得的資料代入 Vue 中
          self.posts = response.data

          // STEP2: 更新需要透過 AJAX 資料才能初始化的資料,如此將進一步促發 `beforeUpdate` 和 `updated`
          self.title = self.posts[self.currentId].title
          self.body = self.posts[self.currentId].body
          console.log('getResponse')
        })
        .catch(function (error) {
          console.log('err', error)
        })
      }
})

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment