基本结构:
◆1、组件化开发思想
◆2、组件注册
◆3、Vue调试工具用法
◆4、组件间数据交互
◆5、组件插槽
◆6、基于组件的案例
 
◆1、组件化开发思想
  优点:
    提高开发效率
    方便重复使用
    简化调试步骤
    提升整个项目的可维护性
    便于多人协同开发
 
◆2、组件注册
  2.1 全局组件
    1> 全局组件注册语法
    
    
    2> 组件用法
    
 
         3>  组件注册注意事项  

      1、组件参数的data值必须是函数
         2、组件模板必须是单个根元素
         3、组件模板的内容可以是模板字符串(``,因为放在一行内可能造成代码可读性差)

      4. 组件命名方式:
          短横线方式 Vue.component('my-component', { /* ... */ })
          驼峰方式 Vue.component('MyComponent', { /* ... */ })
    4> 具体使用  

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Document</title>
</head>
<body>
<div id="app">
<button-counter></button-counter>
<button-counter></button-counter>
<button-counter></button-counter>
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
/*
组件注册注意事项
  1、组件参数的data值必须是函数,
        之前实例化的时候是一个对象{},使用函数可以形成一个闭包环境,保证每一个组件都是拥有一份独立的数据
  2、组件模板必须是单个根元素
        <button @click="handle">点击了{{count}}次</button><button>测试</button> ---不行
        解决方法:<div><button @click="handle">点击了{{count}}次</button><button>测试</button></div>
  3、组件模板的内容可以是模板字符串
        ( ``,因为放在一行内,不直观造成代码可读性差)
*/ Vue.component("button-counter", {
data: function () {
return {
count: 0,
};
},
// template: '<div><button @click="handle">点击了{{count}}次</button><button>测试</button></div>',
template: `
<div>
<button @click="handle">点击了{{count}}次</button>
<button>测试123</button>
</div>
`,
methods: {
handle: function () {
this.count += 2;
},
},
});
var vm = new Vue({
el: "#app",
data: { },
});
</script>
</body>
</html>
  2.2 局部组件
    1> 局部组件注册语法
    
  
    2> 注意事项及代码
    

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="app">
<hello-world></hello-world>
<hello-tom></hello-tom>
<hello-jerry></hello-jerry>
<test-com></test-com>
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
/*
局部组件注册
局部组件只能在注册他的父组件中使用
*/
Vue.component('test-com',{
template: '<div>Test<hello-world></hello-world></div>',
//全局组件中不可用,只能在注册他的父组件中使用 <div id="app"></div>
}); var HelloWorld = {
data: function(){
return {
msg: 'HelloWorld'
}
},
template: '<div>{{msg}}</div>'
}; var HelloTom = {
data: function(){
return {
msg: 'HelloTom'
}
},
template: '<div>{{msg}}</div>'
}; var HelloJerry = {
data: function(){
return {
msg: 'HelloJerry'
}
},
template: '<div>{{msg}}</div>'
}; var vm = new Vue({
el: '#app',
data: { },
components: {
'hello-world': HelloWorld,
'hello-tom': HelloTom,
'hello-jerry': HelloJerry
}
});
</script>
</body>
</html>
 ◆4、组件间数据交互
  4.1 父组件向子组件传值
     1.组件内部通过props接收传递过来的值
    
 
    2. 父组件通过属性将值传递给子组件
    
 
    3. props属性名规则
      在props中使用驼峰形式,模板中需要使用短横线的形式
      字符串形式的模板中没有这个限制
    
  
  4.2 子组件向父组件传值
    1. 子组件通过自定义事件向父组件传递信息
      <button @click='$emit("enlarge-text") '>扩大字体</button>
      <button @click='$emit("enlarge-text", 0.1) '>扩大字体</button>
 
    2. 父组件监听子组件的事件
      <menu-item @enlarge-text='fontSize += 0.1'></menu-item>
      <menu-item @enlarge-text='fontSize += $event'></menu-item>  
    注意:   

      子组件向父组件传值-基本用法
          props传递数据原则:
          单向数据流(只允许父向子传递,因为如果子可以直接控制props的话,将会造成混乱,比较复杂)
          不推荐在子组件中直接修改 props的值
         理解:当子组件被触发的时候,自动抛向父组件,父组件触发之后会执行响应的动作
  4.3 兄弟组件间传值
    
    1. 单独的事件中心管理组件间的通信
      var eventHub = new Vue()
 
    2. 监听事件与销毁事件
      eventHub.$on('add-todo', addTodo)
      eventHub.$off('add-todo')
 
    3. 触发事件
      eventHub.$emit(‘add-todo', id)

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="app">
<div>父组件</div>
<div>
<button @click='handle'>销毁事件</button>
</div>
<test-tom></test-tom>
<test-jerry></test-jerry>
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
/*
兄弟组件之间数据传递
*/
// 提供事件中心
var hub = new Vue(); Vue.component('test-tom', {
data: function(){
return {
num: 0
}
},
template: `
<div>
<div>TOM:{{num}}</div>
<div>
<button @click='handle'>点击</button>
</div>
</div>
`,
methods: {
handle: function(){
hub.$emit('jerry-event', 2);
}
},
mounted: function() { //钩子函数,表示模板已就位
// 监听事件
hub.$on('tom-event', (val) => { //用箭头函数(this指向父级本身),因为要用this
this.num += val;
});
}
}); Vue.component('test-jerry', {
data: function(){
return {
num: 0
}
},
template: `
<div>
<div>JERRY:{{num}}</div>
<div>
<button @click='handle'>点击</button>
</div>
</div>
`,
methods: {
handle: function(){
// 触发兄弟组件的事件
hub.$emit('tom-event', 1);
}
},
mounted: function() {
// 监听事件
hub.$on('jerry-event', (val) => {
this.num += val;
});
}
}); var vm = new Vue({
el: '#app',
data: { },
methods: {
handle: function(){
hub.$off('tom-event');
hub.$off('jerry-event');
}
}
});
</script>
</body>
</html>

◆5、组件插槽

  1、组件插槽基本用法
    1. 插槽位置
      
    2. 插槽内容
      
 
  2、具名插槽用法
    1. 插槽位置

                  
    2. 插槽内容
      
 
 
  3、作用域插槽

    应用场景:父组件对子组件的内容进行加工处理
      // 因为一般子组件的值定义好了之后不方便再进行修改,一般不动了,所以在父组件中进行
    1. 插槽位置
      
 
    2. 插槽内容
      
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<style type="text/css">
.current {
color: orange;
}
</style>
<body>
<div id="app">
<fruit-list :list='list'>
<template slot-scope='slotProps'>
<strong v-if='slotProps.info.id==3' class="current">{{slotProps.info.name}}</strong>
<span v-else>{{slotProps.info.name}}</span>
</template>
</fruit-list>
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
/*
作用域插槽
应用场景:父组件对子组件的内容进行加工处理
//因为一般子组件的值定义好了之后不方便再进行修改,一般不动了,所以在父组件中进行
*/
Vue.component('fruit-list', {
props: ['list'],
template: `
<div>
<li :key='item.id' v-for='item in list'>
<slot :info='item'>{{item.name}}</slot>
</li>
</div>
`
});
var vm = new Vue({
el: '#app',
data: {
list: [{
id: 1,
name: 'apple'
},{
id: 2,
name: 'orange'
},{
id: 3,
name: 'banana'
}]
}
});
</script>
</body>
</html>

◆6、基于组件的案例

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Document</title>
<style type="text/css">
.container {
}
.container .cart {
width: 300px;
/*background-color: lightgreen;*/
margin: auto;
}
.container .title {
background-color: lightblue;
height: 40px;
line-height: 40px;
text-align: center;
/*color: #fff;*/
}
.container .total {
background-color: #ffce46;
height: 50px;
line-height: 50px;
text-align: right;
}
.container .total button {
margin: 0 10px;
background-color: #dc4c40;
height: 35px;
width: 80px;
border: 0;
}
.container .total span {
color: red;
font-weight: bold;
}
.container .item {
height: 55px;
line-height: 55px;
position: relative;
border-top: 1px solid black;
}
.container .item img {
width: 45px;
height: 45px;
margin: 5px;
}
.container .item .name {
position: absolute;
width: 90px;
top: 0;
left: 55px;
font-size: 16px;
} .container .item .change {
width: 100px;
position: absolute;
top: 0;
right: 50px;
}
.container .item .change a {
font-size: 20px;
width: 30px;
text-decoration: none;
background-color: lightgray;
vertical-align: middle;
}
.container .item .change .num {
width: 40px;
height: 25px;
}
.container .item .del {
position: absolute;
top: 0;
right: 0px;
width: 40px;
text-align: center;
font-size: 40px;
cursor: pointer;
color: red;
}
.container .item .del:hover {
background-color: orange;
}
</style>
</head>
<body>
<div id="app">
<div class="container">
<my-cart></my-cart>
</div>
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
var CartTitle = {
props: ["uname"],
template: `
<div class="title">{{uname}}的商品</div>
`,
};
var CartList = {
props: ["list"],
template: `
<div>
<div class="item" v-for='item in list' :key='item.id'>
<img :src="item.img" />
<div class="name">{{item.name}}</div>
<div class="change">
<a href="" @click.prevent='sub(item.id)'>-</a>
<input type="text" class="num" :value='item.num' @blur='changeNum(item.id, $event)'/>
<a href="" @click.prevent='add(item.id)'>+</a>
</div>
<div class="del" @click=del(item.id)>×</div>
</div>
</div>
`,
methods: {
// <!-- 如果事件直接绑定函数名称,那么默认会传递事件对象作为事件函数的第一个参数 -->
// <button v-on:click='handle1'>点击1</button>
// <!-- 2、如果绑定函数调用,需要传递事件对象,那么必须作为最后一个参数传递,名称必须是$event -->
// <button v-on:click='handle2(123, 456)'>点击2 </button>
// <button v-on:click='handle2(123, 456, $event)'>点击2 </button>
changeNum: function (id, event) {
this.$emit("change-num", {
id: id,
type: "change",
num: event.target.value,
});
},
sub: function (id) {
this.$emit("change-num", {
id: id,
type: "sub",
});
},
add: function (id) {
this.$emit("change-num", {
id: id,
type: "add",
});
}, del: function (id) {
this.$emit("cart-del", id);
},
},
};
var CartTotal = {
props: ["list"],
template: `
<div class="total">
<span>总价:{{total}}</span>
<button>结算</button>
</div>
`,
computed: {
total: function () {
var t = 0;
this.list.forEach((item) => {
t += item.num * item.price;
});
return t;
},
},
};
Vue.component("my-cart", {
data: function () {
return {
uname: "涂松",
list: [
{
id: 1,
name: "TCL彩电",
price: 1000,
num: 1,
img: "img/a.jpg",
},
{
id: 2,
name: "机顶盒",
price: 1000,
num: 1,
img: "img/b.jpg",
},
{
id: 3,
name: "海尔冰箱",
price: 1000,
num: 1,
img: "img/c.jpg",
},
{
id: 4,
name: "小米手机",
price: 1000,
num: 1,
img: "img/d.jpg",
},
{
id: 5,
name: "PPTV电视",
price: 1000,
num: 2,
img: "img/e.jpg",
},
],
};
},
template: `
<div class="cart">
<cart-title :uname='uname'></cart-title>
<cart-list :list='list' @cart-del='delCart($event)' @change-num='changeNum($event)'></cart-list>
<cart-total :list='list'></cart-total>
</div>
`,
components: {
"cart-title": CartTitle,
"cart-list": CartList,
"cart-total": CartTotal,
},
methods: {
changeNum: function (val) {
// 分为三种情况:输入域变更、加号变更、减号变更
if (val.type == "change") {
// 根据子组件传递过来的数据,跟新list中对应的数据
this.list.some((item) => {
if (item.id == val.id) {
item.num = val.num;
// 终止遍历
return true;
}
});
} else if (val.type == "sub") {
// 减一操作
this.list.some((item) => {
if (item.id == val.id) {
item.num -= 1;
// 终止遍历
return true;
}
});
} else if (val.type == "add") {
// 加一操作
this.list.some((item) => {
if (item.id == val.id) {
item.num += 1;
// 终止遍历
return true;
}
});
}
},
delCart: function (id) {
// 根据id删除list中对应的数据
// 1、找到id所对应数据的索引
// var index = this.list.findIndex((item) => {
// return item.id == id;
// });
// // 2、根据索引删除对应数据
// this.list.splice(index, 1);
this.list = this.list.filter((item) => {
return item.id !== id;
});
},
},
});
var vm = new Vue({
el: "#app",
data: {},
});
</script>
</body>
</html>

Vue基础(三)---- 组件化开发的更多相关文章

  1. Vue 入门之组件化开发

    Vue 入门之组件化开发 组件其实就是一个拥有样式.动画.js 逻辑.HTML 结构的综合块.前端组件化确实让大的前端团队更高效的开发前端项目.而作为前端比较流行的框架之一,Vue 的组件和也做的非常 ...

  2. vue.js原生组件化开发(一)——组件开发基础

    前言 vue作为一个轻量级前端框架,其核心就是组件化开发.我们一般常用的是用脚手架vue-cli来进行开发和管理,一个个组件即为一个个vue页面,这种叫单文件组件.我们在引用组件之时只需将组件页面引入 ...

  3. Webpack+Vue+ES6 前端组件化开发mobile-multi-page应用实战总结

    本文版权归博客园和作者吴双本人共同所有 转载和爬虫请注明原文地址 www.cnblogs.com/tdws 一.写在前面 项目上线有一段时间了,一个基于webpack+vue+ES6的手机端多页面应用 ...

  4. Webpack+Vue+ES6 前端组件化开发mobile-multi-page应用实战总结和踩坑

    本文版权归博客园和作者吴双本人共同所有 转载和爬虫请注明原文地址 www.cnblogs.com/tdws 一.写在前面 项目上线有一段时间了,一个基于webpack+vue+ES6的手机端多页面应用 ...

  5. vue.js原生组件化开发(二)——父子组件

    前言 在了解父子组件之前应先掌握组件开发基础.在实际开发过程中,组件之间可以嵌套,也因此生成父子组件. 父子组件创建流程 1.构建父子组件 1.1 全局注册 (1)构建注册子组件 //构建子组件chi ...

  6. vue(9)—— 组件化开发 - webpack(3)

    前面两个终于把webpack相关配置解析完了.现在终于进入vue的开发了 vue组件化开发预热 前期准备 创建如下项目: app.js: footer.js: main.js: webpack.con ...

  7. Vue学习笔记-Vue.js-2.X 学习(二)===>组件化开发

    ===重点重点开始 ========================== (三) 组件化开发 1.创建组件构造器: Vue.extends() 2.注册组件: Vue.component() 3.使用 ...

  8. vue.js组件化开发实践

    前言 公司目前制作一个H5活动,特别是有一定统一结构的活动,都要码一个重复的轮子.后来接到一个基于模板的活动设计系统的需求,便有了下面的内容.借油开车. 组件化 需求一到,接就是怎么实现,技术选型自然 ...

  9. vue组件化开发实践

    前言 公司目前制作一个H5活动,特别是有一定统一结构的活动,都要码一个重复的轮子.后来接到一个基于模板的活动设计系统的需求,便有了一下的内容.首先会对使用Vue进行开发的一些前期需要的技术储备进行简单 ...

随机推荐

  1. react引入相同组件时互不影响

    具体代码可以查看我的代码仓库 https://gitee.com/haomYGH/Web20/tree/master/010-React/014-redux-immutable 页面展示 要处理的问题 ...

  2. Python机器学习及实践_从零开始通往KAGGLE竞赛之路PDF高清完整版免费下载|百度云盘|Python基础教程免费电子书

    点击获取提取码:i5nw Python机器学习及实践面向所有对机器学习与数据挖掘的实践及竞赛感兴趣的读者,从零开始,以Python编程语言为基础,在不涉及大量数学模型与复杂编程知识的前提下,逐步带领读 ...

  3. 回首Java——写在前面

    我记得在大学的课程要求中,第一个接触的高级编程语言,应该是C语言或者C++等.但是Java应该是我的编程母语,我在高中毕业就接触了Java语言.当时看的是纸质书,具体书名也忘记了.只记得当时第一次接触 ...

  4. Redis分布式限流器

    以下文章来源于微信公众号:程序员内点事 ,作者:程序员内点事 请大家关注原作者 1. 什么是限流?为什么要限流? 限流是保证系统高可用的重要手段!!!由于互联网公司的流量巨大,系统上线会做一个流量峰值 ...

  5. ios迅雷上架成功的秘密 背后的“苹果TF签名”

    距离ios迅雷从App Store下架已经过去很久了,小微经常看到知乎里有很多迅雷用户到处寻找可以下载应用的渠道.近期迅雷被爆“好消息”iOS 迅雷(官方版)正式上架 App Store,此消息一出可 ...

  6. Python 3.9 beta2 版本发布了,看看新特性?

    随着 Python 3.9.0b1 的发布,即开发周期中计划的四个 beta 版本的首个,Python 3.9 的功能已经是完善了.在 10 月发布最终版本之前,还会有许多测试和稳定性方面的工作要做. ...

  7. JDBC回顾

    回顾JDBC,完成查询 1 什么是JDBC JDBC(Java DataBase Connectivity)就是Java数据库连接,说白了就是用Java语言来操作数据库.原来我们操作数据库是在控制台使 ...

  8. GitLab 转让所有者权限

    GitLab 转让所有者权限 没有查看文档,自己测试了一下,可能会有纰漏,谨慎阅读 私人项目的所有者 私人项目没有所有者权限,可以认为项目命名空间就是所有者. 私人项目http://xxxxxxxxx ...

  9. 浅析Facebook LibraBFT与比原链Bystack BBFT共识

    如果说什么是区块链的灵魂,那一定是共识机制. 它是区块链的根基.无论公链或是联盟链,共识机制都从基础上限制了区块链的交易处理能力和扩展性. 2019年6月18日,Facebook 发布了自己 Libr ...

  10. 2020重新出发,JAVA语言,什么是JAVA?

    @ 目录 什么是 java? JAVA三大体系 Java SE Java EE JavaME java的主要特性和优势 1. 面向对象 2. 平台无关性 3. 可移植性 4. 简单性 5. 解释执行 ...