[TOC]
> 参考 [https://juejin.im/post/5c776ee4f265da2da53edfad](https://juejin.im/post/5c776ee4f265da2da53edfad)
## 父组件传递props属性给子组件
子组件要想得到父组件的数据,只需要在子组件内部通过props显示的声明自己想要什么属性。声明之后父组件将数据传递给子组件就ok了,如下:
~~~
Vue.component('child',{
props: ['message','myMessage'],
template: '<span>{{ message }}</span>'
})
~~~
在父组件中使用 `<child message="hello!" :my-message="parentMsg"></child> `即可
> 注意:在子组件中不能修改父组件传递过来的数据,只能做备份来修改,并且引用类型要深拷贝
<br>
<br>
## 父组件传递非props属性给子组件
在父组件中通过传递非props属性,将自动添加到子组件根元素上面,如下
~~~
<bs-date-input data-3d-date-picker="true"></bs-date-input>
~~~
如果子组件上面已经存在了同名属性,一般都是直接替换的,但是class和style是和子组件的class和style合并的
。
<br>
<br>
## 子组件通知父组件
~~~
// 父组件
<aaa v-on:somefunction="parentfunction"></aaa>
~~~
~~~
// 子组件
export default {
methods: {
childfunction () {
this.$emit('somefunction')
}
}
}
~~~
在子组件中触发某个事件同时`v-on:click="childfunciton"`,可以通过在 childfunction 内部添加`this.$emit('somefunction')`通知触发父组件中的事件,在父组件中通过 `v-on:somefunction="parentfunction"` 接受到通知,然后触发父组件中的 parentfunction 事件,也就是说在父组件中,将 `v-on` 用在子组件标签上面并不是给子组件绑定事件而是监听子组件内部的消息。
但是如果确实想绑定一个事件给子组件可以通过添加.native修饰符,如下
~~~
<my-component v-on:click.native="doTheThing"></my-component>
~~~
这个事件将直接绑定到子组件的根元素
。
<br>
<br>
## 子组件父组件数据双向绑定
在一个包含 title prop 的假设的组件中,我们可以用以下方法表达对其赋新值的意图:
~~~
this.$emit('update:title', newTitle)
~~~
然后父组件可以监听那个事件并根据需要更新一个本地的数据属性。例如:
~~~
<text-document
v-bind:title="doc.title"
v-on:update:title="doc.title = $event"
></text-document>
~~~
为了方便起见,我们为这种模式提供一个缩写,即 .sync 修饰符:
~~~
<text-document v-bind:title.sync="doc.title"></text-document>
~~~
> 注意带有 `.sync` 修饰符的 `v-bind` 不能和表达式一起使用 (例如 `v-bind:title.sync=”doc.title + ‘!’”` 是无效的)。取而代之的是,你只能提供你想要绑定的属性名,类似 `v-model`。
当我们用一个对象同时设置多个 prop 的时候,也可以将这个 `.sync` 修饰符和 `v-bind` 配合使用:
~~~
<text-document v-bind.sync="doc"></text-document>
~~~
这样会把 `doc` 对象中的每一个属性 (如 `title`) 都作为一个独立的 `prop` 传进去,然后各自添加用于更新的 `v-on` 监听器。
<br>
<br>
## 自定义组件通信
~~~
<input v-model="something">
~~~
v-model其实,就是下面的简写形式:
~~~
<input v-bind:value="something" v-on:input="something = $event.target.value">
~~~
同样v-model也可以用在组件身上,就是如下的样子了。
~~~
<custom-input :value="something" @input="value => { something = value }"></custom-input>
~~~
所以知道这上面两点就可以实现自定义组件v-model功能了。
<br>
下面是child.vue的代码
~~~
<div>
<input type="text" :value="value" @input="updateValue($event.target.value)">
{{value}}
</div>
export default {
props: ['value'],
methods: {
updateValue(value){
this.$emit('input',value)
}
},
}
~~~
下面是father.vue的代码
~~~
<child v-model="price"></child>
data () {
return {
price: ''
}
}
~~~
在子组件中的input中输入数据,可以动态的反应到父组件中,实现双向绑定
由于默认是value和input如果想改变这个默认的,可以在子组件中,使用model如下:
~~~
model: {
prop: 'checked',
event: 'change'
},
props: {
checked: Boolean,
value: String
}
~~~
所以使用 `<my-checkbox v-model="foo" value="some value"></my-checkbox>` 其实就是下面的简写
~~~
<my-checkbox :checked="foo" @change="val => { foo = val }" value="some value"></my-checkbox>
~~~
<br>
<br>
## 非父子组件之间的通信
非父子组件之间的通信就要使用$on了。首先要有一个空的vue实例
~~~
var bus = new Vue();
~~~
如果你使用vue的webpack项目的话,这个东西你要单独的加在一个js文件中以store.js为例,添加如下代码
:
~~~
import Vue from 'vue'
window.bus = new Vue();
~~~
并且还要在main.js中通过import './store.js'导入,这时就可以在vue项目全局使用bus了
如果在一个组件中需要传递消息,就使用bus.$emit('fn', 1)传递数据
在要接受数据的组件中使用,bus.$on('fn',function(value){...})即可
讲到这儿,vue最核心的部分也就将完了,弄懂这块儿东西,相信后面的学习就易如反掌了
<br>
<br>
## 使用slot实现内容分发
实际工作中组件的组成大多数是类似下面的
:
~~~
<parent>
<child>
<someother-component></someother-component>
</child>
</parent>
~~~
slot的作用就是用来处理嵌套在组件标签内部的内容
<br>
<br>
## 单一slot
如果只有一个slot标签并且没有任何属性,slot标签将会被全部替换成嵌套在组件标签内部的内容,如果slot标签自身包裹内容,这个内容只会在组件标签内部不包含任何东西的时候展示,demo如下
如果一个child组件的模板内容如下
~~~
<div>
<h2>I'm the child title</h2>
<slot>
这里面的内容只会在没有插入内容时显示
</slot>
</div>
~~~
然后`<child>hahahhahahah</child>
`,那么hahahhahahah就会替换 `slot` 成为 `child` 模板的一部分
。
<br>
<br>
## 命名slot
可以给slot起个名字,比如`<slot name="header"></slot>
`
然后给组件标签内容添加slot属性,属性值和上面的名字相同,就可以实现特殊指派了,如
~~~
<child>
<h1 slot="header">指定的内容</h1>
</child>
~~~
这样就实现的需求导入了
。
<br>
<br>
## 局部slot
上面讲的 `slot` 都是可以实现父组件传递数据到子组件中,现在想实现将子组件中的数据传递到 `slot` 要替换的内容中
。
可以在子组件中的 `slot` 插槽中添加任意属性,如 '<slot text="子组件child中的数据"></slot>
'。
然后,在子组件标签内部,如下
:
~~~
<parent>
<child>
// 必须使用template标签,并且添加scope属性,属性值props就是包含slot传递的数据对象
<template scope="props">
<span>父组件parent中的数据</span>
<span>{{props.text}}</span>
</template>
</child>
</parent>
~~~
<br>
<br>
## 动态组件
可以使用同一个绑定点,动态的切换渲染不同的组件,要实现这个功能要借助component标签和is属性
。
~~~
<component :is="currentView"></component>
~~~
vue实例代码如下
:
~~~
var vm = new Vue({
el: "#example",
data: {
currentView: 'home'
},
components: { home,posts,archive }
})
~~~
通过改变currentView的值,可以实现动态切换组件。
上面这种写法可以满足局部组件,也就是你自己定义的组件的切换,但是如果你使用全局组件,比如某些UI组件库中的组件,那么就要像下面这样用
:
~~~
var Home = {
template: ...
};
var vm = new Vue({
el: "#example",
data: {
currentView: Home
}
});
~~~
如果你想将切换渲染过的组件保留在内存中可以使用keep-alive将动态组件包裹
~~~
<keep-alive>
<component :is="currentView">
...
</component>
<keep-alive>
~~~
- 第一部分 HTML
- meta
- meta标签
- HTML5
- 2.1 语义
- 2.2 通信
- 2.3 离线&存储
- 2.4 多媒体
- 2.5 3D,图像&效果
- 2.6 性能&集成
- 2.7 设备访问
- SEO
- Canvas
- 压缩图片
- 制作圆角矩形
- 全局属性
- 第二部分 CSS
- CSS原理
- 层叠上下文(stacking context)
- 外边距合并
- 块状格式化上下文(BFC)
- 盒模型
- important
- 样式继承
- 层叠
- 属性值处理流程
- 分辨率
- 视口
- CSS API
- grid(未完成)
- flex
- 选择器
- 3D
- Matrix
- AT规则
- line-height 和 vertical-align
- CSS技术
- 居中
- 响应式布局
- 兼容性
- 移动端适配方案
- CSS应用
- CSS Modules(未完成)
- 分层
- 面向对象CSS(未完成)
- 布局
- 三列布局
- 单列等宽,其他多列自适应均匀
- 多列等高
- 圣杯布局
- 双飞翼布局
- 瀑布流
- 1px问题
- 适配iPhoneX
- 横屏适配
- 图片模糊问题
- stylelint
- 第三部分 JavaScript
- JavaScript原理
- 内存空间
- 作用域
- 执行上下文栈
- 变量对象
- 作用域链
- this
- 类型转换
- 闭包(未完成)
- 原型、面向对象
- class和extend
- 继承
- new
- DOM
- Event Loop
- 垃圾回收机制
- 内存泄漏
- 数值存储
- 连等赋值
- 基本类型
- 堆栈溢出
- JavaScriptAPI
- document.referrer
- Promise(未完成)
- Object.create
- 遍历对象属性
- 宽度、高度
- performance
- 位运算
- tostring( ) 与 valueOf( )方法
- JavaScript技术
- 错误
- 异常处理
- 存储
- Cookie与Session
- ES6(未完成)
- Babel转码
- let和const命令
- 变量的解构赋值
- 字符串的扩展
- 正则的扩展
- 数值的扩展
- 数组的扩展
- 函数的扩展
- 对象的扩展
- Symbol
- Set 和 Map 数据结构
- proxy
- Reflect
- module
- AJAX
- ES5
- 严格模式
- JSON
- 数组方法
- 对象方法
- 函数方法
- 服务端推送(未完成)
- JavaScript应用
- 复杂判断
- 3D 全景图
- 重载
- 上传(未完成)
- 上传方式
- 文件格式
- 渲染大量数据
- 图片裁剪
- 斐波那契数列
- 编码
- 数组去重
- 浅拷贝、深拷贝
- instanceof
- 模拟 new
- 防抖
- 节流
- 数组扁平化
- sleep函数
- 模拟bind
- 柯里化
- 零碎知识点
- 第四部分 进阶
- 计算机原理
- 数据结构(未完成)
- 算法(未完成)
- 排序算法
- 冒泡排序
- 选择排序
- 插入排序
- 快速排序
- 搜索算法
- 动态规划
- 二叉树
- 浏览器
- 浏览器结构
- 浏览器工作原理
- HTML解析
- CSS解析
- 渲染树构建
- 布局(Layout)
- 渲染
- 浏览器输入 URL 后发生了什么
- 跨域
- 缓存机制
- reflow(回流)和repaint(重绘)
- 渲染层合并
- 编译(未完成)
- Babel
- 设计模式(未完成)
- 函数式编程(未完成)
- 正则表达式(未完成)
- 性能
- 性能分析
- 性能指标
- 首屏加载
- 优化
- 浏览器层面
- HTTP层面
- 代码层面
- 构建层面
- 移动端首屏优化
- 服务器层面
- bigpipe
- 构建工具
- Gulp
- webpack
- Webpack概念
- Webpack工具
- Webpack优化
- Webpack原理
- 实现loader
- 实现plugin
- tapable
- Webpack打包后代码
- rollup.js
- parcel
- 模块化
- ESM
- 安全
- XSS
- CSRF
- 点击劫持
- 中间人攻击
- 密码存储
- 测试(未完成)
- 单元测试
- E2E测试
- 框架测试
- 样式回归测试
- 异步测试
- 自动化测试
- PWA
- PWA官网
- web app manifest
- service worker
- app install banners
- 调试PWA
- PWA教程
- 框架
- MVVM原理
- Vue
- Vue 饿了么整理
- 样式
- 技巧
- Vue音乐播放器
- Vue源码
- Virtual Dom
- computed原理
- 数组绑定原理
- 双向绑定
- nextTick
- keep-alive
- 导航守卫
- 组件通信
- React
- Diff 算法
- Fiber 原理
- batchUpdate
- React 生命周期
- Redux
- 动画(未完成)
- 异常监控、收集(未完成)
- 数据采集
- Sentry
- 贝塞尔曲线
- 视频
- 服务端渲染
- 服务端渲染的利与弊
- Vue SSR
- React SSR
- 客户端
- 离线包
- 第五部分 网络
- 五层协议
- TCP
- UDP
- HTTP
- 方法
- 首部
- 状态码
- 持久连接
- TLS
- content-type
- Redirect
- CSP
- 请求流程
- HTTP/2 及 HTTP/3
- CDN
- DNS
- HTTPDNS
- 第六部分 服务端
- Linux
- Linux命令
- 权限
- XAMPP
- Node.js
- 安装
- Node模块化
- 设置环境变量
- Node的event loop
- 进程
- 全局对象
- 异步IO与事件驱动
- 文件系统
- Node错误处理
- koa
- koa-compose
- koa-router
- Nginx
- Nginx配置文件
- 代理服务
- 负载均衡
- 获取用户IP
- 解决跨域
- 适配PC与移动环境
- 简单的访问限制
- 页面内容修改
- 图片处理
- 合并请求
- PM2
- MongoDB
- MySQL
- 常用MySql命令
- 自动化(未完成)
- docker
- 创建CLI
- 持续集成
- 持续交付
- 持续部署
- Jenkins
- 部署与发布
- 远程登录服务器
- 增强服务器安全等级
- 搭建 Nodejs 生产环境
- 配置 Nginx 实现反向代理
- 管理域名解析
- 配置 PM2 一键部署
- 发布上线
- 部署HTTPS
- Node 应用
- 爬虫(未完成)
- 例子
- 反爬虫
- 中间件
- body-parser
- connect-redis
- cookie-parser
- cors
- csurf
- express-session
- helmet
- ioredis
- log4js(未完成)
- uuid
- errorhandler
- nodeclub源码
- app.js
- config.js
- 消息队列
- RPC
- 性能优化
- 第七部分 总结
- Web服务器
- 目录结构
- 依赖
- 功能
- 代码片段
- 整理
- 知识清单、博客
- 项目、组件、库
- Node代码
- 面试必考
- 91算法
- 第八部分 工作代码总结
- 样式代码
- 框架代码
- 组件代码
- 功能代码
- 通用代码