首先,要进行脚手架的安装
1)在安装之前,我们需要先安装vpm, 所以要先安装一个node js(这个软件的安装很简单,无脑下一步就行)
2)然后有了vpm之后,我们配置一个淘宝镜像,有助于我们对脚手架的下载
npm config set registry https://registry.npm.taobao.org
3)安装vue脚手架
npm install -g @vue/cli
等待他安装完成,然后重新打开小黑窗口,输入vue 如果能够看到类似的界面,就表示安装成功了
接下来,我们在桌面创建一个vue-test,做法是:在小黑窗口转换到桌面,然后执行 vue create vue-test
然后他就会进行加载,最后到如下界面,就证明成功了
我们可以用上面的地址进行访问,如果是同个局域网的同事,就可以通过第二个地址进行访问
实现一个小案例如下:(本来是想呈现出school、student的组件,可是一直显示不出来。。。)
我们创建一个gubi组件,然后让其在APP.vue中引入,然后呈现

<template> <div class="demo"> <h4>{{name}}</h4> </div> </template> <script> export default{ data(){ return { name:'gubi' } } } </script> <style> </style>

<template> <div> <h3>hh</h3> <gubi></gubi> </div> </template> <script> import gubi from './components/gubi.vue' export default{ components:{ gubi } } </script> <style> </style>
脚手架文件结构
配置文件
使用 vue inspect >output.js 可以查看到Vue脚手架的默认配置
使用Vue.config.js可以对脚手架进行个性化定制
ref
1)被用来给元素或子组件注册引用信息 (id的替代者)
2)应用在html标签上获取的是真实DOM元素,应用在组件标签上是组件实例对象(vc)
3)使用方式 <h1 ref=“xxx”></h1> <School ref="xxx"></School>
在原生html中,如果我们要获取某个标签,通常是 ==》 【document.getElementById】 这种写法
但vue并不推荐直接操作dom对象,他给了【ref】这个属性,我们给想要过去的标签配上这个属性,就可以在控制台上查询到
props
功能:让组件接收外部传过来的数据,我们可以通过props来自定义表情前内的属性,如下框
使用props的三种方式如下: 第一种只接收 第二种限制数据类型 第三种限制类型,限制必要性,指定默认值

//第一种做法
//props:['name','age','sex']
//第二种做法,限制了数据类型
/* props:{
name:String,
age:Number,
sex:String
} */
methods:{
updateAge(){
this.myAge++
}
},
props:{
name:{
type:String,
required:true
},
age:{
type:Number,
default:99
},
sex:{
type:String,
required:true
}
}
备注:
props是只读的,Vue底层会监测你对props的修改,如果进行了修改,就会发出警告,若业务需求确实需要修改,那么请复制props的内容到data中(但是要换个名字),然后去修改data中的数据,代码如下:

