一、基础组件
当Vue实例中出现了el 和 template 两个属性时,template的优先级大于el。Vue中组件的名字首字母要大写。
1.1、子组件基本用法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue 组件的基本使用</title>
</head>
<body>
<div id="app">
<!-- 3.2使用子组件 -->
<!-- <App /> -->
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
<script>
// 1、声明子组件
let App = {
data(){
return {
name:'Jsom'
}
},
template:`
<div>
<h2>{{ name }}</h2>
</div>
`
}
let vm = new Vue({
el:'#app',
data(){
return {
msg:'Vue'
}
},
// 3.1、使用子组件,不用template可以直接在父组件中使用子组件
template:`<App />`,
// 2、通过 components 属性把子组件挂载到父组件中
components:{
App
}
})
</script>
</body>
</html>
1.2、Vue.component(’’,{}) 声明全局组件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>component 声明全局组件</title>
</head>
<body>
<div id="app"><heade></heade></div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
<script>
Vue.component('heade',{
data:function (){
return {
name:'Head'
}
},
template:'<div>{{ name }}</div>'
})
let vm = new Vue({el:'#app'})
</script>
</body>
</html>
PS:定义组件名的时候千万不能与HTML标签名冲突。
1.3、props 父子组件传值
父组件给子组件传值方法:
- 声明props,将父组件要传入子组件的值通过props挂载到子组件
- 父组件在使用子组件时,通过 v-bind 将父组件要传给子组件的值绑定到子组件标签上。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>父组件给子组件传值</title>
</head>
<body>
<div id="app"></div>
<script src='https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js'></script>
<script>
// 将父组件的 msg 传入子组件中
// 子组件
let App = {
data(){
return {
name:'我是子组件'
}
},
// 1、声明props,将父组件要传入子组件的值通过props挂载到子组件
// PS:props声明的值,必须与父组件传输值的名称相同。
props:['msg','obj'],
template:`
<div>
<h2>{{ name }}</h2>
<!--使用父组件传入的值。-->
<h3>{{ msg }}</h3>
<h4>{{ obj.age }}</h4>
</div>
`
}
// 父组件
let vm = new Vue({
el:'#app',
data(){
return {
msg:'父组件给子组件的值',
obj:{
age:30
},
style:{
style:'color:red'
}
}
},
// 2、父组件在使用子组件时,通过 v-bind 将父组件要传给子组件的值绑定到子组件标签上。
// :msg 表示 props 中的值,='msg' 表示父组件传给子组件的值
// 3、给子组件标签传入父组件的值。使用v-bind 把父组件要传的值绑定到子组件标签上。
template:`<App :msg = 'msg' :obj = 'obj' v-bind = 'style' />`,
components:{
App
}
})
</script>
</body>
</html>
结果:
子组件给父组件传值方法:
1. 父组件通过在子组件标签上绑定自定义事件和事件处理函数。
2. 在子组件中创建函数,通过该函数运行
e
m
i
t
方
法
给
父
组
件
传
值
。
3.
通
过
V
u
e
提
供
的
emit方法给父组件传值。 3. 通过Vue提供的
emit方法给父组件传值。3.通过Vue提供的emit方法将子组件的值传给父组件。
4. 通过自定义事件处理函数接收子组件传过来的值。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>父组件给子组件传值</title>
</head>
<body>
<div id="app">
<h2>{{ msg }}</h2>
</div>
<script src='https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js'></script>
<script>
// 将子组件的 name 传入父组件中
let App = {
data(){
return {
name:'我是子组件',
obj:{
age:25
}
}
},
props:['msg'],
template:`
<div>
<h2 @click='childData'>{{ name }}</h2>
<h3>{{ msg }}</h3>
</div>
`,
methods:{
// 2、在子组件中创建函数,通过该函数运行$emit方法给父组件传值。
childData(){
// 3、通过Vue提供的$emit方法将子组件的值传给父组件。
// PS:$emit 第一个值为父组件绑定的自定义事件名称,第二个值为要传的值。
this.$emit('fatherEven',this.obj.age);
}
}
}
// 父组件
let vm = new Vue({
el:'#app',
data(){
return {
msg:'父组件给子组件的值'
}
},
methods:{
// 4、通过自定义事件处理函数接收子组件传过来的值。
// PS:val为子组件传过来的值。
fatherData(val){
this.msg = val;
}
},
template:`
<div>
<h2>{{ msg }}</h2>
<!-- 1、父组件通过在子组件标签上绑定自定义事件和事件处理函数。 -->
<App @fatherEven = 'fatherData' :msg = 'msg'/>
</div>
`,
components:{
App
}
})
</script>
</body>
</html>
结果:
平行组件传值方法:
这种传值方法可以取代上面两种传值方法,更加简便的实现传值的需求。
Test 需要通过 $on() 声明这个事件,而App则通过 $emit() 来调用Test声明的事件。
PS:
- $on $emit 必须绑定在同一个示例对象中。
- 需要注意的是 $on 中this的指向问题,由于对象中的传统函数是谁调用this就指向谁,所以需要通过箭头函数改变this指向组件对象。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>平行组件传值</title>
</head>
<body>
<div id="app">
</div>
<script src='https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js'></script>
<script>
var bus = new Vue();
// 子组件App 给 组件Test 传值
// Test 需要通过$on()声明这个事件,而App则通过$emit() 来调用Test声明的事件。
// PS:1、$on $emit 必须绑定在同一个示例对象中。
// 2、需要注意的是 $on 中this的指向问题,由于对象中的传统函数是谁调用this就指向谁,
// 所以需要通过箭头函数改变this指向组件对象。
Vue.component('Test',{
data(){
return {
text:''
}
},
template:`
<div>
{{ text }}
</div>
`,
methods:{
},
created(){
// 1、Test 需要通过$on()声明这个事件。
// 为什么这里的箭头函数中的this指向的组件对象?
// 这里 bus.$on() 调用其内部匿名函数时,箭头函数指向当前调用该函数上文关系中的父对象。
// bus.$on('',()=>{console.log(this)}) -> 上文关系 created() 函数的父对象 -> Vue.component('Test')。
bus.$on('appData2',(val)=>{
// 3、把传过来的值设置到接收组件中。
this.text = val;
});
}
})
let App = {
data(){
return {
name:'我是子组件App'
}
},
template:`
<div>
<h2 @click='appData'>{{ name }}</h2>
</div>
`,
methods:{
// 2、App通过$emit() 来调用Test声明的事件。
appData(){
bus.$emit('appData2',this.name);
}
}
}
// 父组件
let vm = new Vue({
el:'#app',
data(){
return {
msg:'父组件给子组件的值'
}
},
methods:{
},
template:`
<div>
<App />
<Test />
</div>
`,
components:{
App
}
})
</script>
</body>
</html>
结果:
二、filter 过滤器
2.1、过滤器的使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>过滤器的使用</title>
</head>
<body>
<div id="app"><heade></heade></div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
<script src="http://momentjs.cn/downloads/moment.js"></script>
<script>
// 定义全局过滤器
Vue.filter('myStr',function(val){
return val.split('').reverse().join('')
})
Vue.component('heade',{
data:function (){
return {
name:'Head',
time:new Date()
}
},
template:`<div>
<h1>过滤器的使用方法</h1>
<h2>{{ name|myStr }}</h2>
<div>{{ time|myTime("YYYY-MM-DD") }}</div>
</div>`,
// 定义局部过滤器
filters:{
myTime(val,t){
return moment(val).format(t)
}
}
})
let vm = new Vue({
el:'#app'
})
</script>
</body>
</html>
三、生命周期和钩子函数
beforeCreate
created --> *组件创建完成,发送ajax获取后台数据。
beforeMount
mounted --> *组件挂载完成,DOM 渲染完成,可以进行DOM操作。
beforeUpdate
updated --> 修改DOM完成。
activated --> 组件激活时调用,搭配 keep-alive 组件标签使用。
deactivated --> 组件停用时调用,搭配 keep-alive 组件标签使用。
beforeDestroy --> 销毁组件前。
destroyed --> 已经销毁组件,定时器销毁一般在这个函数中处理。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>生命周期和钩子函数</title>
</head>
<body>
<div id="app">
<keep-alive>
<heade v-if='show'></heade>
</keep-alive>
<button @click="isshow">修改DOM</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
<script>
Vue.component('heade',{
data:function (){
return {
name:'Head',
}
},
template:`<div>
<h2>{{ name }}</h2>
</div>`,
created(){
console.log('创建组件完成!')
},
mounted(){
console.log('组件更新完成!')
},
activated(){
console.log('激活组件!')
},
deactivated(){
console.log('停用组件!')
}
})
let vm = new Vue({
el:'#app',
data(){
return{
show:true
}
},
methods:{
isshow(){
this.show = !this.show;
}
},
})
</script>
</body>
</html>
四、refs属性获取原生DOM
ref 被用来给元素或子组件注册引用信息。引用信息将会注册在父组件的 $refs 对象上。如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例:
<input ref="input">
this.$refs.input.focus()
<child-component ref="child"></child-component>
this.$refs.child.focus()
五、模块系统
5.1、文件结构
<template>
<div>
<app-header></app-header>
</div>
</template>
<style>
...
</style>
<script>
import AppHeader from './AppHeader.vue'
export default {
name:'app',
props:['data']
data() {
return {}
},
methods: {
},
components: {
AppHeader
}
}
</script>
template 里是模板代码,这里一般是一个闭合的html标签,比如一个div。
style 里是css代码,这个代码是作用到整个页面的,如果只想作用到当前的模板中,需要用scoped属性
<style scoped>
如果想用一些css预处理器,比如sass,只需要声明lang,然后vue-loader就会自动的加载,当然,前提是对应的 sass-loader安装好。
<style lang="sass">
script 注意这里使用的是 es6 的代码,可以使用babel来编译,所以理所当然需要安装 babel,es6的preset,还要在根目录下自建 .babelrc 文件。具体可以参考官方的 vue-cli 来初始化项目。