第一步(仅第一次执行):全局安装@vue/cli
npm install -g @vue/cli
第二步:切换到你要创建项目的目录,然后使用命令创建项目
vue create 项目名称
第三步:启动项目
npm run server
备注:
如出现下载缓慢请配置npm淘宝镜像:npm config set registry https://registry.npm.taobao.org
Vue脚手架隐藏了所有webpack相关的配置,若想查看具体的webpakc配置,请执行:
vue inspect > output.js (但是output配置文件仅可以查看,并不能直接在上面修改)
脚手架文件结构
├── 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:包版本控制文件
vue.config.js配置文件
脚手架默认的配置文件是隐藏的,使用vue inspect > output.js可以查看到Vue脚手架的默认配置。
使用vue.config.js可以对脚手架进行个性化定制,详情见:https://cli.vuejs.org/zh
vue.config.js 文件 直接放入到根目录下,需要覆盖的配置写入文件即可,脚手架会自动进行合并,覆盖原来默认的配置
module.exports = {
pages: {
index: {
//入口
entry: 'src/main.js',
},
},
lintOnSave:false, //关闭语法检查
}
vue
总结:
1. ref属性被用来给元素或子组件注册引用信息(id的替代者)
2. 应用在html标签上获取的是真实DOM元素,应用在组件标签上是组件实例对象(vc)
3. 使用方式:
1. 打标识:```.....
```或 ``` ```
2. 获取:```this.$refs.xxx```
<template>
<div class="school">
<h1>{{msg}}</h1>
<h2>学生姓名:{{name}}</h2>
<h2>学生年龄:{{myAge}}</h2>
<button @click="addAge">增加年龄</button>
</div>
</template>
<script>
export default {
name:"School",
data(){
return {
msg:'我就一学生',
myAge:this.age
}
},
methods:{
addAge(){
this.myAge++
}
},
// 简单声明接收, 最常用
props:['name', 'age']
// 接收的同时对数据类型进行限制
// props:{
// name:String,
// age:Number
// }
// 接收的同时对数据:进行类型限制+默认值的指定+必要性的限制
// props:{
// name:{
// type:String,
// required:true // 设置必填项
// },
// age:Number,
// default:99 // 设置默认值
// }
}
</script>
props总结:
1. 功能:让组件接收外部传过来的数据
2. 传递数据:
3. 接收数据:
1. 第一种方式(只接收):props:['name']
2. 第二种方式(限制类型):props:{name:String}
3. 第三种方式(限制类型、限制必要性、指定默认值):
props:{
name:{
type:String, //类型
required:true, //必要性
default:'老王' //默认值
}
}
备注:props是只读的,Vue底层会监测你对props的修改,如果进行了修改,就会发出警告,若业务需求确实需要修改,那么请复制props的内容到data中一份,然后去修改data中的数据。
混入就是:如果两个或多个文件中有相同的代码,那么可以将相同的代码抽离出来,形成一个文件,在需要的地方引入这个文件,实现原本的功能
对于data以及methods等来说,如果混合文件中有,原文件中也有,那么就以原文件为主,
对于生命周期函数来说,如果混合文件和源原文件都有,那么全都要
一旦使用全局, vm以及各个vc上全部具备混合文件中所具备的特征
总结:
1. 功能:可以把多个组件共用的配置提取成一个混入对象
2. 使用方式:
第一步定义混合:
{
data(){....},
methods:{....}
}
第二步使用混入:
全局混入:Vue.mixin(xxx)
局部混入:mixins:['xxx']
编码时在不同组件中写的样式都会被汇总到一起,因此会产生一个问题是,如果两个组件中的样式名字相同,那么就会产生冲突,冲突后会按照先后引入组件的次序不同,后引入组件会覆盖前面引入组件的样式
注意:App.vue比较特殊,其内部写的style不但要自己使用,也要为别的组件使用,因此一般不用scoped修饰
1. 组件化编码流程:
(1).拆分静态组件:组件要按照功能点拆分,命名不要与html元素冲突。
(2).实现动态组件:考虑好数据的存放位置,数据是一个组件在用,还是一些组件在用:
1).一个组件在用:放在组件自身即可。
2). 一些组件在用:放在他们共同的父组件上(状态提升)。
(3).实现交互:从绑定事件开始。
2. props适用于:
(1).父组件 ==> 子组件 通信
(2).子组件 ==> 父组件 通信(要求父先给子一个函数)
3. 使用v-model时要切记:v-model绑定的值不能是props传过来的值,因为props是不可以修改的!
4. props传过来的若是对象类型的值,修改对象中的属性时Vue不会报错,但不推荐这样做。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>localStorage</title>
</head>
<body>
<h2>localStorage</h2>
<button onclick="saveData()">点击保存数据</button>
<button onclick="readData()">点击读取数据</button>
<button onclick="deleteData()">点击删除数据</button>
<button onclick="deleteAllData()">点击清空数据</button>
<script>
function saveData(){
let p = {name:'张三', age:18}
// window可省略
window.localStorage.setItem("msg","hello!!")
localStorage.setItem("msg2",666) // 即使是数字,保存的时候也会转成字符串
window.localStorage.setItem("person",JSON.stringify(p))
}
function readData(){
console.log(localStorage.getItem('msg'))
const result = localStorage.getItem("person") // 如果数据不存在,那么就返回null
console.log(JSON.parse(result)) // 数据不存在时,JSON.parse解析也为null
}
function deleteData(){
localStorage.removeItem("msg")
}
function deleteAllData(){
localStorage.clear()
}
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>sessionStorage</title>
</head>
<body>
<h2>sessionStorage</h2>
<button onclick="saveData()">点击保存数据</button>
<button onclick="readData()">点击读取数据</button>
<button onclick="deleteData()">点击删除数据</button>
<button onclick="deleteAllData()">点击清空数据</button>
<script>
function saveData(){
let p = {name:'张三', age:18}
// window可省略
window.sessionStorage.setItem("msg","hello!!")
sessionStorage.setItem("msg2",666) // 即使是数字,保存的时候也会转成字符串
window.sessionStorage.setItem("person",JSON.stringify(p))
}
function readData(){
console.log(sessionStorage.getItem('msg'))
const result = sessionStorage.getItem("person") // 如果数据不存在,那么就返回null
console.log(JSON.parse(result)) // 数据不存在时,JSON.parse解析也为null
}
function deleteData(){
sessionStorage.removeItem("msg")
}
function deleteAllData(){
sessionStorage.clear()
}
</script>
</body>
</html>
总结:
存储内容大小一般支持5MB左右(不同浏览器可能还不一样)
浏览器端通过 Window.sessionStorage 和 Window.localStorage 属性来实现本地存储机制。
相关API:
xxxxxStorage.setItem('key', 'value');
该方法接受一个键和值作为参数,会把键值对添加到存储中,如果键名存在,则更新其对应的值。
xxxxxStorage.getItem('person');
该方法接受一个键名作为参数,返回键名对应的值。
xxxxxStorage.removeItem('key');
该方法接受一个键名作为参数,并把该键名从存储中删除。
xxxxxStorage.clear()
该方法会清空存储中的所有数据。
备注:
xxxxxStorage.getItem(xxx)
如果xxx对应的value获取不到,那么getItem的返回值是null。JSON.parse(null)
的结果依然是null。使用@或者v-on时可直接在后面加once
<Student v-on:atguigu.once="getStudentName"/>
使用ref时将$on更换为$once
this.$refs.student.$once('atguigu',this.getStudentName)
一种组件间通信的方式,适用于:子组件 ===> 父组件
使用场景:A是父组件,B是子组件,B想给A传数据,那么就要在A中给B绑定自定义事件(事件的回调在A中)。
绑定自定义事件:
第一种方式,在父组件中:
或
第二种方式,在父组件中:
<Demo ref="demo"/>
......
mounted(){
this.$refs.xxx.$on('atguigu',this.test)
}
若想让自定义事件只能触发一次,可以使用once
修饰符,或$once
方法。
触发自定义事件:this.$emit('atguigu',数据)
解绑自定义事件this.$off('atguigu')
组件上也可以绑定原生DOM事件,需要使用native
修饰符。
注意:通过this.$refs.xxx.$on('atguigu',回调)
绑定自定义事件时,回调要么配置在methods中,要么用箭头函数,否则this指向会出问题!
一种组件间通信的方式,适用于任意组件间通信。
安装全局事件总线:
new Vue({
......
beforeCreate() {
Vue.prototype.$bus = this //安装全局事件总线,$bus就是当前应用的vm
},
......
})
使用事件总线:
接收数据:A组件想接收数据,则在A组件中给$bus绑定自定义事件,事件的回调留在A组件自身。
methods(){
demo(data){......}
}
......
mounted() {
this.$bus.$on('xxxx',this.demo)
}
提供数据:this.$bus.$emit('xxxx',数据)
最好在beforeDestroy钩子中,用$off去解绑当前组件所用到的事件。
一种组件间通信的方式,适用于任意组件间通信。
使用步骤:
安装pubsub:npm i pubsub-js
引入: import pubsub from 'pubsub-js'
接收数据:A组件想接收数据,则在A组件中订阅消息,订阅的回调留在A组件自身。
methods(){
demo(data){......}
}
......
mounted() {
this.pid = pubsub.subscribe('xxx',this.demo) //订阅消息
}
提供数据:pubsub.publish('xxx',数据)
最好在beforeDestroy钩子中,用PubSub.unsubscribe(pid)
去取消订阅。
案例:Student组件发送消息,School组件订阅消息
语法:this.$nextTick(回调函数)
作用:在下一次 DOM 更新结束后执行其指定的回调。
什么时候用:当改变数据后,要基于更新后的新DOM进行某些操作时,要在nextTick所指定的回调函数中执行。
当你修改了数据之后,vue帮你操作完dom之后,把真实的dom放入页面了,vue再帮忙调用nextTick函数
vue封装的动画要求写在transition标签中,以进场和离场动画为例,若不给transition标签指定名字hello,那么这两个动画的名字要固定的写为.v-enter-active和.v-leave-active,如果给transition指定name为hello,那么两个动画的名字为.hello-enter-active和.hello-leave-active,如果希望在开始时就有出场动画,就要在transition标签上加入:appear=“true”, 可简写为appear
<template>
<div>
<button @click="isShow = !isShow">显示/隐藏</button>
<transition name="hello" appear>
<h1 v-show="isShow">你好啊!</h1>
</transition>
</div>
</template>
<script>
export default {
name:'Test',
data() {
return {
isShow:true
}
},
}
</script>
<style scoped>
h1{
background-color: orange;
}
.hello-enter-active{
animation: atguigu 0.5s linear;
}
.hello-leave-active{
animation: atguigu 0.5s linear reverse;
}
@keyframes atguigu {
from{
transform: translateX(-100%);
}
to{
transform: translateX(0px);
}
}
</style>
vue封装transition时,元素进场或者离场时会给内部的元素添加两对共六个样式,分别是
1 进入的起点.hello-enter、2 离开的终点 .hello-leave-to
3 进入的全过程.hello-enter-active、 4 离开的全过程 .hello-leave-active
5 进入的终点.hello-enter-to、 6 离开的起点 .hello-leave
<template>
<div>
<button @click="isShow = !isShow">显示/隐藏</button>
<transition name="hello" appear>
<h1 v-show="isShow">你好啊!</h1>
</transition>
</div>
</template>
<script>
export default {
name:'Test',
data() {
return {
isShow:true
}
},
}
</script>
<style scoped>
h1{
background-color: orange;
}
/* 进入的起点、离开的终点 */
.hello-enter,.hello-leave-to{
transform: translateX(-100%);
}
.hello-enter-active,.hello-leave-active{
transition: 0.5s linear;
}
/* 进入的终点、离开的起点 */
.hello-enter-to,.hello-leave{
transform: translateX(0);
}
</style>
多个元素过渡要使用transition-group 标签,并且其内部的元素要有key值标识
<template>
<div>
<button @click="isShow = !isShow">显示/隐藏</button>
<transition-group name="hello" appear>
<h1 v-show="!isShow" key="1">你好啊!</h1>
<h1 v-show="isShow" key="2">尚硅谷!</h1>
</transition-group>
</div>
</template>
安装animate.css库,命令为 npm i animate.css
transition-group标签的名字要改为animate__animated animate__bounce
对其内部的标签配置进入和离开的动画,进入动画配置为enter-active-class=“animate__swing”,离开动画leave-active-class=“animate__backOutUp”
<template>
<div>
<button @click="isShow = !isShow">显示/隐藏</button>
<transition-group
appear
name="animate__animated animate__bounce"
enter-active-class="animate__swing"
leave-active-class="animate__backOutUp"
>
<h1 v-show="!isShow" key="1">你好啊!</h1>
<h1 v-show="isShow" key="2">尚硅谷!</h1>
</transition-group>
</div>
</template>
<script>
import 'animate.css'
export default {
name:'Test',
data() {
return {
isShow:true
}
},
}
</script>
<style scoped>
h1{
background-color: orange;
}
</style>
Vue封装的过度与动画总结
作用:在插入、更新或移除 DOM元素时,在合适的时候给元素添加样式类名。
图示:
写法:
准备好样式:
使用
包裹要过度的元素,并配置name属性:
你好啊!
备注:若有多个元素需要过度,则需要使用:
,且每个元素都要指定key
值。