Vue Cli官网:介绍 | Vue CLI
-
1.组件本质:一个自定义的标签
-
普通标签:只有html结构
-
组件:有html结构,css样式,js业务逻辑
-
-
2.组件作用:
复用
.把页面上可重用的部分
封装为组件
,从而方便项目的 开发 和 维护-
==一个组件相当于一个vue实例==
-
1.1-单文件组件
-
1.
单文件组件
: 把每一个组件放到一个独立的文件里-
好处:(1)便于维护 (2)便于复用
-
之前的学习中,当一个页面非常复杂的时候,我们需要把所有的结构都写在一个html中,非常的不便于维护
-
vue提供了一个专业的工具来帮我们将每一个组件放到一个独立的文件中管理
-
-
-
2.组件文件的后缀名是
.vue
文件 -
3.这个
.vue
文件主要由三个部分组成-
template
-
这里写组件的HTML结构模板
-
-
script
-
这里写组件的js业务逻辑。组件中的data、methods、计算属性,声明周期钩子等都写在这里
-
-
style
-
这里写组件的css样式
-
-
-
4.小提示 : 快速生成组件三大部分的快捷键:
<vue>
1.2-Vue cli工具安装
-
1.在任何位置打开终端小黑窗,输入命令(需要耐心等待5分钟左右)
-
npm install -g @vue/cli
-
2.如果安装失败,例如下图所示。解决方案如下
-
一般是由于网速较慢下载到一半导致中断,多试几次即可
-
(1)清除npm缓存,再重新安装
-
清除缓存命令:
npm cache clean -f
-
-
(2)检查有没有安装成功:
vue --version
02-vue cli脚手架使用教程
-
1.默认情况下,浏览器只能识别
html,css,js
后缀文件,无法识别.vue
后缀文件,所以要想让浏览器识别.vue
后缀文件,我们需要借助一些插件来帮我们将.vue
文件转成浏览器可以识别的html文件-
类似于我们以前学习的
less
,需要借助插件Easy LESS
先转成css
文件浏览器才可以识别
-
-
2.脚手架作用
-
(1)生成规范的vue项目目录
-
(2)底层基于webpack, 将后缀名为 .vue 的文件 编译成浏览器可以识别的 html文件
-
1.1-Vue脚手架安装流程
-
脚手架
:指的是
一个项目的目录结构
-
a. 我们以前写项目的时候,会把js文件放到js文件夹,css文件放到css文件夹,图片文件可能放在images文件夹,也可能放在imgs文件夹。第三方框架可能放在libs文件夹,也有可能放在js文件夹
-
尽管在vue之前,我们已经有这种项目文件夹命名规范的意识,但是无法避免会有一些差异
-
-
b. 有了脚手架之后,可以一键帮我们生成项目
统一
的目录结构,我们只需要写页面逻辑,而无需为了取名而烦恼。
-
-
vue-cli生成脚手架官网文档传送门:创建一个项目 | Vue CLI
-
1.创建vue项目 :
vue create 项目名称
-
a. 在哪里打开黑窗,就在哪里创建项目
-
例如,我这里cd到day06文件夹,所以就在这个文件夹创建vue项目
-
-
b.项目名称不要有中文,也不要有大写字母
-
错误名称: vue create 组件学习
-
错误名称: vue create Components
-
正确名称: vue create 01-components
-
-
c.最好使用系统自带终端打开,
千万不要使用git bash!
-
2.选择默认配置
-
第一次比较久,需要耐心等待
3.成功提示
4.运行项目的命令的位置是项目根目录,与package.json
文件同级
-
npm run serve
-
终端开启之后不要关闭,此时我们修改代码无需重新运行,浏览器会自动刷新
1.2-脚手架文件目录介绍
vuecil-demo # 项目目录
├── node_modules # 项目依赖的第三方包
├── public # 静态文件目录
├── favicon.ico# 浏览器小图标
└── index.html # 单页面的html文件(网站首页,vue会帮我们配置好,使用较少)
├── src # 业务文件夹(项目核心文件夹,我们写的项目代码都放在这个文件夹里面)
├── assets # 静态资源(一般项目图片、css都放在这里)
└── logo.png # vue的logo图片(没啥用,vue打广告的,可删除)
├── components # 组件目录一般我们写的组件都放在这里)
└── HelloWorld.vue # 欢迎页面vue代码文件 (打广告的,可删除)
├── App.vue # 整个应用的根组件(网站首页index.htm默认会渲染这个根组件)
└── main.js # 入口js文件(入口文件,vue实例的创建,根组件的挂载都是在这里完成)
├── .gitignore # git提交忽略配置(默认已经帮我们配置好 )
├── babel.config.js # babel配置(ES6转换ES5工具,一般不用管)
├── package.json # 依赖包列表
├── README.md # 项目说明(一般公司代码规范,人员组成之类的可以写在这里)
└── package-lock.json # 项目包版本锁定和缓存地址
└── vue.config.js # 项目webpack配置项
项目文件夹
-
node_modules : 第三方包管理文件夹
-
public : 网站主页和图标(使用较少)
-
index.html : 网站首页,vue会帮我们配置好,使用较少
-
faviicon.ico:网站图标
-
-
src
: 项目核心文件夹
,我们写的项目代码都放在这个文件夹里面-
assets : 静态资源 (一般项目图片、css都放在这里)
-
components:组件 (一般我们写的组件都放在这里)
-
App.vue : 根组件 (网站首页index.htm默认会渲染这个根组件)
-
main.js : 入口文件 (入口文件,vue实例的创建,根组件的挂载都是在这里完成)
-
-
.gitignore : git忽略文件,默认已经帮我们配置好
-
.babel.configs : ES6转换ES5工具
-
.package-lock.json:记录项目第三方包下载信息
-
.package.json:记录项目第三方包版本信息
-
README.md :项目说明(一般公司代码规范,人员组成之类的可以写在这里)
-
vue.config.js 项目webpack配置项
main.js 入口文件说明
//1.导入vue框架
import Vue from 'vue'
//2.导入App.vue根组件
import App from './App.vue'
//3.控制台打印提示开关
Vue.config.productionTip = false
//4.创建vue实例
new Vue({
//默认渲染App.vue组件(根组件)
render: h => h(App),
}).$mount('#app')//设置挂载点,相当于 el:'#app'
1.3-脚手架准备工作:清理欢迎界面与自定义配置
1.关闭eslint插件(推荐)
-
eslint是一个插件, 内置在脚手架项目里配置好了, 运行时检查你的代码风格
-
这个插件对代码格式要求很严格, 比如不能随便写分号、代码缩进要规范等等。 对初学者不是很友好,建议关闭
module.exports = {
// 关闭eslint代码检查
lintOnSave: false
}
-
2.修改服务器端口号(可选)
脚手架内置的webpack, 配置文件叫vue.config.js
module.exports = {
devServer: { // 自定义服务配置
host:'127.0.0.1',
open: true, // 自动打开浏览器
port: 3000
}
}
3.删除conponents文件夹下的默认介绍组件, 删除App.vue中所有代码
1.2-注册局部组件
注册局部组件
1.导入局部组件 : 在scrip标签中导入
import 组件名 from '组件路径'
2.挂载组件 : 在export default里面写一个属性components
export default {
components: {
"标签名": 组件名
}
}
使用局部组件 : 像标签一样使用即可,组件可以理解为一个自定义标签
<组件名></组件名>
<!-- 1.html标签: 放模板(html结构)
细节:组件中的最外层父元素只能有一个,不能添加两个平级父元素
正确: <div> <div></div> <div>
错误: <div></div> <div></div>
-->
<template>
<div>
<h1>Hello!</h1>
<div class="box">{{ msg }}</div>
<button @click="doClick">点我试试</button>
<!-- 使用组件: 像标签一样使用即可(可以把组件看成是一个vue自定义标签) -->
<local01></local01>
<local02></local02>
</div>
</template>
<!-- 2.js代码,写组件js业务逻 -->
<script>
/* 局部组件使用流程
1.导入局部组件 : 在scrip标签中导入
import 组件名 from '组件路径'
2.挂载组件 : 在export default里面写一个属性components
export default {
components: {
"标签名": 组件名
}
}
*/
import local01 from './components/local01.vue'
import local02 from './components/local02.vue'
export default {
//之前vue实例的代码写在这里:可以放data,methods,计算属性、侦听器等
//注意哟:组件里面的data是一个函数,返回值就是之前vue实例中的data对象
data(){
return{
msg:'我是坤坤!'
}
},
methods: {
doClick(){
alert('我被点击了')
}
},
components:{
/* 这里使用了对象解构赋值,相当于 local01 : local01
如果写成 aaa : local01 , 那么在模板中 <aaa> 标签就表示组件
这里不建议大家修改,避免取的别名和其他组件名冲突
*/
local01,// local01 : local01
local02
}
}
</script>
<!-- 3.css:写组件样式 -->
<style>
.box{
width: 100px;
height: 100px;
background-color: red;
}
</style>
1.3-注册全局组件
-
官方文档:组件注册 — Vue.js
/* 注册全局组件 : 在main.js文件中
1.导入组件 import 组件名 from '组件文件路径'
2.注册全局组件 Vue.component('标签名', 组件名)
一旦注册全局组件之后,可以在任何组件直接使用,并且不需要导入和挂载 */
-
局部组件和全局组件区别
-
局部组件 : 在哪里用就在哪里注册 (用一次,注册一次)
-
如果一个组件只在一两个页面用到,就可以局部注册(例如商品详情)
-
-
全局组件 : 在main.js中注册,任何地方都能直接使用 (注册一次,终生可用)
-
如果一个组件需要在很多个页面用到,就可以全局注册(例如,弹框、自定义按钮这些)
-
-
//1.导入vue框架
import Vue from 'vue'
//2.导入App.vue根组件
import App from './App.vue'
//3.控制台打印提示开关
Vue.config.productionTip = false
/* 注册全局组件 : 在main.js文件中
1.导入组件
import 组件名 from '组件文件路径'
2.注册全局组件
Vue.component('标签名', 组件名)
一旦注册全局组件之后,可以在任何组件直接使用,并且不需要导入和挂载
*/
//1.导入组件
import global from './components/global.vue'
//2.注册全局组件
//参数1 : 组件的id (id叫什么,自定义标签名就叫什么)
//参数2 : 组件
Vue.component('test', global)
//4.创建vue实例
new Vue({
//默认渲染App.vue组件(根组件)
render: h => h(App),
}).$mount('#app')//设置挂载点,相当于 el:'#app'
1.4-组件CSS作用域scoped属性介绍
-
scoped属性官方文档:scoped
-
关于scoped介绍: 为组件设置Scoped必要
<style scoped>
/*
1.默认情况下,如果父组件与子组件有相同的css选择器样式,则父组件的样式会覆盖子组件的样式
2.scoped属性作用 : 如果子组件与父组件有相同样式,则优先加载子组件自身的。如果没有则加载父组件的
*/
/* css */
.box{
width: 100px;
height: 100px;
background-color: red;
}
</style>
知识点验收
-
scoped作用是什么?
-
专业术语: 子组件的css作用域
-
说人话: 避免子组件选择器样式被父组件覆盖
-
-
scoped原理是什么?
-
属性选择器
:本质是给子组件添加一个唯一的
行内自定义属性,然后通过[data-v-xxx]
属性选择器避免样式被父组件覆盖
-
1.1-父组件传值子组件:props
使用步骤
第一步:给子组件添加props属性
(与data平级)
作用:类似于声明变量,定义要接收的属性名
第二组:在父组件中使用行内自定义 attribute传值
<子组件 属性名="属性值"></子组件>
注意点: prop中的属性不能有大写字母,不要使用驼峰命名。建议使用
-
作为分隔符。原因:行内自定义属性attribute不支持大写
子组件
<template>
<div class="son">
<h3>我是子组件</h3>
<!-- 使用时,像使用data中属性一样使用props中的属性
(1)在js中使用props属性需要通过: this.属性名 。 行内可以省略this
(2)属性名如果有-,则需要转成驼峰。(因为行内自定义属性不支持大写)
-->
<h4>商品名称:{{ goodName }}</h4>
<h4>商品价格:{{ goodPrice }}</h4>
</div>
</template>
<script>
export default {
name:'goods',
//子组件中声明props : 相当于声明属性
props:["good-name","good-price"],
data(){
return{
}
}
}
</script>
<style scoped>
.son{
border: 1px solid red;
}
</style>
父组件
<template>
<div id="app">
<h1>我是父组件</h1>
<!-- 父组件:通过行内自定义属性 来 传递数据给 props -->
<goods good-name="苹果手机" good-price="5888"></goods>
<goods good-name="小米手机" good-price="1888"></goods>
</div>
</template>
<script>
//导入局部组件
import goods from './goods.vue'
export default {
data(){
return{
}
},
components:{
goods
}
}
</script>
<style>
#app{
border: 1px solid #000;
}
</style>
知识点验收
注意:
-
props
的作用是什么?-
父
->子
传数据
-
-
props
定义的位置和data
同级吗?-
是
-
-
props
定义的格式是什么?-
['属性1','属性2']
-
1.2-组件传值练习:加载商品列表
-
实际开发中,
父组件
的数据都不是写死的,而是来源于服务器。将服务器返回的数据传递给子组件
-
父组件App.vue
-
1.组件本质相当于一个自定义标签,也支持
v-for
列表渲染 -
2.组件语法要求很严格:
v-for
必须要添加key值, 而且index如果没有使用则不能写,否则会报错(用不上index,就强制不写。需要使用index的时候再写) -
3.
父组件
通过props
来传值的时候,如果在行内想要访问data中的数据,需要使用v-bind
指令
-
<template>
<div id="app">
<h1>我是父组件</h1>
<!-- 父组件:通过行内自定义属性 来 传递数据给 props -->
<goods v-for="(item) in list" :key="item.id" :good-name="item.name" :good-price="item.price" :good-id="item.id"></goods>
</div>
</template>
<script>
//导入局部组件
import goods from './goods.vue'
export default {
data(){
return{
//模拟服务器返回商品列表
list:[
{
name:'苹果手机',
price:5888,
id:1
},
{
name:'小米手机',
price:1888,
id:2
},
{
name:'华为手机',
price:1888,
id:3
},
]
}
},
components:{
goods
},
}
</script>
<style>
#app{
border: 1px solid #000;
}
</style>
子组件goods.vue:代码不变
<template>
<div class="son">
<h3>我是子组件</h3>
<!-- 使用时,像使用data中属性一样使用props中的属性
(1)在js中使用props属性需要通过: this.属性名 。 行内可以省略this
(2)属性名如果有-,则需要转成驼峰。(因为行内自定义属性不支持大写)
-->
<h4>商品名称:{{ goodName }}</h4>
<h4>商品名称:{{ goodPrice }}</h4>
<h4>商品编号:{{ goodId }}</h4>
<button>点我砍一刀</button>
</div>
</template>
<script>
export default {
name:'goods',
//子组件中声明props : 相当于声明属性
props:["good-name","good-price","good-id"],
data(){
return{
}
}
}
</script>
<style scoped>
.son{
border: 1px solid red;
}
</style>