<template> <div> <h4>{{name}}</h4> <h4>{{myAge}}</h4> <h4>{{sex}}</h4> <button @click="updateAge">修改年龄</button> <!-- 修改数据--> </div> </template> <script> export default{ data(){ return { //name:'gubi', //age:'18', //sex:'男' myAge:this.age } }, //第一种做法 //props:['name','age','sex'] //第二种做法,限制了数据类型 /* props:{ name:String, age:Number, sex:String } */ methods:{ //修改数据的方法 updateAge(){ this.myAge++ } }, props:{ name:{ type:String, required:true }, age:{ type:Number, default:99 }, sex:{ type:String, required:true } } } </script> <style> </style>
mixin
功能:可以把多个组件共用的配置提取成一个混入对象
使用方式:
第一步定义混合,例如: 其中maxin是名字,即我们其他地方调用时所需要输入的内容
export const maxin = { methods:{ showName(){ alert(this.name) } }, }
第二步使用
1)全局混入
2)局部混入
插件
功能:用于增强Vue
本质:包含install方法的一个对象,install的第一个参数是Vue,第二个以后的参数是插件使用者传递的数据
定义插件: (创建一个js文件,名字随意)
使用插件(在main.js进行引入)
scoped 样式
我们在一个组件(比如App)中引入其他组件时,他们的样式是放在App的style之下,也就是说,会有重复冲突问题,一个组件中的样式可能应用在另一个组件中,如下
我只是在gubi当中定义了样式,然后在mm中引用了相同class标签,然后就呈现了出来,所以 scoped的作用就是,让每一个组件的样式只服务于自己
作用:让样式在局部生效,防止冲突
写法:<style scoped>
总结TodoList案例
1.组件化i编码
1)拆分静态组件 组件要按照功能点拆分,命名不要于html元素冲突
2)实现动态组件 考虑好数据的存放位置,数据是一个组件在用,还是一些组件在用
1)一个组件在用,放在组件自身即可
2)一些组件在用,放在他们共用的父组件上
3)实现交互 从绑定事件开始
2.props适用于:
1)父组件 ==> 子组件 通信
2)子组件 ==> 父组件 通信 (要求父先给子一个函数)
3.使用v-model时要切记: v-model绑定的值不能时props传过来的值,因为props时不可以被修改的
4.props传过来的若是对象类型的值,修改对象中的属性时Vue不会报错,但不推荐这样做
WebStorage
存储内容大小一般在5MB左右
浏览器通过Window.sessionStorage和Window.loaclStorage属性来实现本地存储机制
相关API
备注
1)SessionStorage 存储的内容会随着浏览器窗口关闭而消失
2)LocalStorage存储的内容,需要手动清除才会消失
3)xxxxStorage.getItem(xxx) 如果xxx对应的value获取不到,那么getItem的返回值是null
4)JSON.parse(null)的结果依然是null
组件的自定义事件
1)一种组件间通信的方式 适用于:子组件==>父组件
2)使用场景:A是父组件,B是子组件,B想给A传数据,那么就要在A中给B绑定自定义事件(事件的回调在A中)
3)绑定自定义事件
1)第一种方式:在父组件中, <Demo @atguigu="test"/> 或 <Demo v-on:atguigu="test"/>
2)第二种方式:在父组件中:大致如下的代码

<Student ref="student"></Student> mounted(){ this.$refs.student.$on('atguigu',this.getStudentName) }
3)若想让自定义事件只能触发一次,可以使用once修饰符,或者$once方法
4)触发自定义事件:this.$emit('atguigu',数据)
5)解绑自定义事件:this.$off('atguigu')
6)组件上也可以绑定原生DOM事件,需要使用native修饰符
全局事件总线
1)一种组件间通信的方式,适用于任意组件通信
2)安装全局事件总线: (在main.js中给生命周期钩子的【beforeCreate()】创建全局总线)

new Vue({
el:'#app',
render: h => h(App),
//创建事件总线管理对象的第二种方式
beforeCreate(){
Vue.prototype.$bus = this
},
})
3)使用,若某个组件想要跟其他组件进行事件绑定,则可以大致如下例子
若其他组件想要用到该事件,则可以用一个button绑定事件,然后大致如下:
4)因为全局总线可能会绑定很多的事件,如果没有及时的销毁,会造成浪费,所以,要进行解绑
消息订阅与发布
首先,需要下载一个库(我这里下载的是pubsub-js)(竟然下载失败了。。没有进行实操)
使用步骤如下
1)引入
2)创建方创建事件
3)接收方事件
nextTick
1)语法: this.$nextTick(回调函数)
2)作用: 在下一次DOM更新结束后执行其指定的回调
3)什么时候用:当改变数据后,要基于更新后的新DOM进行某些操作时,要在nextTick所指定的回调函数中执行
过度与动画
1)准备好样式
元素进入的样式
1)v-enter 进入的起点
2)v-enter-active 进入过程中
3)v-enter-to 进入的终点
元素离开的样式
1)v-leave 离开的起点
2)v-leave-active 离开过程中
3)v-leave-to 离开的终点
2)使用 transition 包裹要过度的元素,并且配置name属性,例子如下:

<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>
插槽
1)作用:让父组件可以向子组件指定位置插入html结构,也是一种组件间通信的方式,适用于 父组件 ==> 子组件
2)分类:默认插槽、具名插槽,作用域插槽
3)使用方式
1)默认插槽,就是没有增加插槽name属性的插槽
我们使用时,只需要将我们想要存放的位置上放上一个插槽标签,然后在父组件定义并且使用即可
子组件

