Vue-cli(vue脚手架)上万字总结,超详细教程
Posted 猫四爷
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vue-cli(vue脚手架)上万字总结,超详细教程相关的知识,希望对你有一定的参考价值。
1、创建Vue脚手架
1.1、首先系统需要全局安装Vue脚手架
npm install -g @vue/cli
1.2、创建Vue脚手架工程
进入你想创建vue脚手架的目录,然后输入命令
vue create xxx项目名
需要注意的是工程名字不能大写,这里我们选择选择Vue2,敲下回车,那么vue将会为我们创建vue脚手架
显示如图所示说明创建成功
如图命令所示 我们进入myvue工程,执行命令
npm run serve
然后浏览器访问http://localhost:8080/
到这里 我们的vue脚手架工程就跑起来了,关闭为Ctrl+C
2、Vue脚手架的文件结构说明
├── node_modules
├── public
│ ├── favicon.ico: 页签图标
│ └── index.html: 主页面
├── src
│ ├── assets: 存放静态资源
│ │ └── logo.png
│ │── component: 存放组件
│ │ └── HelloWorld.vue
│ │── App.vue: 汇总所有组件
│ │── main.js: 入口文件
├── .gitignore: git版本管制忽略的配置
├── babel.config.js: babel的配置文件
├── package.json: 应用包配置文件
├── README.md: 应用描述文件
├── package-lock.json:包版本控制文件
3、修改默认配置
Vue-cli官网配置参考:https://cli.vuejs.org/zh/config/#publicpath
在工程根目录下创建文件vue.config.js
这里我们演示配置一下语法检查
3.1、配置前
会发现,默认语法检查是开启的,然后我们写了一个function没有被使用的话就会导致整个项目启动不了,所以在实际开发中,会带来很多障碍,所以我们将它关闭。
3.2、配置后
在vue.config.js中,加入以下代码
这时发现,默认配置已被修改,项目正常启动。
后序我们修改默认都可以结合官网的文档在该文件夹中配置
4、标签的 ref属性
因为在Vue里使用原生js拿去Dom元素不太好,所以就有了ref属性
4.1、ref属性的作用
1、被用来给元素或子组件注册引用信息(id的替代者)
2.应用在html标签上获取的是真是Dmo元素,应用在组件标签上的是组件实例对象(vc)
3.使用方法:
<h1 ref="xxx">......</h1> 或<组件ref="xxx"></组件>
获取:this.$refs.xxx
作用就相当于给一个表情加了个id=“xxx” 然后通过document.getElementById(“xxx”)的效果一样。
4.2、示范
编写一个School.vue组件,然后在App.vue中引入
我们访问网页 会发现,拿得到Dom元素,测试成功!
5、props配置
5.1、功能
让组件接收外部传递过来的数据,从而达到组件复用的目的
(1).传递数据
<Demo name="xxx"/>
(2).接收数据
第一种方式(只接收):
props:['name']
会发现以上会出现一个问题,如果我们需要传递18而显示19的话,那就需要做一下调整,因为默认传递过去的是一个字符串类型的数据,所以会造成字符串的拼接,所以我们得在传递的属性上面加 : 或者 v-bind ,他就会将表达式中的值正真的传递过去而不是以字符串的形式。
第二种方式(限制类型):
props
name:String
会发现传递字符串的话就会报错,一样通过:或者v-bind解决
第三种方式(限制类型、限制必要性、指定默认值)
props:
name:
type:String, //类型
required:true, //是否必传
default:'老王'//默认值
备注:props是只读的,不能修改,Vue底层会检测你对props的修改,如果进行了修改,就会发出警告,若业务需求确实需要修改,那么请复制props的内容到data中一份,然后去修改data中的数据。
如图所示:
6、mixin混入
6.1、功能
(1)示范准备
可以看到School和Student组件中有相同的方法
我们可以将其抽取出来达到复用的效果。
(2)创建一个js文件将相同的代码抽取出来,然后在Student和School组件中分别导入。
(3) 测试
会发现 抽取出来的方法生效了!!!
6.2、补充
不光上面演示的代码能在写在混合中,Vue中的声明的东西也都可以写在混合中,比如mounted、create,也包括自己定义的一些属性等方法等…混合中的数据最终都会和组件中的数据作一个整合
(1)、示范
一、我们在混合中加入mounted代码块
二、我们在混合文件中加入一些属性。
这里我们重新暴露一个代码块,然后代码块中声明name数据,然后School和Student中导入
测试
会发现使用name值成功了。注意:从示例中我们可以看到,如果混合和组件中有相同的组件和方法,会以组件中的为准。但是如果是mounted钩子函数,那么都要。并且混合中的钩子函数中的内容会先被执行。
mounted钩子函数测试
两个组件都引入,会发现混合中的钩子函数内容会先被执行
6.3、全局混入
上面那些都属于局部混入,导入某个组件内仅供该组件使用。这里介绍全局混入,导入一次可在所有组件中使用混入文件。
6.4、总结
功能:可以吧多个组件的共同配置提取成一个混入对象
使用方式:
第一步定义混合,例如:
data()....,
methods:....
第二部使用混入,例如:
(1).全局混入:Vue.minxin(xxx)
(2).局部混入:mixins:[xxx]
7、插件
7.1、功能
功能:用于增强Vue
本质:包含install方法的一个对象,install的第一个参数就是Vue,第二个以后的参数是插件使用者传递的数据。
定义插件:
对象.install=function(Vue,options)
//1.添加全局过滤器
Vue.filter(...)
//2.添加全局指令
Vue.directive(...)
//3.配置全局混入
Vue.minxin(...)
//4.添加实例方法
Vue.prototype.xxx=function()
.....
Vue.prototype.xxx=(...)=>
......
1、示范
先创建一个plugins.js文件,然后在文件中install方法中声明一些全局混入 或者方法等…
2、导入并且使用插件
在main.js 中导入并且在School组件中使用插件中定义的各种混入,方法,过滤器等…
3、测试
4、补充
在使用插件的时候 还可以传递参数
8、scoped样式
8.1、功能
作用:让样式在局部生效
写法:在style标签上加上scoped即可
<style scoped></style>
示范
在两个组件中都使用相同的样式
会发现样式会有冲突,所以我们在标签上加上 scoped
会发现,成功啦!!!
9、组件的自定义事件
9.1、props传递 方法
通过前面的知识我们可以知道,父组件在向子组件传递数据的时候可以在使用子组件时传递参数然后子组件中通过props属性接收参数,其实不光可以接受传递过来的属性,然后也可以接收传递过来的方法。然后子组件中调用方法,通过参数列表像父组件的方法中传递数据。
示范
需求:子组件中的数据传递到父组件中然后显示
(1)、准备一个student组件,然后父组件传递方法,子组件接收传递过来的方法
在子组件中调用父组件中的方法,则会回调父组件中传递的那个方法,参数则为子组件中传递的参数,那么父组件中就拿到子组件中传递过来的数据了。
(2)、测试
测试成功!!!
9.2、自定义事件(写法一)
上面的例子是通过props属性的方式实现的,我们还可以通过自定义事件的方式实现子组件 像父组件传递数据
示范
(1)、同样准备一个Student组件,然后在父组件中为子组件绑定事件和回调函数,然后在子组件触发父组件绑定的事件
触发事件用this.$emit('xxx',参数1,参数2...)
当然,参数想传递多少都是可以的。
(2)、测试
哈哈,成功啦!!!
9.3、自定义事件(写法二)
(1)、我们还可以通过ref的方式给指定的组件绑定事件
(2)、测试
成功啦!!!咋样,是不是很简单呢。
(3)、补充
既然能给组件绑定自定义事件,那么我们也可以解绑自定义事件,记住,给哪个组件绑定的事件就找那个组件触发去,同样,给哪个组件绑定的事件,就找哪个组件解绑
解绑指定的事件:this.$off('xxxxxx');
解绑多个事件:this.$off(['xxx','xxx']);
如果解绑所有事件,直接用: this.$off( );
解绑之后,那么这个事件就无法被触发了。
9.4、总结
组件的自定义事件
1、是一种组件间的通信方式,适用于子组件===>父组件
2、使用场景: A是父组件,B是子组件,B想给A传递数据,那么就要在A中给B绑定自定义事件和回调函数(回调函数在A中,参数则为B传递过来的)
3、绑定自定义事件:
- 第一种,在父组件中
<Demo @zidingyi="test"/>
或
<Demo v-on:zidingyi="test"/>
- 第二种,在父组件中
<Demo ref="demo"/>
......
mounted()
this.$refs.demo.$on('zidingyi',this.test)
3.若想让事件只出发一次,可以使用**once**修饰符,或**$once**方法。
- 触发自定义事件:
在子组件中
this.$emit('zidingyi',参数1,参数二...)
- 解绑自定义事件
this.$off('zidingyi')
- 组件也可以绑定原生DOM事件,需要使用native修饰符。
比如:
<Demo @click.native="xxxx"/>
10、全局事件总线
10.1、功能
从上面props和自定义事件例子中可以看到,他们适用于父组件与子组件或者子组件与父组件中的数据传递进行通信,那么如何实现任意两个组件中的通讯呢?
我们可以使用全局事件总线,全局事件总线并不是一个新的技术或者API,只是编码的经验而已。
(1)、首先得先有一个存放数据的地方,并且这个存放的地方必须是所有组件都能看到的。
通过图中我们可以看到,若所有的vc要拿数据 x (this.xxx),如果x在vc中找不到,那么就会去找VueComponent的原型对象中找,但是每一个组件都会有一个新的VueComponent,所以数据是不共享的,所以不能存在这里,那么就继续往上找到Vue,Vue的原型对象是所有的组件vm或vc都能看到的,所以存在Vue的原型对象中再合适不过了。
(2)、在Vue的原型对象中存入一个组件,那么这个组件就能被其他所有的组件绑定事件或者触发事件,从而达到通讯的目的
在main.js文件中,构建一个组件并且存入Vue的原型对象中
(3)、准备两个组件Student和School组件,然后在Student给Vue原型对象中的组件绑定事件,然后School中触发事件
(4)、测试
会发现,Student组件中触发了School中给公用组件绑定的方法并且拿到了数据。到这里就实现了兄弟组件中的通讯了,不再局限于父穿子,子传父了。
(5)补充
除了上面那种在main.js 中先构建一个组件然后再存入Vue的原型对象中的写法外还有一种比较标准的写法
将之前原型对象的k为x都改为$bus (起这名是因为bus也总线的意思,哈哈),测试
10.2、总结
全局事件总进线(GlobalEventBus)
-
一种组件间通信的方式,适用于任意组件间的通信。
-
在main.js中开启全局事件总线:
new Vue(
......
beforeCreate()
Vue.prototype.$bus=this //开启全局配置总线
)
- 使用事件总线:
3.1. 接收数据:A组件想要接收数据,则在A组件中给$bug绑定自定义事件,事件的回调留在A组件自身.
methods()
demo(date)
......
mounted()
this.$bus.$on('xxx',this.demo)
3.2. 提供数据
this.$bus.$emit('xxx',数据)
- 最好是在beforeDestory构子中,用$off去解绑当前组件所用到的事件。
11、消息的订阅与发布(pubsub.js)
11.1、介绍和使用步骤
除了上面全局事件总线的方式实现任意组件中的通讯,我们还可以借助 消息的订阅与发布(pubsub.js)实现任意的组件中的通讯。
使用步骤
- 安装pubsub:
npm i pubsub-js
- 在组件中引入:
import pubsub from 'pubsub-js'
- 接收数据:A组件中想要接收数据,则先在A组件中订阅消息,订阅的回调函数留在A组件自身
methods()
demo(msgName,参数1,参数2)......
,
......
mounted()
this.pid=pubsub.subscribe('xxx',this.demo)//订阅消息
,
beforeDestroy()
pubsub.unsubscribe(this.pid);
- 提供数据:
pubsub.publish('xxx',数据)
- 最好在beforeDestroy钩子中,用
pubsub.unsubscribe(pid)
取消订阅
11.2、示范
将之前给公用组件绑定自定义事件的方式替换成消息的订阅与发布
测试
测试成功啦!!!
12、$nextTick
12.1、功能
1、需求
如图所示,点击按钮,显示输入框并且输入框获取焦点
2、代码如图所示
3、测试
会发现根本就没有获取焦点
4、分析原因
在模版都没成功渲染的时候显然连Dom元素都没有获取到
5、解决
这里我们需要借助$nextTick解决
6、再次测试
会发现,成功显示输入框并且输入框也获取了焦点
12.2、总结
- 语法:
this.$nextTick(回调函数)
- 作用:在下一次DOM更新结束后执行指定的回调。
- 什么时候用:当改变数据后,要基于更新后的DOM进行某些操作时,要在nextTick所指定的回调函数中执行
13、animate.css
13.1、功能
animate.css包含了很多动画效果,这里我们试一下 显示/隐藏 的动画效果。有了它,我们不再需要自己手写C3动画样式了。非常nice
官网:点击进入首页
示范:
我们准备一个Test组件
1、安装animate.css :npm install animate.css
2、在组件中引入import 'animate.css'
3、设置显示和隐藏时的动画效果
我们在官网找到想要的样式
编写代码,appear为true时表示进入网页时组件第一次渲染就开始显示配置的效果
4、测试
很方便对不对,nice
14、反向代理
在解决ajax跨域问题时,后端人员经常会配置CORS解决跨域,但是作为前端,我们也可以通过自己的反向代理的方式解决跨域,这样就不用麻烦后端开发人员。
我们先准备两个接口,这里有使用node-js写的两个服务器。先下载运行起来
链接:https://pan.baidu.com/s/1Tbezmmg7vj_NpqxysYgCjg
提取码:1024
解压之后我们通过node运行
测试一下接口是否正常返回数据:
接下来我们写一个组件通过ajax的方式去请求接口,这里我们使用axios发起请求,当然得先安装axios:npm i axios
会发现,产生了跨域问题,接下来我们用以下两种方式解决跨域
14.1、方式一
官网配置说明:点击直达
在vue.config.js中加入配置
module.exports =
devServer:
proxy: 'http://localhost:4000'
重启脚手架项目,这样vue-cli就为你开启了一个8080的代理服务器去代理5000的服务器
重新发起请求
注意,如果我们8080的服务器上本身就有和5000相同的资源,代理服务器就不会把我们的请求转发给5000
14.2、方式二
会发现方式一存在两个问题,一是不能配置多个代理,二是不能灵活的控制请求是否转发。
编写vue.config.js具体规则
module.exports =
devServer:
proxy:
'/api1': // 匹配所有以 '/api1'开头的请求路径
target: 'http://localhost:5000',// 代理目标的基础路径
changeOrigin: true,
pathRewrite: '^/api1': ''
,
'/api2': // 匹配所有以 '/api2'开头的请求路径
target: 'http://localhost:5001',// 代理目标的基础路径
changeOrigin: true,
pathRewrite: '^/api2': ''
/*
changeOrigin设置为true时,服务器收到的请求头中的host为:localhost:5000
changeOrigin设置为false时,服务器收到的请求头中的host为:localhost:8080
changeOrigin默认值为true
*/
配置完我们需要重启服务器,我们将请求前缀加上/api1 或/api2,测试。
说明:
1.优点:可以配置多个代理,且可以灵活控制请求是否走代理
2.缺点:配置略微繁琐,请求资源时必须加前缀。
15、插槽
15.1、插槽的介绍和使用方式
1、作用:让父组件可以向子组件指定的位置插入html结构,也是一种组件间通信的方式,适用于父组件===>子组件。
2、分类:默认插槽、具名插槽、作用域插槽
3、使用方式:
- 默认插槽:
父组件中:
<xxx组件>
<div>html结构1</div>
</xxx组件>
子组件中:
<template>
<div>
<slot>插槽默认内容...</slot>
</div>
</template>
- 具名插槽
父组件中:
<xxx组件>
<template slot="center">
<div>html结构1</div>
</templat>
<template v-slot:footer>
<div>html结构2</div>
</templat>
<xxx组件>
子组件中:
<template>
<div>
<!--定义插槽-->
<slot name="center">插槽默认内容...</slot>
<slot name="footer">插槽默认内容</slot>
</div>
</template>
- 作用于插槽
1、理解:数据在组件自身,但数据生成的结构需要组件的使用者来决定,意思就是说,组件的使用者可以拿到组件中提前定义好的数据 然后在使用时根据自己的需求进行渲染。
2、具体编码
父组件中:
<xxx组件>
<!--或者scope换成slot-scope也行-->
<template scope="scopeData">
<!--生成的是ul列表>
<ul>
<li v-for="g in scopeData.games" :key="g" >g</li>
</ul>
</template>
</xxx组件>
子组件中:
<template>
<div>
<slot :games="games"></slot>
</div>
</template>
<script>
export default
name:'Category',
//数据在组件自身
data()
return
games:['红色警戒','穿越火线','劲舞团']
</script>
15.2、默认插槽
首先我们准备一Category1组件,在组件中定义一个插槽,然后使用这个组件时动态是插入html结构内容
测试成功、
15.3、具名插槽
默认插槽只能定义一个插槽,我们可以使用具名插槽定义多个插槽。我们准备一个Category2组件,在其中声明两个插槽
测试成功
15.4、作用域插槽
准备一个组件Category3,并定义插槽携带数据
测试成功
16、Vuex
16.1、vuex是什么?
-
概念:专门在Vue中实现集中式状态(数据)管理的一个Vue插件,在Vue应用中多个组件共享状态进行集中式管理(读/写),也是一种组件间通信方式,且适用于任意组件中的通信。(说白了就像后端中的redis可以用来多个应用中做数据共享)
-
Github地址:https://github.com/vuejs/vuex
16.2、什么时候使用Vuex
- 多个组件依赖于同一状态
- 多个组件的行为需要变更同一状态
16.3、Vuex原理图
现在看不懂没关系,我们逐个分析…
16.4、搭建Vuex环境
注意:在2022年的2月7日,vue3成为了默认版本,如果我们现在去执行npm i vue ,安装的直接就是vue3了,并且在vue3成为默认版本后。vuex更新到了4版本,所以我们如果执行npm i vuex,安装的是vuex4,而vue3版本只能在vue3版本中使用。
所以简单来说:
vue2中,要用vuex的3版本
vue3中,要用vuex的4版本
1、安装vuex并使用vuex插件
npm i vuex@3
2、为了让所有的vm和vc都拥有$store,所以我们需要配置store
在src文件夹下创建store文件夹和index.js文件
测试:
调整写法
index.js文件内容
//该文件用于创建VUex中最为核心的store
import Vue from 'vue'
//引入VUex
import Vuex from 'vuex'
Vue.use(Vuex)
//准备actions-用于响应组件中的动作
const actions=
//准备mutations-用于操作数据(state)
const mutations=
//准备state-用于存储数据
const state=
//创建并暴露store
export default new Vuex.Store(
actions,
mutations,
state,
)
这回,就没有报错了!!!
测试vm和vc中是否包含$store,我们直接在mounted钩子中打印this
成功啦,之后$store中那些强大的API我们就都可以在任意vm和vc中使用了。
16.5、求和案例
现在的需求:
16.5.1、纯Vue版本
16.5.2、Vuex版本
测试
16.6、Store中的getters配置项
1、概念:当state中的数据需要经过加工后再使用时,可以使用getters加工。他就和vue中的计算属性是一样的。
2、在./store/index.js中追加getters配置
......
const getters=
bigSum(state)
return state.sum*10
//创建并暴露store
export default new Vuex.Store(
......
getters
)
3、组件中读取数据:$store.getters.bigSum
4、示范
5、测试
完美。
16.7、mapState与mapGetters
16.7.1、mapState
1、会发现如过store中的state中有多个属性数据需要读取,就比较繁琐