用了一段时间的 Vue,基本熟悉了讨论,看到 Vue2.0 已经发布,而且文档已经比较齐全,刚好学习和迁移一下
Vue2 的一份详细修编记录
https://github.com/vuejs/vue/issues/2873
vue-migration-helper
Vue 官方提供了一个有意思的工具可以对代码进行扫描,并提醒哪里需要进行代码的修改:
安装:
sudo npm install --global git://github.com/vuejs/vue-migration-helper.git
package.json 中的这个配置项会创建一个 /usr/local/bin/vue-migration-helper 文件
"bin": {
"vue-migration-helper": "index.js"
},
然后就可以直接调用:
# navigate to a Vue 1.x project directory
cd path/to/my-vue-project
# scan all files in the current directory
vue-migration-helper
# scan all files in specific sub-directories
vue-migration-helper src folder-a folder-b
具体修改:
这些是我在升级过程中遇到的点,显然 Vue2 并不兼容 Vue1,重构的比较全面
Vue1 | Vue2 |
---|---|
实例中的 ready 方法 | 使用 mounted 替代 |
ajax 的回调方法中支持 this 调用 Vue 实例 | 不再支持,请使用 var vm = this 在 ajax 之前 |
< img src="@{{imagePath}}"> 不再有效 | 请使用 < img v-bind:src="imagePath"> |
<a href="/path/to/@{{id}}"> 不再有效 | 请使用 <a v-bind:href="'/path/to' + id"> |
参数变化 vm.$set('products', objectData) | 变为了 vm.$set(vm, 'products', objectData); |
实例中的data如果是对象,需要初始化 | 可以不用 |
有趣的知识点
这些语法并非是 Vue2 新有的,只是在学习过程中发现到的,比较有意思,就记录在这里:
Shorthands
<!-- full syntax -->
<a v-bind:href="url"></a>
<!-- shorthand -->
<a :href="url"></a>
<!-- full syntax -->
<a v-on:click="doSomething"></a>
<!-- shorthand -->
<a @click="doSomething"></a>
computed property
和 Vue 实例中的属性值绑定 getter 关系的方法集,在每次调用 getter 属性的时候都会自动响应到的方法
var vm = new Vue({
data: {
message: 'Hello'
},
computed: {
// a computed getter
reversedMessage: function () {
// `this` points to the vm instance
return this.message.split('').reverse().join('')
}
}
})
Watchers
在异步操作的情况下,需要使用 Watcher 去监控一个数据,并作出相应的显示:
<!-- Since there is already a rich ecosystem of ajax libraries -->
<!-- and collections of general-purpose utility methods, Vue core -->
<!-- is able to remain small by not reinventing them. This also -->
<!-- gives you the freedom to just use what you're familiar with. -->
<script src="https://unpkg.com/axios@0.12.0/dist/axios.min.js"></script>
<script src="https://unpkg.com/lodash@4.13.1/lodash.min.js"></script>
<script>
var watchExampleVM = new Vue({
el: '#watch-example',
data: {
question: '',
answer: 'I cannot give you an answer until you ask a question!'
},
watch: {
// whenever question changes, this function will run
question: function (newQuestion) {
this.answer = 'Waiting for you to stop typing...'
this.getAnswer()
}
},
methods: {
// _.debounce is a function provided by lodash to limit how
// often a particularly expensive operation can be run.
// In this case, we want to limit how often we access
// yesno.wtf/api, waiting until the user has completely
// finished typing before making the ajax request. To learn
// more about the _.debounce function (and its cousin
// _.throttle), visit: https://lodash.com/docs#debounce
getAnswer: _.debounce(
function () {
var vm = this
if (this.question.indexOf('?') === -1) {
vm.answer = 'Questions usually contain a question mark. ;-)'
return
}
vm.answer = 'Thinking...'
axios.get('https://yesno.wtf/api')
.then(function (response) {
vm.answer = _.capitalize(response.data.answer)
})
.catch(function (error) {
vm.answer = 'Error! Could not reach the API. ' + error
})
},
// This is the number of milliseconds we wait for the
// user to stop typing.
500
)
}
})
</script>
Event Modifiers
<!-- the click event's propagation will be stopped -->
<a v-on:click.stop="doThis"></a>
<!-- the submit event will no longer reload the page -->
<form v-on:submit.prevent="onSubmit"></form>
<!-- modifiers can be chained -->
<a v-on:click.stop.prevent="doThat"></a>
<!-- just the modifier -->
<form v-on:submit.prevent></form>
<!-- use capture mode when adding the event listener -->
<div v-on:click.capture="doThis">...</div>
<!-- only trigger handler if event.target is the element itself -->
<!-- i.e. not from a child element -->
<div v-on:click.self="doThat">...</div>
Key Modifiers
<input v-on:keyup.enter="submit">
.trim
<input v-model.trim="msg">
DOM Template Parsing Caveats
This will lead to issues when using custom components with elements that have such restrictions, for example:
<table>
<my-row>...</my-row>
</table>
The custom component <my-row> will be hoisted out as invalid content, thus causing errors in the eventual rendered output. A workaround is to use the is special attribute:
<table>
<tr is="my-row"></tr>
</table>
scope
终于反应过来,这个单词的中文翻译是:作用域
Props
component 在 HTML 上以属性的形式来进行值传递的方式:Every component instance has its own isolated scope. This means you cannot (and should not) directly reference parent data in a child component’s template. Data can be passed down to child components using props.
Vue.component('child', {
// declare the props
props: ['message'],
// just like data, the prop can be used inside templates
// and is also made available in the vm as this.message
template: '<span>{{ message }}</span>'
})
<child message="hello!"></child>
camelCase vs. kebab-case
Vue.component('child', {
// camelCase in JavaScript
props: ['myMessage'],
template: '<span>{{ myMessage }}</span>'
})
<!-- kebab-case in HTML -->
<child my-message="hello!"></child>
Prop Validation
Vue.component('example', {
props: {
// basic type check (`null` means accept any type)
propA: Number,
// multiple possible types
propB: [String, Number],
// a required string
propC: {
type: String,
required: true
},
// a number with default value
propD: {
type: Number,
default: 100
},
// object/array defaults should be returned from a
// factory function
propE: {
type: Object,
default: function () {
return { message: 'hello' }
}
},
// custom validator function
propF: {
validator: function (value) {
return value > 10
}
}
}
})
Events interface
vm.$on('test', function (msg) {
console.log(msg)
})
vm.$emit('test', 'hi')
// -> "hi"