小概
本章的学习内容:vue单文件组件结构介绍,vue注册局部组件(注册全局组件),slot组件插槽,父子组件传值(比较重要),vue-cli脚手架的使用
(vue项目结构介绍,ui页面创建项目)。本章还是干货还是比较多的,得好好记好好学,加油!
1. 单文件组件
.vue文件
.vue文件,称为单文件组件,是Vue.js自定义的一种文件格式,一个.vue文件就是一个单独的组件,在文件内封装了组件相关的代码:html、css、js
<template>
<!-- 组件的html结构 : 一个组件只能有一个根元素
正确: <div><div></div></div>
错误: <div></div><div></div>
-->
<!-- 1.html结构 -->
<div class="box">
<h1>我是组件</h1>
</div>
</template>
<script>
/* 2.js业务逻辑 */
export default {
/* 以前vue实例的成员都写到这里 : data,methods,computed,filters,生命周期钩子
注意点: 组件中的data是一个函数,这个函数返回值就是以前的data对象
*/
data(){
return {
msg:''
}
}
}
</script>
<style>
/* 3.css样式 */
</style>
注意:template页面内容中只能有一个根元素,
组件中data数据以函数返回值的形式存放,原因:.vue组件有可能在很多个地方复用,而以函数返回值的形式使用data中数据,每个组件实例可以维护一份被返回对象的独立拷贝,组件中的数据相互不受影响,它们各自维护各自内部的data。
export default:es6导出默认接口,后面会详写。
2. 注册局部组件
组件:组件就是页面的一部分的结构,包含html结构,css样式,js行为,组件可以在多个地方复用,解决了代码复用
模块:.js文件
注册局部组件:在一个组件(父组件)中使用另一个组件(子组件)
- 导入组件:import 组件名 from ‘组件地址’(建议组件名和文件名一致)
- 挂载组件:在export default对象中通过components:{标签名:组件名}
<template>
<div class="box">
<h1>我是父组件</h1>
<!-- 子组件:组件本质可以理解为就是一个自定义标签 -->
<local></local>
<goods></goods> //goods标签就是引入的组件
<goods></goods>
</div>
</template>
<script>
//1.导入子组件
import goods from './goods.vue'
import local from './local.vue'
export default {
data(){
return {
}
},
//2.挂载组件
components:{
/* 这里其实是ES6的解构赋值: goods:goods */
goods,
local
},
//事件处理函数
methods: {
},
//计算属性
computed:{
}
}
</script>
<style>
</style>
组件本质可以理解为就是一个自定义标签
组件export default中的name属性,添加一个唯一标识符方便调试(组件name不能重复,一般与组件名一致,不要用中文命名)
name:‘goods’
scoped作用
默认情况下,如果子组件的选择器与父组件选择器一致。 则子组件样式会被父组件覆盖。(先渲染子,后渲染父)
解决方法:在子组件style标签内加 scoped设置子组件作用域
如果子组件与父组件样式相同,则优先加载子组件自身样式,没有则加载父组件。
原理:给子组件添加一个行内自定义属性 data-v-xxx,使用属性选择器
解决问题:子组件与父组件css选择器一致,样式会被父组件覆盖
<style scoped>
.box{
border: 1px solid red;
width: 500px;
height: 300px;
}
</style>
3. slot组件插槽
上面说了父组件中使用子组件(已标签的形式引入)
作用:父组件要往子组件插入不同的html结构就可以用slot实现
官方原话:用于标记往哪个具名插槽中插入子组件内容
父组件
<template>
<div class="box">
<h2>我是父组件</h2>
<!-- 子组件:标签 -->
<goods>
<!-- 传递插槽:父组件传 -->
<button>
<a href="http://www.itheima.com">点我购买</a>
</button>
</goods>
<!-- 子组件:标签名 -->
<goods>
<button disabled>已卖完</button>
</goods>
<!-- 子组件:标签名 -->
<goods></goods>
</div>
</template>
子组件
<template>
<div class="box">
<h3>我是子组件</h3>
<p>商品名称</p>
<p>商品价格</p>
<p>商品编号</p>
<!-- 插槽: 父组件传递结构给子组件 -->
<slot><a href="">我是插槽默认内容</a></slot>
</div>
</template>
子组件的slot标签中的内容为默认内容,如果父组件没传内容,就好显示默认内容
4. 父子组件之间的传值
4.1 父传子
问:如果需要发起ajax请求获取数据,是在父组件发起请求得到数据并传递给子组件好?还是在子组件发起请求好?
:建议在父组件发起,父传子,原因:子组件有可能在父组件被复用多次,如果在子组件发起ajax请求获得数据,每引用一次就需要发起一次ajax请求,耗时耗性能。
父传子传值是
单向数据流
父传子:父组件页面修改数据,子组件接收的数据也会随之改变;但是如果在子页面直接修改传过来的数据,父组件对应的数据不会更新,则会出现数据差异并报错。
父组件:在子组件标签内 用自定义属性=“需要传递的数据”(可以用v-bind 得到data中的数据)
子组件:在export default{}中用props
:[ “接收数据1”,“接收数据2”,“接收数据3”…]。使用props中的数据就像使用data中数据一样
2.1.行内使用,则需要省略this
2.2方法中使用,则需要通过 this.属性名
2.3.如果props中属性名有-,用的时候需要转成驼峰
4.2 子传父
通过
$emit() 事件通知
实现子组件传递参数给父组件
上面说了,父传子是数据单向传递,也就是父组件可以随意修改传递的数据,子组件会同步更新;但是子组件却不能随意直接修改传递过来的数据,虽然子组件上的数据会改变,但是父组件的数据不会改变。
需求:子组件上有一个按钮点一下,修改数据goodsPirce -1。(数据是来自父组件传递)
-如果直接在子组件写点击事件 this.goodsPrice–
-正确做法:子组件用$emit('事件名',参数1,参数2....)
传递需要修改商品的id和修改的数量(上图)
5. vue-cli(脚手架)的使用
vue cli cmd 指令创建项目
创建vue项目 :vue create 项目名称
-项目文件介绍
通过vue ui 创建项目
注意:eslint语法检测,新手不建议使用这个,太严格了
组件全局挂载
上面我们讲了注册局部组件,也就那个父组件要用 则在该组件页import 组件名 from ‘组件地址’,然后在该页面components:{标签名:组件名} 挂载组件
如果一个组件在很多个页面都需要用到,一个一个页面的注册太麻烦,我们可以将该组件注册成全局组件。
- 1.项目的main.js文件将该组件挂载为全局组件
//导入vue框架
import Vue from 'vue'
// 导入根组件
import App from './App.vue'
/*
1.局部组件 : 在什么地方使用,就在什么地方导入(用一次就需要导入一次)
1.1 在要用的父组件中导入: import 组件名 from '组件路径'
1.2 在要用的父组件中注册: components:{ 组件名 }
2.全局组件 : 在main.js中导入一次,之后任何组件都可以使用(整个项目只需要导入一次)
1.1 在main.js中导入 :import 组件名 from '组件路径'
1.2 在Vue构造函数原型中注册: Vue.component('标签名',组件)
*/
//(1)导入全局组件
import global from './components/global.vue'
//(2)注册到Vue构造函数原型中
Vue.component('global',global)
// 控制台打印
Vue.config.productionTip = false
// 创建vue实例,将根组件App.vue挂载到index.html的#app上
new Vue({
render: h => h(App)
}).$mount('#app')
- 2.在需要使用的页面 直接页面的template中使用组件(自定义标签的形式)
总结
关于vue 全家桶,前面我们学了axios,本章学习了vue cli,接下来还会学习vue router 和VueX。今天学习的父子组件传值比较重要,后续还会更新兄弟组件之间的传值。不多说了,兄弟们加油肝!