| style与class
| computed、directive、filter
| watch 侦听Data数据的变化
| 生命周期: beforeCreate、create、beforeMount、mounted、beforeUpdate、updated、destroyed
| this.$refs、$el、$data、$watch
| v-bind缩写:、v-on缩写@
Vue2.0
一、Vue的MVVM实现的原理
ViewModel是Vue.js的核心,Vue实例是作用于某一个HTML元素上的,这个元素可以是HTML的body元素,也可以是指定了id的某个元素
DOM Listeners 和 Data Bindings看作两个工具,它们是实现双向绑定的关键。
从view层来看,ViewModel中的DOM Listeners工具会帮我们监测页面上DOM元素的变化,如果有变化,则更改Model中的数据;
从Model层来看,当我们更新Model中的数据时,Data Bindings工具会帮我们更新页面中的DOM元素。
二、安装
$ npm i vue --save-dev
$ npm i vue-cli 脚手架
生命周期
一、构造器
1、每个构造器都是通过创建一个Vue的实例启动的
var vm = new Vue({
// ...
})
2、扩展构造器
通过扩展构造器可以创建可复用的组件构造器
var MyComponent = Vue.extend({
// 扩展选项
})
二、生命周期
1、beforeCreate(): 实例初始化,数据观测(data observer)和事件(event/watcher)配置之前被调用
2、created(): 实例创建完后被调用,完成了数据观测(data observer)和事件(event/watcher)回调,但还挂载还没开始$el属性不可见
3、beforeMount(): 在挂载开始之前调用,render()函数被调用
4、mounted(): el被创建的vm.$el替换,挂载到实例上调用钩子
5、beforeUpdate(): 数据更新时调用,在虚拟DOM重新渲染
6、updated(): 数据更改导致虚拟DOM重新渲染
7、destroyed(): 卸载组件
数据绑定
一、文本绑定: <p>{{ data.name }}</p>
二、html绑定: <p v-html="data"></p>
三、绑定属性的值
<div id="item-{{id}}"></div>
<div :id="userId"></div>
四、表达式: {{ dat.num == 1 }}、 {{ num ? 'yes' : 'no' }}、 {{if(ok) {return message} }}
五、过滤器: {{ message | capitalize }}
连续过滤器: {{ message | filterA | filterB }}
常用指令
指令: 以 v- 开头
<div v-if="greeting == 1"></div>
带参数: <a v-bind:href="url"></a>
一、v-if、v-else-if、v-else条件渲染:
<div v-if="type === 'A'">A</div>
<div v-else-if="type === 'B'">B</div>
<div v-else>Not A/B/C</div>
二、v-show: 显示还是隐藏元素,用的display
三、v-for 循环
$index: 索引 $key:
* 数组
<li v-for="item in items" :key="item">{{ item.message }}</li>
* 数组对象
<li v-for="(val, index) in objList" :key="index">
{{index}}. {{key}} : {{val.type}}
</li>
** 注意:key,如果key没有改变不会重新渲染组件,问题在于子组件中存在于绑定
* filterBy()、orderBy()过滤器
四、v-model: 绑定值,这也是MVVM的关键点
可以对文本表单、单选框 、多选框、下拉菜单进行绑定值
1、lazy: 不是输入时就进行同步而是在change的时候才对数据进行同步
<input type="text" v-model="msg" lazy /> {{msg}}
2、number: 将用户输入的转成Number型,如果返回NaN那就返回原值
3、debounce: 设置一个最小延时,否则如果输入是ajax请求,每次敲击都会去请求
<input type="text" debounce="500" v-model="msg"> // 按完键500毫秒后在进行
获取checkbox值:
<input type="checkbox" v-model="toggle" v-bind:true-value="a" v-bind:false-value="b">
// 当选中时
vm.toggle === vm.a
// 当没有选中时
vm.toggle === vm.b
五、v-bind: 绑定到HTML元素上,v-bind:class="active",缩写 ":" <a :href='url'></a>
六、v-on: 监听DOM事件 v-on缩写: "@" <div @click="doSomeing"></div>
七、ref: 访问子组件
<div ref="box">xxxx</div>
<el-button type="primary" slot="append" @click="getRefs">发送</el-button>
</div>
{
methods:{
getRefs(){
console.log(this.$refs.box.innerHTML); // 获取 $refs
}
}
}
如果绑定一个元素使用 :ref='item'
<p v-for="item in items" :ref="item"></p>
八、v-pre: 跳过这个元素和它的子元素的编译过程,这样加快了编译的速度
<div v-pre>{{ 这里不用框架来编译 }}</div>
九、v-cloak:
十、v-once: 只渲染元素和组件一次,之后的渲染都会跳过次元素
<span v-once>xxxxx</span>
过滤器
过滤器,对绑定值进行处理
一、自定义过滤器
在一个组件中定义过滤器:
<span v-text="message | reverse 'addText' "></span>
export default {
filters: {
capitalize: function (value) {
value = value.toString();
return value.charAt(0).toUpperCase() + value.slice(1)
}
}
}
定义全局过滤器:
filters.js
Vue.filter('datetime', function (value, format) {
if (!value) {
return
}
return moment(value).format(format || 'YYYY-MM-DD HH:mm:ss');
});
main.js
import './filters.js' // 引用
二、内置过滤器
1、uppercase: 字母转成大写
2、lowercase: 字母转成小写
3、capitalize: 首字母转成大写
4、filterBy: 过滤内容
5、limitBy: 过滤数据从开始到指定位置结束的内容
6、orderBy: 过滤排序
7、currency: 货币过滤
8、debounce: 延迟过滤
三、双向过滤器
模型的值显示在视图之前转换它
<input v-mode="money | formatMoney">
<div>{{ money | formatMoney }}</div>
Vue.filter('formatMoney', {
// model -> vlew过程 在更新<input> 元素之初化值
read: function(val){
return '$' + val.toFixed(2);
},
// vlew -> model过程 在写回数据之前格式化值
write: function(val){
var number = +val.replace(/[^\d.]/g, '');
return isNaN(number) ? 0 : parseFloat(number.toFixed(2));
}
})
四、动态参数
参数用空格格开
<input type="text" v-model="userInput">
<span>{{msg | concat userInput}}</span>
Vue.filter('concat', function (value, input) {
// `input` === `this.userInput`
return value + input;
})
五、filterBy过滤器
<div id="app">
<div>过滤数据里包含 蛋糕 字符 </div>
<div class="box">
<ul>
<li v-for="user in users | filterBy '蛋糕' ">{{ user.name }}</li>
</ul>
</div>
<div style="margin-top: 30px" >过滤出输入的字符</div>
<input type="text" name="" v-model="searchKey" />
<div class="box">
<ul>
<li v-for="user in users | filterBy searchKey in 'name'">{{ user.name }}</li>
</ul>
</div>
</div>
<script src="../../js/vue.js"></script>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
searchKey: '',
users:[
{
name: '外卖',
tag: 1
},
{
name: '鲜花',
tag: 5
},
{
name: '蛋糕',
tag: 4
},
{
name: '水果',
tag: 2
},
{
name: '茶点',
tag: 3
}
]
}
})
</script>
六、orderBy排序
<div id="app">
<input type="text" name="" v-model="searchKey" />
<div class="box">
<ul>
<li v-for="user in users | orderBy 'tag'">{{ user.name }}</li>
</ul>
</div>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
searchKey: '',
users:[
{
name: '外卖',
tag: 1
},
{
name: '咖啡',
tag: 5
},
{
name: '餐厅订座',
tag: 4
},
{
name: '蛋糕',
tag: 2
},
{
name: '票务',
tag: 3
}
]
}
})
</script>
指令
一、钩子函数
el:指令所绑定的元素,可以用来直接操作 DOM 。
binding:一个对象,包含以下属性:
name:指令名,不包括 v- 前缀。
value:指令的绑定值,例如:v-my-directive="1 + 1" 中,绑定值为 2。
oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
expression:字符串形式的指令表达式。例如 v-my-directive="1 + 1" 中,表达式为 "1 + 1"。
arg:传给指令的参数,可选。例如 v-my-directive:foo 中,参数为 "foo"。
modifiers:一个包含修饰符的对象。例如:v-my-directive.foo.bar 中,修饰符对象为 { foo: true, bar: true }。
vnode:Vue 编译生成的虚拟节点。移步 VNode API 来了解更多详情。
oldVnode:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。
二、对象字面量
<div v-demoA="{ color: 'white', text: 'hello'}"></div>
Vue.directive('demoA', function(el, value){
console.log(value.color);
console.log(value.text);
})
三、元素指令,相当于angular的E指令
Vue.elementDirective('my-directive', {
bind: function(){
// 操作this.el
}
})
<my-directive></my-directive> // 不能这么写<div v-my-directive></div>
四、高级选项
params: 自动提取绑定元素的这些特性.
<div v-example a="hi"></div>
Vue.directive('example', {
params: ['a'],
bind: function () {
console.log(this.params.a); // -> "hi"
}
})
computed 计算属性
计算属性当依赖属性发生变化时,属性的值会自动更新,相关的DOM也会同步更新
一、计算属性的getter
<div id="app">
<p>user_inof={{ userInfo }}</p>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
"user_name": "lulu",
"user_age": "20"
},
computed: {
// 一个计算属性getter
userInfo: function(){
return '姓名: '+ this.user_name +' 年龄: '+ this.user_age;
}
}
})
</script>
二、计算属性的setter
var vm = new Vue({
el: '#app',
data: {
"user_name": "lulu",
"user_age": "20"
},
computed: {
userInfo: function(){
get: function(){
return '姓名: '+ this.user_name +' 年龄: '+ this.user_age;
},
set: function(newValue){ // 这里当
this.userInfo = newValue;
}
}
}
})
watch 侦听器
watch 侦听data下指定数据的变化
watch:{
message: function(newValue){
return newValue + 1; // 如果message变化值加1
}
}
// 写在实例化下侦听数据变化
// vm.$watch('message', function(newVal, oldVal){
// console.log(newVal, oldVal);
// this.message = newVal.replace(/s|g/g, '*');
// })
class和style的绑定
一、class
// 对象
<div :class="{ 'active': isActive }"></div>
var vm = new Vue({
el: '#app',
data: {
isActive: true
}
})
// 数组
<div :class="[activeClass, errorClass]"></div> // 三元 <div v-bind:class="[isActive ? activeClass : '', errorClass]"></div>
data: {
activeClass: 'active',
errorClass: 'text-danger'
}
二、style
<div :style="[crm, hk]"> 或 <div :style="{color: activeColor, fontSize: fontSize+'px'}">
var vm = new Vue({
el: '#app',
data: {
activeColor: 'red',
fontSize: 30,
crm: {
color: '#000',
fontSize: '16px'
},
hk: {
color: '#fff',
fontSize: '18px'
}
}
})
事件
一、@click
<div @click="say"></div>
<div @click="say('hi')"></div>
<div @click="content + 1"></div>
<!-- 阻止单击事件冒泡 -->
<a v-on:click.stop="doThis"></a>
<!-- 提交事件不再重载页面 -->
<form v-on:submit.prevent="onSubmit"></form>
<!-- 修饰符可以串联 -->
<a v-on:click.stop.prevent="doThat"></a>
<!-- 只有修饰符 -->
<form v-on:submit.prevent></form>
<!-- 添加事件侦听器时使用事件捕获模式 -->
<div v-on:click.capture="doThis">...</div>
<!-- 只当事件在该元素本身(而不是子元素)触发时触发回调 -->
<div v-on:click.self="doThat">...</div>
二、按键别名
.enter、.tab、.delete (捕获 “删除” 和 “退格” 键)、.esc、.space、.up、.down、.left、.right、.ctrl、.alt、.shift、.meta
三、once: 只处理一次点击 <a v-on:click.once="doThis"></a>
四、修饰符 <input v-on:keyup.13="submit">
模板语法
Vue在底层将模板编译成虚拟DOM渲染函数,也可以不用模板直接写render函数,可选JSX语法
常见问题
一、props传值子元素不会接收
问题1: 封装tab标签来加载不同子组件,当同一组件重新被打开时,应先消毁之前的相同组件在加载新的组件,但在子组件中destroyed()来侦听消毁缺没有回调
// 打开新页面
openTabPage(tabPage, cb) {
// 先关闭存在的同名的,再打开
if (this.pages.some(item => item.name === tabPage.name)) {
this.handleRemove(tabPage.name);
}
this.$nextTick(()=>{ // 使用$nextTick 进行重新渲染
this.pages.push(tabPage);
this.activeName = tabPage.name;
})
if (cb && typeof cb === 'function') {
cb(this.activeName)
}
if (this.tabCreate) {
this.tabCreate(tabPage)
}
},
问题2: 这种加了一层会对相同子组件进行消毁在重建
<template slot="tabcreate">
<create-data-config ref="createDataConfig" :create-prop="createProp"></create-data-config>
</template>
openTab(tabName, row){
// this.createProp['detailInfo'] = row || ''; 这种写法子组件watch不到createProp的变化
this.createProp = {
detailInfo: row || ''
}
}
子组件
watch:{
createProp: function(){
debugger;
}
}
二、v-bind 内联字符串连接
data(){
return {
addString: '加入内容'
}
}
1.x版本 写法 <div attr="xxxx{{addString}}">
2.x版本 写法 <div v-bind="'xxxx'+ addString">
三、checkbox动态创建绑定
// v-model="item.check" 绑定的值要相同
<p v-for="item in checkList">
<input type="checkbox" name="cb" v-model="item.check" /> {{item.name}}
</p>
data(){
return{
checkList:[
{check: false, name: 'aa'},
{check: false, name: 'bb'},
{check: false, name: 'cc'}
]
}
}
四、vue使用jxs语法
new Vue({
el: '#demo',
render (h) {
return ( // 使用这种jsx语法
<AnchoredHeading level={1}>
<span>Hello</span> world!
</AnchoredHeading>
)
}
})
安装插件
$ npm install babel-plugin-syntax-jsx babel-plugin-transform-vue-jsx babel-helper-vue-jsx-merge-props babel-preset-en --save-dev
.babelrc:
{
"presets": ["env"],
"plugins": ["transform-vue-jsx"]
}
https://github.com/vuejs/babel-plugin-transform-vue-jsx
五、vue键盘事件不起作用
@keyup.enter.native="login" // 如果不加.native是不起作用有
六、$nextTick 页面某一块数据渲染完成后在执行其它操作
queryBindBank(){
let that = this;
common.ajax({
url: '/business/web/v1/paytool/payCardList',
method: 'post',
data: {},
dataType: 'json',
success: function(res) {
that.showLoading = false;
if (res && res.data) {
// 渲染数据表
that.bindBankData = res.data.list;
// 需要数据表渲染完后在执行其它操作
that.$nextTick(function(){
cardList.forEach(function(item, idx, arr){
if(item.designAbled){
that.$refs.multipleTable.toggleRowSelection(item);
}
})
})
that.bindBankData.forEach((bank, idx, arr) => {
if(bank.designAbled){
that.selectedRadio = bank.bankCard;
}
})
}
}
});
}
| http://www.jianshu.com/p/95b2caf7e0da // vue-cli
| http://cn.vuejs.org/guide/ // Vue中文官网
| https://github.com/vuejs/vue // github
| http://vuefe.cn/guide/installation.html // 2.0
| http://router.vuejs.org/zh-cn/ // vue-router2.0
| https://github.com/vuejs // Vue组件列表
| http://www.cnblogs.com/dh-dh/p/5606596.html // binding原理,vue的数据
| https://github.com/vuejs/awesome-vue#libraries--plugins
| http://vuex.vuejs.org/zh-cn/ // Vuex 2.0文档
| https://github.com/vuejs/vuex/blob/1.0/docs/zh-cn/intro.md
| http://www.cnblogs.com/keepfool/category/845804.html
| http://www.jianshu.com/p/f8e21d87a572
| https://github.com/pablohpsilva/vuejs-component-style-guide/blob/master/README-CN.md#%E5%9F%BA%E4%BA%8E%E6%A8%A1%E5%9D%97%E5%BC%80%E5%8F%91 // Vue代码规范
| https://juejin.im/book/5a36661851882538e2259c0f/section/5a37bbb35188257d167a4d64 源码