<template> <div class="category"> <h3>{{title}}分类</h3> <slot>我是插槽填放位置,当使用者传递具体结构时,我会出现</slot> <!-- <ul> <li v-for="(item,index) in listData" :key="index">{{item}}</li> </ul> --> </div> </template> <script> export default{ name:'Category', props:['title'] } </script> <style> .category{ background-color: #006666; width: 200px; height: 300px; } </style>
父组件

<template> <div class="cantainer"> <Category title="美食"> <h3>美食插槽</h3> </Category> <Category title="游戏"> <ul> <li v-for="(g,index) in games" :key="index">{{g}}</li> </ul> </Category> <Category title="电影"> <h3>电影插槽</h3> </Category> </div> </template> <script> import Category from './components/Category.vue' export default { name:'App', components:{Category}, data(){ return{ foods:['火锅','烧烤','小龙虾','牛排'], games:['红色警戒','穿越火线','劲舞团','超级玛丽'], films:['《教父》','《拆弹专家》','《你好,李焕英》','《尚硅谷》'] } }, } </script> <style> .cantainer{ display: flex; justify-content: space-around; } h3{ text-align: center; background-color: orange; } </style>
2)具名插槽,当我们所想要插入的插槽数量不是一个的时候,我们就需要给对应的插槽附上name,才能做到精准调用
子组件

<template> <div class="category"> <h3>{{title}}分类</h3> <slot name="center">我是插槽填放位置,当使用者传递具体结构时,我会出现</slot> <slot name="footer">我是插槽填放位置,当使用者传递具体结构时,我会出现</slot> <!-- <ul> <li v-for="(item,index) in listData" :key="index">{{item}}</li> </ul> --> </div> </template> <script> export default{ name:'Category', props:['title'] } </script> <style> .category{ background-color: #006666; width: 200px; height: 300px; } </style>
父组件

<template> <div class="cantainer"> <Category title="美食"> <h3 slot="center">美食插槽</h3> </Category> <Category title="游戏"> <ul slot="center"> <li v-for="(g,index) in games" :key="index">{{g}}</li> </ul> <div class="foot" slot="footer"> <a>单机游戏</a> <a>网络游戏</a> </div> </Category> <Category title="电影"> <h3 slot="center">电影插槽</h3> <div class="foot" slot="footer"> <a>经典</a> <a>热门</a> <a>推荐</a> </div> <h4 slot="footer" style="text-align: center;">欢迎观影</h4> </Category> </div> </template> <script> import Category from './components/Category.vue' export default { name:'App', components:{Category}, data(){ return{ foods:['火锅','烧烤','小龙虾','牛排'], games:['红色警戒','穿越火线','劲舞团','超级玛丽'], films:['《教父》','《拆弹专家》','《你好,李焕英》','《尚硅谷》'] } }, } </script> <style> .cantainer{ display: flex; justify-content: space-around; } .foot{ display: flex; justify-content: space-around; } h3{ text-align: center; background-color: orange; } </style>
3)作用域卡槽,有些时候,父组件并不像以上两种情况,数据存在于父组件这里,那么如果数据存在于子组件的话,然后父组件又要获取到子组件的数据,那么该如何操作呢?作用域插槽帮我们解决了这个问题
在作用域卡槽中,有这样一个属性,我们在插槽上定义data()中的games属性
然后再父组件中要调用的话
1)包含在 <template> </template>中
2)给其赋予属性 scope=“tmp” (其中tmp是我们传递过来的参数,如果想要调用里面的数据,就调用tmp.games【本例子中是games,具体问题具体分析】)
子组件

<template> <div class="category"> <h3>{{title}}分类</h3> <slot :games="games">我是插槽填放位置,当使用者传递具体结构时,我会出现</slot> <!-- <ul> <li v-for="(item,index) in listData" :key="index">{{item}}</li> </ul> --> </div> </template> <script> export default{ name:'Category', props:['title'], data(){ return{ games:['红色警戒','穿越火线','劲舞团','超级玛丽'], } }, } </script> <style> .category{ background-color: #006666; width: 200px; height: 300px; } </style>
父组件

<template> <div class="cantainer"> <Category title="游戏"> <template scope="tmp"> <ul> <li v-for="(g,index) in tmp.games" :key="index">{{g}}</li> </ul> </template> </Category> <Category title="游戏"> <template scope="tmp"> <ol> <li style="color: red;" v-for="(g,index) in tmp.games" :key="index">{{g}}</li> </ol> </template> </Category> <Category title="游戏"> <template scope="tmp"> <h4 style="color: black;" v-for="(g,index) in tmp.games" :key="index">{{g}}</h4> </template> </Category> </div> </template> <script> import Category from './components/Category.vue' export default { name:'App', components:{Category}, } </script> <style> .cantainer{ display: flex; justify-content: space-around; } .foot{ display: flex; justify-content: space-around; } h3{ text-align: center; background-color: orange; } </style>