Vue-组件化编程
文档
Vue组件化编程
开发常用
//delete - ask |
脚手架
#安装
npm install -g @vue/cli |
#版本
vue --version |
#创建项目
vue create "Demo_name" |
#运行
#VsCode open folder cd/cd.. |
脚手架文件结构
├── 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中使用组件的三大步骤:
- 一、定义组件(创建组件)
使用:Vue.extend(options)创建,其中options.和new Vue(options)时传入的那个options.几乎一样,但也有点区别:
区别如下:
1.e1不要写,为什么?—–最终所有的组件都要经过一个vm的管理,由vm中的e1决定服务哪个容器。
2.data必须写成函数,为什么?避免组件被复用时,数据存在引用关系。 data(){ }
备注:使用template可以配置组件结构。
- 二、注册组件
1.:局部注册:靠new Vue的时候传入components选项
2.:全局注册:靠Vue.component(‘组件名’,组件)
- 三、使用组件(写组件标签)
编写组件标签:< school>< /school>
<body> |
ref (id替代者)–绑定Dom
#ref属性
被用来给元素或子件注册引用信息(id的替代者)
应用在htm1标签上获取的是真实D0M元素,应用在组件标签上是组件实例对象(vc)
使用方式:
打标识:< h1 ref=”Xxx”/> 或< Schoo ref=”Xx”/>
获取:this.$refs,xxxxx
获取值:const c= this.$refs.Xxx.innerText
<h1 v-text="chen" id="title"></h1> |
关于不同版本的Vue
vue.js与vue.runtime.xxx.js的区别:
- vue.js是完整版的Vue,包含:核心功能 + 模板解析器。
- vue.runtime.xxx.js是运行版的Vue,只包含:核心功能;没有模板解析器。
- 因为vue.runtime.xxx.js没有模板解析器,所以不能使用template这个配置项,需要使用render函数接收到的createElement函数去指定具体内容。
vue.config.js配置文件
- 使用vue inspect > output.js可以查看到Vue脚手架的默认配置。
- 使用vue.config.js可以对脚手架进行个性化定制,详情见:https://cli.vuejs.org/zh
组件间通讯
一、props – 跨组件传数据
功能:让组件接收外部传过来的数据
(1).父组件 ==> 子组件 通信
(2).子组件 ==> 父组件 通信(要求父先给子一个函数)
(3).使用v-model时要切记:v-model绑定的值不能是props传过来的值,因为props是不可以修改的!
(4).props传过来的若是对象类型的值,修改对象中的属性时Vue不会报错,但不推荐这样做。
传递数据:
<Demo name="xxx"/>
<!--整型传值 v-bind=“value” --> |
接收数据(子):
- 第一种方式(只接收):
props:['name']
- 第一种方式(只接收):
// 第一种:简单接收 -- 常用 |
- 第二种方式(限制类型):
props:{name:String}
props:{ |
- 第三种方式(限制类型、限制必要性、指定默认值):
props:{ |
备注:props是只读的,Vue底层会监测你对props的修改,如果进行了修改,就会发出警告,若业务需求确实需要修改,那么请复制props的内容到data中一份,然后去修改data中的数据。
如需修改,设置中转变量
data(){ |
二、*组件自定义事件 –ref
- 一种组件间通信的方式,适用于:子组件 ===> 父组件
- 使用场景:A是父组件,B是子组件,B想给A传数据,那么就要在A中给B绑定自定义事件(事件的回调在A中)。
- (第一种写法,使用@或v-on)(第二种写法,使用 ref 需要触发 emit ),
1、 v-on :name=’name’
父组件设置给子组件绑定一个自定义事件,在methods中配置接收参数和数据处理方法
使用ref,需要在钩子中绑定自定义事件然后被等待调用 –
this.$refs.refs名.$on(’自定义事件名‘,回调)
第一种写法,使用 @ / v-on
父组件:
通过父组件给子组件传递函数类型的props实现:子给父传递数据
通过父组件给子组件给子组件绑定一个自定义事件实现:子给父传递数据(使用 @ 或 v-on)
<School :getSchoolName="getSchoolName"/> |
- 子组件 使用 $emit 触发该自定义事件
2、 ref
使用 ref
通过父组件给子组件给子组件 ref 绑定一个自定义事件实现:子给父传递数据
父组件在钩子中绑定自定义事件** – this.$refs.refs名.$on(’自定义事件名‘,methods函数)
<Student ref="studentc"/> |
子组件 使用 $emit 触发该自定义事件
2、 触发 $emit
无论是使用 v-on :name=’name’ 还是使用 ref ,子组件都是通过 $emit 进行触发自定义事件 : this.$emit(‘chen’,value)
- 传递多个数据使用 funcation_name(name,…params):除了name,剩余数据包装到params数组中
//子组件 |
3、解绑 – $off
子组件中设置解绑组件实例上的name事件
methods:{ |
三、数据传递 – 子传父
- 父组件在methods里面设置一个函数,函数获取调用值,通过v-bind把函数传递到子组件,子组件把要传的值写入该函数的形参中通过传递地址修改值实现
父组件:
<MyHeader :receivea="receivec"/> |
子组件:
props:['receivea'], |
四、全局事件总线–bus
1、安装全局事件总线
main.js
- 安装全局事件总线第一种写法
const Demo=Vue.extend({}) |
- (推荐写法)安装全局事件总线
new Vue({ |
2、接收数据
使用:this.$bus.$on(‘事件name’,(data)=>{ })
绑定事件
回调留在组件本身
methods:{ |
3、提供数据
- 触发:this.$bus.$emit(‘事件name’,data)
- 绑定事件,传值
methods:{ |
4、销毁
- beforeDestroy钩子中编写销毁方法
beforeDestroy(){ |
五、消息订阅与发布 (pubsub)
一种组件间通信的方式,适用于任意组件间通信。
使用步骤
①安装pubsub:
npm i pubsub-js` |
② 引入
- 哪个组件要使用则要导入
import pubsub from 'pubsub-js' |
③接收数据
- A组件想接收数据,则在A组件中订阅消息,订阅的回调留在A组件自身。
- this.pubId=pubsub.subscribe(‘ccc’,this.demo)
- pubId为订阅id,在取消订阅销毁的时候使用到
methods:{ |
④.提供数据
- pubsub.publish(‘xxx’,value)
methods: { |
⑤.取消订阅。
- 在beforeDestroy钩子中
- PubSub.unsubscribe(pid)
beforeDestroy() { |
mixin混入 – 共享配置
- 当数据冲突,原数据为主,src创建混合js
- 新建js文件并配置数据
export const hunhe = { |
引用混合配置
①引入混合
import {hunhe,hunhe2} from '../mixin' |
②使用
<h2>学校地址:{{x}}{{y}} |
插件
功能:用于增强Vue
本质:包含install方法的一个对象,install的第一个参数是Vue,第二个以后的参数是插件使用者传递的数据。
定义插件plugins.js:
export default { |
4.引入并使用插件(main.js)
import plugins from './plugins' |
5.使用插件
- 直接使用插件里面方法的名字即可
<h2>学校名称:{{name | mySlice}}</h2> |
scoped 样式隔离
- 在编译的时候,全部组件样式汇总到一起,各组件类名相同时会发生冲突,在App.vue中后引用的组件样式会覆盖上层
//Vscode -- vuecss快捷键 |
本地存储
存储内容大小一般支持5MB左右(不同浏览器可能还不一样)
浏览器端通过 Window.sessionStorage(会话,关闭丢失) 和 Window.localStorage 属性来实现本地存储机制。
相关API:
xxxxxStorage.setItem(‘key’, ‘value’);
该方法接受一个键和值作为参数,会把键值对添加到存储中,如果键名存在,则更新其对应的值。
let p = {name:'张三',age:18} |
- xxxxxStorage.getItem(‘person’)
该方法接受一个键名作为参数,返回键名对应的值。
function readData(){ |
- xxxxxStorage.removeItem(‘key’);
该方法接受一个键名作为参数,并把该键名从存储中删除。
function deleteData(){ |
- xxxxxStorage.clear()
该方法会清空存储中的所有数据。
function deleteAllData(){ |
- Vue通过深度监视进行读取本地存储数据进行对vc上的数据进行响应式存储
watch:{ |
nextTick
进行执行代码,如果存在对Dom元素存在修改行为,Vue会执行所有的代码后更新页面Dom。例:执行focus()获取焦点代码后,上部分代码存在修改Dom行为,则执行focus()后所有的代码后页面会被刷新,获取焦点失败。
语法:this.$nextTick(回调函数)
作用:在下一次 DOM 更新结束后执行其指定的回调。
什么时候用:当改变数据后,要基于更新后的新DOM进行某些操作时,要在nextTick所指定的回调函数中执行。
解决方法:
①使用定时器,等待页面刷新后执行
②使用nextTick
this.$nextTick(function(){ |
动画
#第二动画库 npm install vue-kinesis
```html
<kinesis-container>
Here, you can put
<kinesis-element :strength="10"> whatever </kinesis-element>
<kinesis-element :strength="20"> content! </kinesis-element>
</kinesis-container>
- 原css中设置动画
.come{ |
过渡 – transition
标签:
appear:初始渲染加入v-enter-active动画(进入网站)
若有多个元素需要过度,则需要使用:
,且每个元素都要指定key值。 元素进入的样式:
v-enter:进入的起点
v-enter-active:进入过程中
v-enter-to:进入的终点
元素离开的样式:
- v-leave:离开的起点
- v-leave-active:离开过程中
- v-leave-to:离开的终点
通过 v-show 判断是否显示该 dom实现动画出现和隐退
<button @click="isShow=!isShow">显示/隐藏</button> |
css中的动画设置
.v-enter-active{ |
- 自定义过渡名字
<transition name='cc'> |
css中类名设置:
.cc-enter-active{ |
封装过渡
<transition-group name="hello" appear> |
/* 进入的起点、离开的终点 */ |
封装动画
- #安装第三方库
npm install animate.css --save |
- 在组件中引入
import 'animate.css' |
- 按照库的要求编写 (name、进入:enter-active-class、隐退:leave-active-class)
<transition-group appear |
vue脚手架配置代理 – axios
node server |
方法一
- 下载axios
npm i axios |
- 当前组件引用
import axios from 'axios' |
- 在 vue.config.js 文件中添加如下配置:
devServer:{ |
说明:
- 优点:配置简单,请求资源时直接发给前端(8080)即可。
- 缺点:不能配置多个代理,不能灵活的控制请求是否走代理。
- 工作方式:若按照上述配置代理,当请求了前端不存在的资源时,那么该请求会转发给服务器 (优先匹配前端资源)
方法二
编写 **vue.config.js **配置具体代理规则:
module.exports = { |
端口欺骗:
changeOrigin设置为true时,服务器收到的请求头中的host为:localhost:5000
changeOrigin设置为false时,服务器收到的请求头中的host为:localhost:8080
changeOrigin默认值为true
- 组件中设置
getStudents(){ |
说明:
- 优点:可以配置多个代理,且可以灵活的控制请求是否走代理。
- 缺点:配置略微繁琐,请求资源时必须加前缀。
Github案例 – axios
调用Github接口
searchUsers(){ |
- 拓展运算符 … (解构,数据替换)
- 接收数据 – 接收对象值dataObj – 与data中的对象info进行比较替换,存在的值则替换为dataOb里面的值
mounted(){ |
Vue-resource
- 安装(插件)
npm i vue-resource |
- 引用(main.js)
import vueResourcec from 'vue-resource |
- 使用 – 和 axios 使用方法类似
//使用 -- this.$http.get |
插槽 slot
作用:让父组件可以向子组件指定位置插入html结构,也是一种组件间通信的方式,适用于 父组件 ===> 子组件 。
分类:默认插槽、具名插槽、作用域插槽
使用方式:(在父组件中使用子组件标签不使用自闭合,在标签内插入内容,在子组件中的slot标签内插入,如果不传内容则slot自身内的内容为默认值)
- 默认插槽(在父组件把内容插入到子组件中 solt)
父组件中(不使用自闭合组件标签)
在父组件把内容插入到子组件中 solt
<Category> |
- 子组件:<– 定义插槽 –>
<template> |
- 具名插槽
- 定义插槽:子组件给 solt 设置 name 属性
<template> |
- 父组件要插入的内容设置 slot=”name” / v-slot:name 属性,精确插入
<Category> |
- 作用域插槽
子组件把 数据传递 回插槽的使用者(父组件)
子组件传递数据:
name不必和父组件接收name相同
<template> |
父组件要使用 template标签包裹插入的j结构
< strong style=”color:blue”>scope</ strong> = “scopeDataName” 接收传递回来的数据
scopeDataName 名字无任何要求
当 scopeDataName 是一个对象,使用 scope=”{对象(names)}”进行 解构赋值 直接获取对象值
<template> |
Vuex
- 安装 – 注意vue2版本要求 – (插件)
#Vue2 --> vuex 3.+ |
搭建环境
1.创建配置项
(文档推荐)assets下创建 store 文件夹,创建index.js
该文件用于创建Vuex中最核心的store
import Vue from 'vue' |
2.传入配置项
- 在 main.js 中创建vm时传入 store 配置项
//引入store |
3.简单实操
1、存储变量
- (index.js)在store的 state 中
//准备state -- 用于存储数据 |
2、获取存储的变量
- 组件插值语法中直接使用 this.$store.state.dataname 获取store中的数据 (可省略this) $store.state.dataname
{{ this.$store.state.sum }} |
3.调用修改变量
this.$store.
调用 actions 中方法使用 dispatch
this.$store.dispatch(‘方法name’,数据)
调用 mutations 中方法使用commit – 可跳过dispatch直接进行数据操纵
this.$store.commit(‘方法name’,数据)
methods:{ |
4.设置响应动作和操纵数据
- store - index.js
- actions – 用于响应组件中的动作
要想被调用使用 .dispatch
在actions中引用自身方法:context.dispatch(‘方法’,值)
传话 :其中的方法不对数据进行操纵修改,它会 调用 mutations 中的方法进行对数据操纵修改
其中的方法(context,value):
context 为上下文 ,使用 .commit 方法进行调用 mutations 中的方法 – context.commit(‘mutations中的方法名’,读取实例获取的值)
//准备actions |
- mutations – 具体实现– 用于操纵 state 中的数据
操纵数据具体实现步骤,要被想调用则使用 :.commit
**方法(state,value)**:获取state的数据:.state.data_name
//准备mutations |
Vuex 模块化
开启命名空间:namespace:ture
目的:让代码更好维护,让多种数据分类更加明确。
- 修改
store.js
const countAbout = { |
- 导出
const store = new Vuex.Store({ |
- 开启命名空间后,组件中读取state数据:
//方式一:自己直接读取 |
- 开启命名空间后,组件中读取getters数据:
//方式一:自己直接读取 |
- 开启命名空间后,组件中调用dispatch
//方式一:自己直接dispatch |
- 开启命名空间后,组件中调用commit
//方式一:自己直接commit / |
全局计算属性
1.getters 配置项
- 当state中的数据需要加工后再使用时,使用 getters 加工:
//追加 getters 配置项 |
- 调用store里面getters数据 – $store.getters.数据
//获取getters返回的值 |
2.mapGetters – 获取getters数据
<h2>当前值:{{ bigSum }}</h2> |
3.mapState – 获取state数据
<h2>{{ sum }}{{ school }}{{ c }}</h2> |
map生成方法
1.mapMutations – commit
- 使用 this.$store.commit 写法时,方法触发不需要传值在触发位置传值
<button @click="increment">+</button> |
methods:{ |
- …mapMutations 写法需要写入传值 给mutayions方法使用
<button @click="increment(n)">+</button> |
//借助mapMutations生成对应的方法,方法中会调用commit去联系mutations |
2.mapActions– dispatch
- 使用 this.$store.dispatch写法时,方法触发不需要传值在触发位置传值
<!-- this.$store.commit 写法不需要传值 --> |
methods:{ |
- …mapActions 写法需要写入**传值 **给 actions 的方法使用
<!-- mapActions 写法需要传值 --> |
methods:{ |
路由
1.安装–引入–应用
#vue2 --安装路由插件 - vue-router@3 |
- main.js
//引入VueRouter插件 |
2.配置
①main.js
new Vue({ |
②创建文件夹(router)– 创建 (name) index.js
- 该文件专门用于创建整个应用的路由器
import VueRouter from "vue-router"; |
③跳转设置
Vue中借助 router-link (等价于html中的 a 标签)标签实现路由跳转
标签内使用 to=”path” 来指定跳转组件
激活属性: active-class=”active” – 被选中激活高亮
<router-link class="list-group-item" active-class="active" to="/about">AboutV</router-link> |
- 在指定位置展示路由跳转显示的组件
<router-view></router-view> |