一、 入门
Vue.js(读音 /vjuː/, 类似于 view) 是一套构建用户界面的渐进式框架。Vue 只关注视图层, 采用自底向上增量开发的设计。Vue 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。
1.1 常用指令
插值表达式
v-cloak
解决插值表达式闪烁的问题
1 2 3 4 5 6 7
| [v-cloak]{ display: none; }
<div id='app' v-cloak> {{ msg }} </div>
|
1 2 3 4 5 6
| new Vue({ el: '#app', data: { msg: 'Hello Vue' } })
|
v-text
v-html
v-bind
v-on
v-model
v-for
v-if
v-show
1.2 事件修饰符
- .stop
- .prevent
- .capture
- .self
1.3 Vue实例
1.4 过滤器
1.5 计算方法
1.6 自定义指令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
Vue.directive('focus',{ bind: function(el,binding,vnode) {}, inserted: function(el,,binding,vnode){}, updated: function(el,binding,vnode,oldVnode){}, unbind: function(el,binding,vnode){} })
|
1 2 3 4 5 6 7 8 9 10 11
| new Vue({ el: '#app', diretives: { 'fontweight': { bind: function(el, binding){...}, ... }, 'focus': function(el, binding) {...} } })
|
1.7 Vue 实例的生命周期
- beforeCreate : 实例创建之前,此时 data 和 method 未被初始化。
- created:实例创建完成,data 和 method 初始化完成。最早可以操作 data 和 method 的时机。
- beforeMount:表示模板在内存中已经编译完成,但尚未渲染到页面中。
- mounted:模板已经被挂载到页面中。
- beforeUpdated: Model 和 View 中的一方数据被更新,另一方未被同步
- updated:双方的数据已经同步完成。
- beforeDestroy:即将销毁实例,但实例中的数据、方法等依旧可用。
- destroyed:实例销毁完成。
在 create 之后 beforeMount 之前,Vue 的模板在内存中编译,在 mounted 之后才会渲染到页面中
1.8 axios 实现请求
二、 组件
==template 的模板内容必须有且仅有一个唯一的根元素==
2.1 创建全局组件的方式
- 使用 Vue.extend 方法创建
1 2 3 4 5 6
| var com1 = Vue.extend({ template: '<h3>这是 Vue.extend 创建的组件</h3>', }) Vue.component('myCom',com1)
|
1 2 3
| <div id="app"> <my-com></my-com> </div>
|
- 直接使用 Vue.component 创建
1 2 3
| Vue.component('mycom1',{ template: '<h3>这是 Vue.component 创建的组件</h3>' })
|
- 使用 template 标签创建
1 2 3 4 5 6 7 8 9
| <div id="app"> <mycom2></mycom2> </div>
<template id="temp"> <div> <h2>这是 template 标签创建的组件</h2> </div> </template>
|
1 2 3
| Vue.component('mycom2',{ template: '#temp' })
|
2.2 创建私有组件的方式
1 2 3 4 5 6 7 8 9 10 11
| new Vue({ el: '#app', components: { login: { template: '<h1>只是私有的组件<h1/>' }, index: { template: '<div></div>' } } })
|
2.3 组件中的 data
1 2 3 4 5 6 7 8 9
| Vue.component('mycom1',{ template: '<h3>这是 Vue.component 创建的组件, {{ msg }}</h3>', data: function(){ return { msg: 'Hello World' } }, method: {} })
|
- 组件可以有自己的 data 数据
- 组件的 data 必须是个方法,且返回值必须是对象
- 组件的 data 的使用方式同实例的 data 一样。
2.4 组件切换
1 2 3 4
| <div id="app"> <component :is="comName"></component> </div>
|
1 2 3 4 5 6 7 8 9 10 11 12
| Vue.component('login',{ template: '<h3>登录组件</h3>' }) Vue.component('register',{ template: '<h3>注册组件</h3>' }) new Vue({ el: '#app', data: { comName: 'login' } })
|
2.5 组件过渡
1 2 3 4 5 6
| <div id='app'> <transition mode='out-in'> <component :is="comName"></component> </transition> </div>
|
2.6 组件通信
2.6.1 通过 Prop 向子组件传值
1 2 3 4 5 6 7 8 9 10 11
| Vue.component('login',{ template: '<h3>Hello {{ parent-msg }}</h3>', props: ['parent-msg'] })
new Vue({ el: '#app', data: { msg: 'joker' } })
|
1 2 3
| <div id='app'> <login :parent-msg='msg'></login> </div>
|
数据验证
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| Vue.component('my-component',{ props: { propA: Number, propB: [String, Number], propC: { type: Boolean, default: false }, propD: { type: Number, required: true }, propE: { type: Arry, default: function(){ return [] } }, propF: { validator: function(data) { return data>10 } } } })
|
2.6.2 通过 $emit 向父组件传值
1 2 3 4 5 6 7 8 9 10 11
| <div id='app'> <com @func="show"></com> </div>
<template id='tmpl'> <div> <button @click='myClick'> 子组件的按钮 </button> </div> </template>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| var com = { template: '#tmpl', data(){ return { son-data: { name: 'ha', age: 6 } } } methods: { myClick(){ this.$emit('func',this.son-data); } } } new Vue({ el: '#app', data: { data-from-son: null }, method: { show(data){ this.data-from-son = data } }, components: { com } })
|
2.7 ref 获取 DOM 和引用组件
1 2 3 4 5 6 7 8 9
| <div id='app'> <h3 ref='myh3'>我是标题</h3> <button ref='mybtn'>子组件的按钮</button> <com ref='mycom'></com> </div>
<template id='tmpl'> <h3>我也是标题</h3> </template>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| new Vue({ el: '#app', methods: { getElement(){ console.log(this.$refs.myh3) console.log(this.$refs.mybtn) console.log(this.$refs.mycom.msg) this.$refs.mycom.show() } }, components: { com: { template: '#tmpl', data(){ return {msg: '...'} }, methods: { show(){} } } } })
|
三、 Render 函数
3.1 createElement 用法
3.1.1 基本参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| createElement( 'div', {}, [ createElement('h1','Hello World'), createElement(MyComponent,{ props: { someProp: 'foo' } }), 'bar' ] )
|
createElement( arg0, [ arg1, arg2 ] )
arg0
必选,可以是一个HTML标签,也可以是一个组件huo函数。
arg1
可选,数据对象,在 template 中使用。具体属性见下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| { 'class': { foo: true, bar: false }, style: { color: 'red', fontSize: '14px' }, attr: { id: 'foo' }, props: { myProp: 'bar' }, domProps: { innerHTML: 'baz' }, on: { click: this.clickHandler } ... }
|
arg2
可选,子节点。
四、 使用 webpack
4.1 webpack 基础配置
- 安装 webpack 和 webpack-dev-server
1 2 3
| npm init npm install webpack --save-dev npm install webpack-dev-server --save-dev
|
- 创建 webpack.config.js 配置文件
五、 路由与 vue-router
5.1 路由的基本使用
引入 vue-router
创建组件模板对象
1 2 3 4 5 6
| let login = { template: '<h1>登录组件</h1>' } let register = { template: '<h1>注册组件</h1>' }
|
创建路由对象
1 2 3 4 5 6 7 8 9 10 11
| var routerObj = new VueRouter({ routes: [ { path: '/', redirect: '/login' }, { path: '/login', component: login }, { path: '/register', component: register } ] })
|
- 将路由规则对象注册到 Vue 实例中
1 2 3 4
| new Vue({ el: '#app', router: routerObj })
|
- 在 html 页面中使用
1 2 3 4 5 6 7 8 9 10 11
| <div id='app'> <a href='#\login'>登录</a> <a href='#\register'>注册</a> <router-link to='/login' tag='span'>登录</router-link> <router-link to='/register'>注册</router-link> <router-view></router-view> </div>
|
5.2 传递参数
使用 query 方式传递参数
1
| <router-link to='/login?id=1&name=joe' tag='span'>登录</router-link>
|
1 2 3 4 5 6
| let login = { template: '<h1>登录组件</h1>', created(){ console.log(this.$route.query) } }
|
使用 params 方式传递参数
1 2 3 4 5
| let router = new VueRouter({ routes: [ { path: '/login/:id', component: login } ] })
|
1
| <router-link to='/login/1' tag='span'>登录</router-link>
|
1 2 3 4 5 6
| let login = { template: '<h1>登录组件</h1>', created(){ console.log(this.$route.params) } }
|
5.3 路由嵌套
1 2 3 4 5 6 7 8 9 10 11 12 13
| <div id='app'> <router-link to='/account'>Account</router-link> <router-view></router-view> </div>
<template id='tmpl'> <div> <h1>account组件</h1> <router-link to='/login'>登录</router-link> <router-link to='/register'>注册</router-link> <router-view></router-view> </div> </template>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| let account = { template: '#tmpl' } let login = { template: '<h3>登录组件</h3>' } let register = { template: '<h3>注册组件</h3>l' }
let router = new VueRouter({ routes: [{ path: '/account', component: account, children: [ { path: 'login', component: login }, { path: 'register', component: register } ] }] })
new Vue({ el: '#app', router })
|
5.4 使用命名视图
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| var header = { template: '<h1 class="head">Header</h1>' } var leftBox = { template: '<h1 class="left">Left</h1>' } var mainBox = { template: '<h1 class="main">Main</h1>' } const router = new VueRouter({ routes: [ { path: '/', components: { 'default': header, 'left': leftBox, 'main': mainBox } }, ] })
var app = new Vue({ el: '#app', data: {}, router })
|
1 2 3 4 5 6 7 8 9 10 11
| <div id='app'> <router-view></router-view> <div class="container"> <router-view name='left'></router-view> <router-view name='main'></router-view> </div> </div>
|
六、 状态管理与 Vuex