1、组件基础
组件是可以复用的vue实例,带有一个名字,我们可以在一个通过new vue创建的vue根实例中把这个组件作为自定义元素来使用。
组件化的作用是把应用程序中一些比较独立的功能模块或者单元把他抽取出来,把它封装成组件。像工程零件,搭积木的积木。能在开发后续程序的过程中维护、复用得到进一步的提升。
2.组件注册、使用及数据传递
vue.component(name,options)可用于注册组件。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>购物车</title>
<script src="vue.js"></script>
<style>
.active{
background-color: #ddd;
}
</style>
</head>
<body>
<!-- 宿主文件 -->
<!-- {{ mustache }}是一个动态的值 左右就用双括号{{}}-->
<!-- 插值文本 -->
<!-- v-once执行一次性插值 之后值变了动态值不变 -->
<div id= "app">
<h2 :title="title">
{{ title }}
</h2>
<!-- 用户输入 -->
<!-- 键盘按下事件v-on:keydown -->
<p><input type="text" v-model = "course" v-on:keydown.enter = "addCourse">{{course}}</p>
<button @click = "addCourse">新增</button>
<!-- 列表渲染 -->
<!-- 被选中点击一个动态的类 没有被选中类被移除掉-->
<!-- transparent 没有颜色透明色 -->
<!-- 列表组件 -->
<course-list :courses = "courses"></course-list>
<!-- <div
v-for="c in courses"
:key="c"
:style = "{backgroundColor: selectedCourse === c ? '#' : 'transparent'}"
@click = "selectedCourse = c">
{{ c }}
</div> -->
<script>
// 课程列表组件
// 组件命名建议取成羊肉串命名法,如果使用驼峰的方式将来在使用的时候很容易产生混淆
// 因为最终在列表组件那里使用的时候一般情况下是不区分大小写的
// 所以即使用了驼峰命名在下面也无法使用因为无法识别
// 而且组件名在内部进行注册的时候会对命名进行转换,这样会造成对使用过程造成混淆
// 推荐组件在命名的时候就进行羊肉串命名法
Vue.component('course-list',{
data(){
return{
selectedCourse:'',
}
},
// props是一个属性,接受老爹传过来的一些属性
// 定义方式有两种:一种是对象,一种是数组
// 如果属性是这样定义['courses'] ,那么就是希望老爹传过来的属性名就叫courses
// 将来在列表组件里就可以通过this.courses来访问传进来的参数了
// ['courses']这种方式对参数的校验没有好处,一般情况下用得更多的是对象形式
// 会用key的方式去命名,然后用type对其类型进行约束
props:{
courses:{
type:Array,
// 默认值为空数组,这样子对courses就会有提前的约束
default:[]
}
},
template:`
<!-- 条件渲染 -->
<!-- v-if 和 v-for最好不要放在一个标签上他们有优先级的不同会争抢 -->
<p v-if = "courses.length == 0 ">没有任何课程信息</p>
<div class="course-list" v-else>
<div
v-for="c in courses"
:key="c"
:class = "{active: selectedCourse === c}"
@click = "selectedCourse = c">
{{ c }}
</div>
</div>
`
})
// 模拟异步数据调用
function getCourses(){
return new Promise(resolve =>{
setTimeout(() => {
resolve(['定风波','web高级'])
})
})
}
// 1.创建vue实例
// 保存vue实例
const app = new Vue({
// 交代宿主是谁
el:"#app",
data: {
title: '课程:',
course:"",
// courses:[],
courses:["黄帝内经","仲景心法","针灸","伤寒","金匮"],
totalCount:0,
},
methods: {
addCourse() {
// 1.添加course到数组
this.courses.push(this.course)
// 2.清空course
this.course = ""
}
},
// 异步用async await
// 创建钩子
async created(){
// created执行时刻,组件实例已创建,由于未挂载dom不存在
const courses = await getCourses()
this.courses = courses
},
// mounted获取业务数据
// mounted时间点更靠后,除了创建之后还做了挂载,获取业务数据
// 挂载的实际操作是将前面所有的渲染函 数执行之后将虚拟DOM转换为真实DOM
// 也就是在mounted中可以访问到DOM元素了
// 其实vue实例被创建,挂载,渲染函数执行虚拟DOM转换为真实DOM都是很快的
// 异步数据获取选择mounted和created本质上没有什么差别
// 不用以为看到created界面会比较早 没有这个区别
// 因为我们访问数据所花销的时间远远大于初始化挂载的时间,没有什么实质上的区别
// mounted(){},
// computed是值变化了返回值
computed: {
total() {
// 计算属性是有缓存性的,如果值没有发生变化,则页面不会重新渲染
return this.courses.length+'门'
}
},
// watch 做某个值得监控,如果发生变化了则会执行这个函数做我想做的事情
// watch是值变化了执行这个函数
// 监控courses这个值的变化
// watch如果不加特别声明表示值变化之后才会执行,它一开始是不会执行的
// 默认情况下watch初始化时不执行想要watch立即执行 immediate为true。立即执行一次
// watch: {
// courses(newValue, oldValue) {
// this.totalCount = newValue.length +"门"
// }
// },
// 为了一开始就能执行要选带选项的watch vwatcher-options
watch: {
data: {
immediate: true,//立即执行 一次
// deep是当监控的数据是很复杂的数据的时候才使用如果是很浅就不需要用到deep
// deep: true,
handler(newValue, oldValue) {
}
}
},
})
</script>
</body>
</html>