Vue.js
Vue是一套用户构建用户界面的渐进式框架,其核心是允许采用简洁的模板语法来声明式的将数据渲染进DOM。
构建项目
# 安装node.js和npm
$ npm install vue
$ npm install vue-cli -g # 全局安装
$ vue init webpack my-project # 基于webpack模板构建
$ cd my-project
$ npm install # 安装依赖
$ npm run dev
# 运行git clone 项目
$ cd project
$ npm install --save # 保存在package.json的dependencies(生产环境)中, --save-dev 保存在devDependencies(开发环境)
$ npm i <package> -S -D # 安装 -S = --save -D --save-dev
$ npm run dev
$ npm run build # 打包压缩
# cnpm, 是国内的淘宝镜像,支持publish之外的所有命令
$ npm install -g cnpm --registry=https://registry.npm.taobao.org
$ cnpm install -g yarn
$ yarn install # yarn 相比npm速度更快
基础
// <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
// <div id="app">
// {{ message}}
// </div>
var app = new Vue({
el: '#app',
data: {
message: 'hello, world'
}
})
v- 表示Vue提供的特殊特性
v-once // 一次性插值
v-html // 原始html
v-bind // 响应式更新html
v-if // if
v-for // for
v-on // 监听DOM事件
v-on:submit.prevent="onSubmit" // 修饰符
v-model // 在表单元素上创建双向数据绑定
// 定义组件
Vue.component('todo-item', {
template: '<li>这是一个代办项</li>'
})
// 创建Vue实例
var data = {a: 1, message: 'hello'}
var vm = new Vue({
data: data
})
// 只有data中的数据是响应式的
Object.freeze(data) // 会阻止修改现有的属性
vm.a = data.a // 数据属性
// 实例属性和方法
vm.$el = document.getElementById('expmple')
vm.$data = data
vm.$watch('a', function (newValue, oldValue)) {
// 这个回调将在a改变后调动
}
var vm = new Vue({
el: '#expmple',
data: data,
created: function () {
// 钩子函数,在实例被创建时执行
},
methods: { // 方法, 没有缓存
reverseMessage: function () {
return this.message.split('').reverse().join()
}
},
computed: { // 计算属性, 只有当message改变时, 才会重新求值, 有缓存
reverseMessage: function () {
return this.message.split('').reverse().join()
},
fullNmae: {
// getter
get: function () {
return this.fistName + ' ' + this.lastName
},
// setter
set: function (newValue) {
var names = newValue.split(' ')
this.firstName = names[0]
this.lastName = names[name.length - 1]
}
}
},
watch: { // 侦听属性
firstName: function (val) {
this.fullName = val + ' ' + this.lastName
}
}
})
// 模板语法
<span>Message: {{ msg }}</span> 文本插值,不能在html上
<span v-once>这个不会改变: {{ msg }}</span>
v-html 使用html
<button v-bind:disabled="isButtonDisabled">Button</button> 数据使用在html上
<p v-if="seen">现在看到我了</p>
<a v-bind:href="url"></a>
<a v-on:click="doSomething"></a>
<from v-on:submit.prevent="onSubmit"></from>
<a v-bind:href="url"></a> 缩写 <a :href="url"></a>
<a v-on:click="doSomething"></a> 缩写 <a @click="doSomething"></a>
// 绑定html class
<div v-bind:class="{ active: isActive }"></div>
<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px'}"></div>
// 条件
<div v-if="type === 'A'"></div>
<div v-else_if="type === 'B'"></div>
<div v-else="type === 'C'"></div>
<h1 v-show="ok"></h1>
// 列表渲染
<li v-for="item in items">
{{ item.message }}
</li>
<li v-for="(item, index) in items">
<div v-for="item of items"></div> // 迭代器
var explame = new Vue({
el: '#explame',
data: {
items: [
{ message: 'Foo'},
{ message: 'Bar'}
]
}
})
动态添加,触发响应更新
Vue.set(vm.items, indexOfItem, newValue) // 或
vm.$set(vm.items, indexOfItem, newVaule)
// 监听事件
v-on
事件修饰符
v-on:click.stop // 阻止单机事件继续
v-on:submit.prevent="onSubmit" // 提交事件不再重载页面
v-on:click.capture // 即元素自身触发的事件先在此处理,然后才交由内部元素进行处理
v-on:click.self // 即事件不是从内部元素触发的
v-on:click.once // 只会触发一次
v-on:scroll.passive="onScroll" // 滚动事件的默认行为 (即滚动行为) 将会立即触发
按键修饰符
<input v-on:keyup.enter="submit"> // 只有按enter时,才执行
// 表单输入绑定
v-model 对<input> <textarea> <select> 有效
修饰符
v-model.lazy // 在change时更新
v-model.number // 自动输入值转为数值类型
v-model.trim // 过滤用户输入的首尾空白字符
// 组件
// 定义一个名为 button-counter 的新组件
Vue.component('button-counter', {
data: function () { // data 必须是一个函数
return {
count: 0
}
},
props: ['title'],
template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>'
})
<div id="components-demo">
<button-counter title="hello"></button-counter>
</div>
new Vue({ el: '#components-demo' })
通过props向子组件传递数据
通过$emit向父组件发送消息
v-on:click="$emit('enlarge-text', 0.1)"
在组件中使用v-model
Vue.component('custom-input', {
props: ['value'],
template: `
<input
v-bind:value="value"
v-on:input="$emit('input', $event.target.value)"
>
`
})
<custom-input v-model="searchText"></custom-input>
组件
Vue.component('my-component-name', { // 全局
// pass
})
new Vue ({ el: '#app'})
<div id="app">
<my-component-name></my-component-name>
</div>
var ComponentA = {} // 局部
new Vue ({
el: '#app',
components: {
'component-a': ComponentA
}
})
基础组件全局注册要在根Vue实例创建之前发生
// Prop
props 用短横写法
props: {
title: String, // 可以定义类型
likes: Number
}
Vue.component('blog-post', {
props: ['post-title'],
template: '<h3>{{ post-title }}</h3>'
})
<blog-post v-bind:post-title="post.post-title"></blog-post>
props 可以类型检查
inheritAttrs: false // 禁用特性继承
// 插槽内容
<slot name="header"></slot>
// 动态组件
<keep-alive> // 会缓存失活的组件
component v-bind:is="currentTabComponent"></component> // 切换组件
</keep-alive>
Vue.component( // 异步组件
'async-webpack-example',
// 这个 `import` 函数会返回一个 `Promise` 对象。
() => import('./my-async-component')
)
new Vue({
data: {
foo: 1
}
})
this.$root.foo // 获取根实例
this.$parent.map // 获取父级组件实例
this.$refs.usernameInput // 访问子组件实例
provide: function () { // 依赖注入
return {
getMap: this.getMap
}
}
inject: ['getMap']
过渡
使用transition组件,可以给任何元素和组件添加进入/离开过渡
<div id="demo">
<button v-on:click="show = !show">
Toggle
</button>
<transition name="fade">
<p v-if="show">hello</p>
</transition>
</div>
new Vue({
el: '#demo',
data: {
show: true
}
})
.fade-enter-active, .fade-leave-active {
transition: opacity .5s;
}
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
opacity: 0;
}
// 配合css动画库
<link href="https://cdn.jsdelivr.net/npm/[email protected]" rel="stylesheet" type="text/css">
// 数据也可以过渡动画
组合
// 混入
var myMixin = {
created: function () {
this.hello()
},
methods: {
hello: function () {
console.log('hello from mixin')
}
}
}
var Component = Vue.extend({
mixins: [myMixin]
})
var component = new Component() // "hello from mixin"