Vue组件 本质上是一个有预定义选项的Vue实例,
Vue.component('todo-item',{
template:'<li>vue实例</li>',
props:['msg']
})
在其他地方使用
<todo-item></todo-item>
vues生命周期
beforeCreate() vue对象实例初始化之前
create() vue对象及时间完全初始化
beforMouted() 检查是否任何模板可用于DOM中呈现
mouted() 模板准备就绪 用模板数据替换DOM元素
beforeUpdate() //外部事件/用户操作之前
update() //实际更新DOM对象
beforeDestroy() 对象破坏之前
destroyed对象破坏
备注
生命周期禁止使用箭头函数(this指向一直向上查找会报错)
vue中的数据是响应式的如果数据变化他的页面就会自动变化,但是如果使用
var obj={foo:"bar"};
Object.freeze(obj); //阻止修改现有的属性
new Vue({data:obj})
指令 带有v- 前缀的特殊特性。作用是 当表达式的值改变时,将其长生的连带影响,响应式地作用于DOM
修饰符
<!-- 阻止单击事件冒泡 -->
<a v-on:click.stop="doThis"></a>
阻止默认事件
<div v-on:click.prevent="dothat"></div>
修饰符串联使用
<div v-on:click.stop.prevent="doThat"></div>
事件捕获 模式
<div v-on:click.capture="doThis"></div>
只有该元素本身触发
<div v-on:click.self="doThat"></div>
<!-- 滚动事件的默认行为 (即滚动行为) 将会立即触发 -->
<!-- 而不会等待 `onScroll` 完成 -->
<!-- 这其中包含 `event.preventDefault()` 的情况 -->
<div v-on:scroll.passive="onScroll">...</div>
按键修饰符
<input v-on:keyup.enter="fn">
监听键盘
<! >
计算属性
使用计算属性的原因:模板中放入太多的逻辑会让模板国中难以维护
计算属性和方法都能返回正确的结果
不同的是计算属性的结果可以缓存,只有当数据变化时,才会重新执行计算,否则会缓存以前的结果
v-model
输入框
<input v-model="message" placeholder="输入文字">
<p>Message is:{{message}}</p>
clas 绑定
1 绑定对象
<div :class="{'obj1':obj1,'obj2':obj2}"></div>
data:{
obj1:btn,
obj2:btn1
}
2 绑定数组
<div :class="[class1,class2]"></div>
data:{
class1:'btn1',
class2:'btn2'
}
3 绑定三元表达式
<div :class="[active? active1:active2]"></div>
data:{
active:true,
active1:'active',
active2:'false'
}
4 绑定计算属性
<div :class="classes"></div>
data:{
isActive:true,
isError:null
},
computed:{
classes(){
return {
active:this.isActive&&!isError,
'text-fail':this.error&&this.error.type==='fail'
}
}
}
5 绑定内联样式
css属性名使用驼峰或者短横线分隔,存储值为字符串形式
<div v-bind:style="{color:color,fontSize:font}"></div>
data:{
color:'red',
font:'30px'
}
组件
组件名
1 短线分隔
Vue.component('my-component',{})
2 首字母大写
Vue.component('MyComponent',{})
全局注册
<div id="app">
<my-component></my-component>
</div>
var vm=new Vue({
el:'#app'
})
//只能在根实例模板中使用 全局注册的行为必须在根Vue实例(new Vue)创建之前执行
Vue.component('my-component',{})
Prop
1 接收父组件传来的参数
组件标签中通过<blog-post post-title="hello!"></blog-post> 传入
2 子组件中js中的props:[postTitl]设置属性
3 可以设置数据类型
props:{
title:String,
likes:Number,
isPublished:Boolean,
commentIds:Array,
author:Object
}
4 接收动态赋值
动态赋值一个变量
<blog-post v-bind:title="post.title"></blog-post>
动态赋值一个表达式
<blog-post v-bind:title="post.title + 'by' + post.author.name"></blog-post>
5 传入一个对象的所有属性
post:{
id:1,
title:'nana'
}
<blog-post v-bind='post'></blog-post>
等价于
(可以用不带参数的v-bind代替v-bind:title)
<blog-post v-bind:title="post.title" v-bind:id="post.id"></blog-post>
6 prop 为单向数据流
所有的prop都是从父组件传到子组件,单向下行绑定,子组件不应该更改prop数据
允许更改的方法
1 子组件作为一个本地的prop数据使用
prop:['init'],
data:function(){
return{
counter:this.init
}
}
2 数据转换
props:['size'],
computed:{
normalizeSize:function(){
return this.size.trim().toLowerCase()
}
}
7 替换合并
如果我们从父级组件传入的属性会替换掉子组件原本的属性但是如果是style class会合并起来
组件
<bootstrap-date-input>
他的模板
<input type="date" class="form-control">
我们使用此组件时
<bootstrap-date-input
data-date-picker="activated"
class="date-picker-theme-dark"
></bootstrap-date-input>
form-control,这是在组件的模板内设置好的
date-picker-theme-dark,这是从组件的父级传入的 他的class 为 form-control date-picker-theme-dark 两者合并
8 禁用特性继承
inheritAttrs: true 允许继承
inheritAttrs: false 不会把未注册的Props呈现为普通的HTML属性
$attrs 获取除class style 以外未注册的特性
Vue.component('base-input', {
inheritAttrs: false,
props: ['label', 'value'],
template: `
<label>
{{ label }}
<input
v-bind="$attrs"
v-bind:value="value"
v-on:input="$emit('input', $event.target.value)"
>
</label>
`
})
自定义事件
1 命名规则 事件命不会自动转化大小写。触发的事件命和监听的事件命必须一样
监听事件名this.$emit('myEvent')
触发事件名 v-on:my-event="doSomething" 不会产生效果
2 将原生事件绑定到组件上
在父组件中给子组件绑定一个原生的事件,就将子组件变成普通的HTML标签,不加".native"事件无法触发
<base-input v-on:focus.native="onFocus"></base-input>
3 $listeners
如果自定义组件名为input类型的但是他的模板根元素为label元素,这时.native就会失效,$listeners属性为一个包含组件上所有事件监听器的对象,可以通过v-on="listeners"将所有的事件监听器指向这个组件的特定子元素
例如 为监视器创建一个inputListeners的计算属性
Vue.component('base-input',{
inheritAttrs:false,
props:['label','value'],
computed:{
inputListeners:function(){
var vm = this
return Object.assign({},$listeners,{input:function(event){
vm.$emit('input',event,target.value)
}})
}
}
]})
4 .sync修饰符
当一个子组件改变了一个prop中的值时。父组件中的值也改变
<child :foo.sync=”msg”></child>
注意
.sync修饰符不和表达式一起使用(v-bind:title.sync="doc.title +'!' ") 无效的
有多个属性时当做对象传入
<text-document v-bind.sync="doc"></text-document>
插槽
1 语法
模板
<a v-bind:href="url" class="nav-link">
<slot></slot>
</a>
<navigation-link url="/profile">
Your Profile
</navigation-link>
渲染时会把<slot></slot>替换为Your Profile 插槽内可以使HTML代码也可以是其他组件。如果中间没有<slot>标签,则该组建中的其他内容会被抛弃
2 编译作用域
<navigation-link url="/profile"> Logged in as {{ user.name }}</navigation-link>可以访问相同实例属性而不能<navigation-link> 的作用域注意父级模板里的内容在父级作用域中编译;子级模板里的内容在子作用域编译
3 具名插槽
需要多个插槽
<div class="container">
<header>
<!-- 我们希望把页头放这里 -->
</header>
<main>
<!-- 我们希望把主要内容放这里 -->
</main>
<footer>
<!-- 我们希望把页脚放这里 -->
</footer>
</div>
解决
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
使用
v-slot指令 以参数的形式提供名称缩写# v-solt:header 等价于 #header
但是 v-slot只能添加在一个<template>上
<base-layout>
<templater v-slot:header>
<h1>Here might be a page title </h1>
</template>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
<template v-slot:footer>
<p> Here's some contact info</p>
</template>
</base-layout>
4 作用域插槽
可以从子组件接收数据,并定义渲染的方式
<div id="root">
<child>
<template slot-scope="props"><!--定义一个插槽,该插槽必须放在template标签内-->
<li>{{props.value}}</li><--!定义使用渲染方式-->
</template>
</child>
<child>
<template slot-scope="props">
<h1>{{props.value}}</h1><!--定义不同的渲染方式-->
</template>
</child>
</div>
<script>
Vue.component('child',{
data: function(){
return {
list:[1,2,3,4]
}
},
template: `<div>
<ul>
<slot v-for="value in list" :value=value>//使用slot占位
</slot>
</ul>
</div>`
})
var vm=new Vue({
el: '#root'
})
</script>
slot-scope为一个对象。对象里的数据就是子组件传来的数据
v-slot:default slot-scope都可以接收来自子组件的数据
动态组件
使用is特性来切换组件
<button @click="view='custom1'">custom1</button>
<button @click="view='custom2'">custom2</button>
<button @click="view='custom3'">custom3</button>
<div :is="view"></div>
<component :is="view"></div>
Vue.component('custom1',{
template:'<div>custom1</div>'
})
Vue.component('custom2',{
template:'<div>custom2</div>'
})
Vue.component('custom3',{
template:'<div>custom3</div>'
})
new Vue({
el:'#demo',
data:{
view:''
}
})
<keep-alive> 将元素动态组件包括起来,组件会被缓存
注意被包括的组件都有自己的名字,不论是name属性 还是局部/全局注册的
异步组件
定义的时候什么都不做,只有在组件渲染的时候进行加载并缓存,以备下次访问
Vue实现按需加载
异步加载的组件在打包的时候,会打包成单独的js文件。通过ajax请求回来插入到HTML中。
处理边界情况
1 每个new Vue实例的组件中。根实例都可以通过$root属性进行访问
new Vue({
data:{
foo:1
},
computed:{
bar:function(){
}
},
methods:{
baz:function(){}
}
})
获取根组件的数据
this.$root.foo
写入根组件的数据
thi.$root.foo = 2
访问根组件的计算属性
this.$root.bar
访问根组件的方法
this.$root.baz()
2 ref获取DOM
给元素或组件一个ID然后在js中调用它
<base-input ref="usernameInput"></base-input>
this.$refs.usernameInput
3 依赖注入provide inject
在父组件中使用provide定义个属性或者方法
在他的任意子组件中通过inject接收它
父级组件提供
provide:{
foo:'bar'
}
后提组件使用inect接收属性
var Child={
inject:['foo'],
created(){
console.log(this.foo)
}
}
4 程序化的监听事件监听
1 父组件通过props把数据传给子组件
2 子组件可以使用$emit触发父组件的自定义事件
5 递归组件
组件可以在他自己的模板中调用自己。必须有name属性,没有name这个属性组件不能自己调用自己,递归的时候需要一个条件来终止递归,v-for
Vue动画
1 基本语法
<button @click="show=!show">
toggle
</button>
<transition name="fade">
<div v-show="show">过渡</div>
</transition>
new Vue({
el:'#demo',
data:{
show:true
}
})
css
.fade-enter-active, .fade-leave-active{
transiton:opacity 0.5s
}
.fade-enter, .fade-leave-to{
opacity:0;
}
Vue.extend(扩展实例构造器)
主要用来服务Vue.component用来生成组件的。
简单说在模板中遇到以该组件命名的自定义标签时,会自动的调用扩展实构造器来生成组件,挂载到自定义元素标签上
Vue.componet('vue-button',{
template:'<button>按钮</button>',
data:function(){},
compunted:{}
})
Vue.component如果传入的普通对象内部会自动调用Vue.extend()生成对象组件然后通过Vue.component注册
混入(mixins)
将一些可复用的方法属性封装起来再需要的组件中使用(类似于reset.css)
1 如果混入的属性和方法与原来组件重合会与组件中的为主
2 混入对象的选项在元组件的选项之前调用
var mixins = {
created:function(){
console.log('混入对象的钩子被调用')
}
}
new Vue({
mixins:[mixin],
created:function(){
console.log('组件钩子被调用')
}
})
全局混入(全局注册的混入对象)
Vue.mixins({
created:function(){
var myOption = this.$options.myOption
if(myOption){
console.log(myOption)
}
}
})
new Vue({
myOption:'hello!'
})
网友评论