template 标签
开发时需要有个大标签包裹,但是又不希望存在dom中,这时候可以使用template标签,只识别指令,不作用在dom中。
可以跟v-if, v-for使用,但是不能和v-show使用,无效的
按键修饰符
<input type="text" @keyup.ctrl.c="handleAction"/>
组合键的使用
.c ,.enter,.tab...
系统修饰符
…
组件
先声明组件
参数1:组件的名字
参数2:组件的配置项,必须写template,定义组件的dom结构的
Vue.component('hello-world', {
template: `
<div class="hello-world">
<h1>hello world</h1>
</div>
`
});
上面的方法是声明的全局组件
还有局部组件的声明:
new Vue({
el: '#app',
// 局部组件
components: {
// key组件的名字
// value值 组件的配置项
'com-a': {
template: `
<div class="box">
<h1>info</h1>
</div>
`
},
...
}
})
需要注意的是
局部组件,声明在哪个组件或者实例内部,那么就只有在这个组件或者实例内部才可以使用
其他任何位置都不可以使用
可以使用的组件有:全局组件,自己内部声明的子组件
组件相当于小的vue实例
组件没有el配置项
template是必填的配置项,否则组件运行不了
data需要是一个函数,函数的返回值才是data属性,才是组件的属性\
为什么data需要是一个函数?
组件是可复用的,当组件复用时,每次调用组件都需要给一个新的data对象。而不是同一个对象
其实是一个class,每创建一个组件就是实例化一个class,使用函数return对象,形成闭包,里面的数据就不会共享
组件的生命周期过程,跟实例的生命周期过程是一致的
父子组件的生命周期
父子组件的生命周期,跟起数据调用有关
举个列子:
上面是父子组件index.vue和List.vue
父组件增加list数据来控制组件更新,子组件渲染从index传过去的list数据,组件生命周期打印如下:
脚手架工具配置
main.js
// 入口文件
import Vue from 'vue'
// 项目的根组件
import App from './App.vue'
// 需要采用runtimeCompiler才能执行
// new Vue({
// el: '#app',
// components: {
// App
// },
// template: `<App/>`
// });
// runtime-only就可以编译
new Vue({
render: (h)=>h(App)
//h是一个函数,用编译组件的
}).$mount('#app');
vue内部组件
keep-alive组件
会识别内部将要销毁的组件,进行缓存,不让这个组件销毁
当下次调用时,如果缓存中有,直接取缓存,如果缓存中没有,就创建
<keep-alive>
<Home v-if="selectIndex === 0"/>
<Discover v-if="selectIndex === 1"/>
<Setting v-if="selectIndex === 2"/>
</keep-alive>
component (动态组件)
<keep-alive>
<component :is="pageName"/>
</keep-alive>
组件的动态加载
动态加载全局组件
Vue.component('', ()=>import())
动态加载,如果组件不调用,那么这个文件就不会加载,如果调用了,再加载
组件间的传值
组件间的关系有两种:
1.父子组件
父组件传值给子组件:
在父组件调用子组件时,给子组件绑定自定义属性
在子组件内部使用props接收。子组件内部当成属性使用 template直接用属性名访问,组件js中使用this访问
子组件传值给父组件:
方式1:
在父组件调用子组件时,给子组件绑定自定义属性, 这个自定义属性是一个函数
在子组件内部使用props接收。当需要传值给父组件时,就调用这个属性,通过调用函数传值给父组件
方式2:
在父组件调用子组件时,给子组件绑定自定义事件,事件的实现在父组件中,是一个函数
当子组件需要传值给父组件时,就使用this.$emit()触发该事件,并传参进去,那么父组件的函数就可以接收到参数了。
2.非父子组件
通过发布订阅模式
vm.$off 解除订阅 (移除事件)
vm.$on 订阅(监听事件)
vm.$emit 发布 (触发事件)
// main.js
Vue.prototype.$EventBus = new Vue();
//页面中使用
EventBus.$emit("aMsg", '来自A页面的消息');
EventBus.$on("aMsg", (msg) => {
// A发送来的消息
this.msg = msg;
});
父组件传值给子组件
Father.vue
<Son :city="selectCity"/>
Son.vue
// 也是组件的属性
// 但是实例没有配置项
// 外部属性
props: ['title', 'value', "city"],
props 的类型和效验
props: {
// props支持的类型
value1: Number,
value2: String,
value3: Boolean,
value4: Array,
value5: Object,
value6: Function,
value7: Promise,
// 校验
value8: [Number, String],
value9: {
type: String,
required: true
},
value10: {
type: String,
default: 'hello'
},
value11: {
validator: (value)=>oneOf(value, ['a', 'b', 'c', 'd'])
}
},
单向数据流
不能修改props的数据,需要保证数据是自顶向下单向传递的
(单向数据流只是一个规范的建议,修改props的值依旧可以成功,基本类型数据会被监听到改动,提示报错,引用类型需要改变引用地址才会报错)
子组件传值给父组件
方法1
Father.vue
<Son :onSend="handleSendAction"/>
methods: {
handleSendAction(val){
console.log('触发了:', val);
}
}
Son.vue
<button @click="btnAction">发送</button>
methods: {
btnAction(){ //点击按钮发送数据
// 调用父组件的属性,这个属性是一个函数
this.onSend(this.value);
}
}
方法2:
Father.vue
<Son @send="handleSendAction" />
methods: {
handleSendAction(val, ...rest){
console.log('触发了:', val, rest);
}
}
Son.vue
methods: {
btnAction(){
console.log(this.value);
// 触发组件标签上的事件
// 自定义事件
// 参数1:自定义事件的名字
// 参数2:调用事件的参数
this.$emit('send', this.value, 1, 2, 3);
}
}
vuex 刷新后保存本地
// 在页面加载时读取sessionStorage里的状态信息
if (sessionStorage.getItem('store')) {
this.$store.replaceState(Object.assign(this.$store.state, JSON.parse(sessionStorage.getItem('store'))))
}
// 在页面刷新时将vuex里的信息保存到sessionStorage里
window.addEventListener('beforeunload', () => {
sessionStorage.setItem('store', JSON.stringify(this.$store.state))
})
细节知识点(优先级不高)
1.怎么将组件内的所有props传递给子组件
极少会用到,但面试可能会问
API: $props
使用:
<User v-bind="$props" />