JustDoIt - dev
type: channel
link: https://www.wangmanyuan.com/category/dev/
items: clickhouse 系统表日志清理
items: 商品分类
items: 管理后台 API 接口文档
items: 用户信息
items: 后台基本布局
items: vue电商业务概述
items: vue模块化的分类
items: vue路由
items: vue接口调用方式
items: vue组件

clickhouse 系统表日志清理
type: item
date: 2023-02-17T01:13:01+00:00
description: 今天出现了生产环境clickhouse 清理业务表数据磁盘并未下降的问题 搜索相关文档后得知system表内会继续各种操作日志 一、查询各个表占用空间信息select concat(database, '.', table) as table, formatReadableSize(sum(bytes)) as size, sum(rows) as rows, max(modification_time) as latest_modification, sum(bytes) as bytes_size, any(engine) as engine, formatReadableSize(sum(primary_key_bytes_in_memory)) as primary_keys_size from system.parts where active group by database, table order by bytes_size desc limit 10; 二、清理system 系统自带的日志表数据2.1 根据指定数据库清理SQLalter table system.query_thread_log delete where current_database ='xxx' ; 2.2 根据指定数据库和时间清理SQLalter table system.query_thread_log delete where current_database ='xxx' and event_date='2023-02-05';

商品分类
type: item
date: 2022-10-28T23:15:01+00:00
description: A.新建分支goods_cate新建分支goods_cate并推送到码云git checkout -b goods_categit push -u origin goods_cateB.创建子级路由创建categories子级路由组件并设置路由规则import Cate from './components/goods/Cate.vue' path: '/home', component: Home, redirect: '/welcome', children: [ { path: "/welcome", component: Welcome }, { path: "/users", component: Users }, { path: "/rights", component: Rights }, { path: "/roles", component: Roles }, { path: "/categories", component: Cate } ] C.添加组件基本布局在Cate.vue组件中添加面包屑导航以及卡片视图中的添加分类按钮 商品分类 <el-breadcrumb separator="/"> <el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item> <el-breadcrumb-item>商品管理</el-breadcrumb-item> <el-breadcrumb-item>商品分类</el-breadcrumb-item> </el-breadcrumb> <el-card> <el-row> <el-col> <el-button type="primary">添加分类</el-button> </el-col> </el-row> </el-card> D.请求分类数据请求分类数据并将数据保存在data中 E.使用插件展示数据使用第三方插件vue-table-with-tree-grid展示分类数据1).在vue 控制台中点击依赖->安装依赖->运行依赖->输入vue-table-with-tree-gird->点击安装2).打开main.js，导入vue-table-with-tree-gridimport TreeTable from 'vue-table-with-tree-grid'.....Vue.config.productionTip = false//全局注册组件 Vue.component('tree-table', TreeTable) 3).使用组件展示分类数据 <tree-table :data="cateList" :columns="columns" :selection-type="false" :expand-type="false" show-index index-text="#" border :show-row-hover="false"> </tree-table> 在数据中添加columns: columns: [ {label:'分类名称',prop:'cat_name'} ] F.自定义数据列使用vue-table-with-tree-grid定义模板列并添加自定义列//先在columns中添加一个列 columns: [ {label:'分类名称',prop:'cat_name'}, //type:'template'(将该列设置为模板列)，template:'isok'(设置该列模板的名称为isok) {label:'是否有效',prop:'',type:'template',template:'isok'}, {label:'排序',prop:'',type:'template',template:'order'}, {label:'操作',prop:'',type:'template',template:'opt'} ] <el-tag size="mini" v-if="scope.row.cat_level===0">一级</el-tag> <el-tag size="mini" type="success" v-else-if="scope.row.cat_level===1">二级</el-tag> <el-tag size="mini" type="warning" v-else>三级</el-tag> <el-button size="mini" type="primary" icon="el-icon-edit">编辑</el-button> <el-button size="mini" type="danger" icon="el-icon-d…

管理后台 API 接口文档
type: item
date: 2022-10-23T04:06:00+00:00
description: 管理接口

用户信息
type: item
date: 2022-10-23T03:23:26+00:00
description: 1.修改用户信息A.为用户列表中的修改按钮绑定点击事件B.在页面中添加修改用户对话框，并修改对话框的属性C.根据id查询需要修改的用户数据//展示编辑用户的对话框 async showEditDialog(id) { //发送请求根据id获取用户信息 const { data: res } = await this.$http.get('users/' + id) //判断如果添加失败，就做提示 if (res.meta.status !== 200) return this.$message.error('获取用户信息失败') //将获取到的数据保存到数据editForm中 this.editForm = res.data //显示弹出窗 this.editDialogVisible = true } D.在弹出窗中添加修改用户信息的表单并做响应的数据绑定以及数据验证 <el-form :model="editForm" :rules="editFormRules" ref="editFormRef" label-width="70px"> <el-form-item label="用户名"> <el-input v-model="editForm.username" disabled></el-input> </el-form-item> <el-form-item label="邮箱" prop="email"> <el-input v-model="editForm.email"></el-input> </el-form-item> <el-form-item label="电话" prop="mobile"> <el-input v-model="editForm.mobile"></el-input> </el-form-item> </el-form> 数据绑定以及验证：//控制修改用户对话框的显示与否 editDialogVisible: false, //修改用户的表单数据 editForm: { username: '', email: '', mobile: '' }, //修改表单的验证规则对象 editFormRules: { email: [ { required: true, message: '请输入邮箱', trigger: 'blur' }, { validator: checkEmail, message: '邮箱格式不正确，请重新输入', trigger: 'blur' } ], mobile: [ { required: true, message: '请输入手机号码', trigger: 'blur' }, { validator: checkMobile, message: '手机号码不正确，请重新输入', trigger: 'blur' } ] } E.监听对话框关闭事件，在对话框关闭之后，重置表单<el-dialog title="修改用户" :visible.sync="editDialogVisible" width="50%" @close="editDialogClosed"> editDialogClosed(){ //对话框关闭之后，重置表达 this.$refs.editFormRef.resetFields() } F.在用户点击确定按钮的时候，验证数据成功之后发送请求完成修改editUser() { //用户点击修改表单中的确定按钮之后，验证表单数据 this.$refs.editFormRef.validate(async valid => { if (!valid) return this.$message.error('请填写完整用户信息') //发送请求完成修改用户的操作 const { data: res } = await this.$http.put( 'users/' + this.editForm.id, this.editForm ) //判断如果修改失败，就做提示 if (res.meta.status !== 200) return this.$message.error('修改用户失败') //修改成功的提示 this.$message.success('修改用户成功') //关闭对话框 this.editDialogVisible = false //重新请求最新的数据 this.getUserList() }) } 2.删除用户在点击删除按钮的时候，我们应该跳出提示信息框，让用户确认要进行删除操作。如果想要使用确认取消提示框，我们需要先将提示信息框挂载到vue中。A.导入MessageBox组件，并将MessageBox组件挂载…

后台基本布局
type: item
date: 2022-10-22T20:09:37+00:00
description: 打开Home.vue组件，进行布局：<el-container class="home-container"> <el-header>Header<el-button type="info" @click="logout"> 退出 </el-button></el-header> <el-container> <el-aside width="200px">Aside</el-aside> <el-main>Main</el-main> </el-container> </el-container> 默认情况下，跟element-ui组件同名的类名可以帮助我们快速的给对应的组件添加样式，如：.home-container { height: 100%; } .el-header{ background-color:#373D41; } .el-aside{ background-color:#333744; } .el-main{ background-color:#eaedf1; } 2.顶部布局，侧边栏布局 <el-container class="home-container"> <el-header> 电商后台管理系统 <el-button type="info" @click="logout"> 退出 </el-button> </el-header> <el-container> <el-aside width="200px"> <el-menu background-color="#333744" text-color="#fff" active-text-color="#ffd04b"> <el-submenu index="1"> 导航一 <el-menu-item index="1-4-1"> 子菜单一 </el-menu-item> </el-submenu> </el-menu> </el-aside> <el-main>Main</el-main> </el-container> </el-container> 3.axios请求拦截器后台除了登录接口之外，都需要token权限验证，我们可以通过添加axios请求拦截器来添加token，以保证拥有获取数据的权限在main.js中添加代码，在将axios挂载到vue原型之前添加下面的代码//请求在到达服务器之前，先会调用use中的这个回调函数来添加请求头信息 axios.interceptors.request.use(config=>{ //为请求头对象，添加token验证的Authorization字段 config.headers.Authorization = window.sessionStorage.getItem("token") return config }) 4.请求侧边栏数据 通过v-for双重循环渲染左侧菜单<el-menu background-color="#333744" text-color="#fff" active-text-color="#ffd04b"> <el-submenu :index="item.id+''" v-for="item in menuList" :key="item.id"> {{item.authName}} <el-menu-item :index="subItem.id+''" v-for="subItem in item.children" :key="subItem.id"> {{subItem.authName}} </el-menu-item> </el-submenu> </el-menu> 5.设置激活子菜单样式通过更改el-menu的active-text-color属性可以设置侧边栏菜单中点击的激活项的文字颜色通过更改菜单项模板（template）中的i标签的类名，可以将左侧菜单栏的图标进行设置，我们需要在项目中使用第三方字体图标在数据中添加一个iconsObj：iconsObj: { '125':'iconfont icon-user', '103':'iconfont icon-tijikongjian', '101':'iconfont icon-shangpin', '102':'iconfont icon-danju', '145':'iconfont icon-baobiao' } 然后将图标类名进行数据绑定，绑定iconsObj中的数据：为了保持左侧菜单每次只能打开一个，显示其中的子菜单，我们可以在el-menu中添加一个属性unique-opened或者也可以数据绑定进行设置(此时true认为是一个bool值，而不是字符串) :unique-opened=…

vue电商业务概述
type: item
date: 2022-10-08T05:20:34+00:00
description: 客户使用的业务服务：PC端，小程序，移动web，移动app管理员使用的业务服务：PC后台管理端。PC后台管理端的功能：管理用户账号（登录，退出，用户管理，权限管理），商品管理（商品分类，分类参数，商品信息，订单），数据统计电商后台管理系统采用前后端分离的开发模式前端项目是基于Vue的SPA（单页应用程序）项目前端技术栈:Vue,Vue-Router,Element-UI,Axios,Echarts后端技术栈：Node.js,Express,Jwt(模拟session),Mysql,Sequelize(操作数据库的框架)2.项目初始化A.安装Vue脚手架B.通过脚手架创建项目C.配置路由D.配置Element-UI:在插件中安装，搜索vue-cli-plugin-elementE.配置Axios：在依赖中安装,搜索axios(运行依赖)F.初始化git仓库G.将本地项目托管到github或者码云中3.码云相关操作A.注册登录码云账号B.安装git在Windows上使用Git，可以从Git官网直接下载安装程序进行安装。测试命令：git --versionC.点击网站右上角“登录”，登录码云，并进行账号设置D.在本地创建公钥：在终端运行：ssh-keygen -t rsa -C "xxx@xxx.com"E.找到公钥地址：Your identification has been saved in /c/Users/My/.ssh/id_rsa.Your public key has been saved in /c/Users/My/.ssh/id_rsa.pub.当我们创建公钥完毕之后，请注意打印出来的信息“Your public key has been saved in”/c/Users/My/.ssh/id_rsa.pub : c盘下面的Users下面的My下面的.ssh下面的id_rsa.pub就是我们创建好的公钥了E.打开id_rsa.pub文件，复制文件中的所有代码，点击码云中的SSH公钥，将生成的公钥复制到公钥中G.测试公钥：打开终端，输入命令ssh -T git@gitee.comH.将本地代码托管到码云中点击码云右上角的+号->新建仓库I.进行git配置：打开项目所在位置的终端，进行git仓库关联4.配置后台项目A.安装phpStudy并导入mysql数据库数据B.安装nodeJS，配置后台项目,从终端打开后台项目vue_api_server然后在终端中输入命令安装项目依赖包：npm installC.使用postman测试api接口5.实现登录功能A.登录状态保持如果服务器和客户端同源，建议可以使用cookie或者session来保持登录状态如果客户端和服务器跨域了，建议使用token进行维持登录状态。B.登录逻辑：在登录页面输入账号和密码进行登录，将数据发送给服务器服务器返回登录的结果，登录成功则返回数据中带有token客户端得到token并进行保存，后续的请求都需要将此token发送给服务器，服务器会验证token以保证用户身份。C.添加新分支login，在login分支中开发当前项目vue_shop：打开vue_shop终端，使用git status确定当前项目状态。确定当前工作目录是干净的之后，创建一个分支进行开发，开发完毕之后将其合并到mastergit checkout -b login然后查看新创建的分支：git branch确定我们正在使用login分支进行开发然后执行vue ui命令打开ui界面，然后运行serve，运行app查看当前项目效果发现现在是一个默认页面，我们需要进行更改，打开项目的src目录，点击main.js文件（入口文件）import Vue from 'vue' import App from './App.vue' import router from './router' import './plugins/element.js' Vue.config.productionTip = false new Vue({ router, render: h => h(App) }).$mount('#app') 再打开App.vue(根组件)，将根组件的内容进行操作梳理(template中留下根节点，script中留下默认导出，去掉组件，style中去掉所有样式) <router-view></router-view> 再打开router.js(路由)，将routes数组中的路由规则清除，然后将views删除，将components中的helloworld.vue删除import Vue from 'vue' import Router from 'vue-router' Vu…

vue模块化的分类
type: item
date: 2022-10-05T23:56:37+00:00
description: A.浏览器端的模块化 1).AMD(Asynchronous Module Definition,异步模块定义) 代表产品为：Require.js 2).CMD(Common Module Definition,通用模块定义) 代表产品为：Sea.js B.服务器端的模块化 服务器端的模块化规范是使用CommonJS规范： 1).使用require引入其他模块或者包 2).使用exports或者module.exports导出模块成员 3).一个文件就是一个模块，都拥有独立的作用域 C.ES6模块化 ES6模块化规范中定义： 1).每一个js文件都是独立的模块 2).导入模块成员使用import关键字 3).暴露模块成员使用export关键字 小结：推荐使用ES6模块化，因为AMD，CMD局限使用与浏览器端，而CommonJS在服务器端使用。ES6模块化是浏览器端和服务器端通用的规范.2.在NodeJS中安装babelA.安装babel打开终端，输入命令：npm install --save-dev @babel/core @babel/cli @babel/preset-env @babel/node 安装完毕之后，再次输入命令安装：npm install --save @babel/polyfill B.创建babel.config.js在项目目录中创建babel.config.js文件。 编辑js文件中的代码如下： const presets = [ ["@babel/env",{ targets:{ edge:"17", firefox:"60", chrome:"67", safari:"11.1" } }] ] //暴露 module.exports = { presets } C.创建index.js文件在项目目录中创建index.js文件作为入口文件 在index.js中输入需要执行的js代码，例如： console.log("ok"); D.使用npx执行文件打开终端，输入命令：npx babel-node ./index.js 3.设置默认导入/导出A.默认导出export default { 成员A, 成员B, ....... },如下： let num = 100; export default{ num } B.默认导入import 接收名称 from "模块标识符"，如下： import test from "./test.js" 注意：在一个模块中，只允许使用export default向外默认暴露一次成员，千万不要写多个export default。如果在一个模块中没有向外暴露成员，其他模块引入该模块时将会得到一个空对象4.设置按需导入/导出A.按需导出export let num = 998; export let myName = "jack"; export function fn = function(){ console.log("fn") } B.按需导入import { num,fn as printFn ,myName } from "./test.js" //同时导入默认导出的成员以及按需导入的成员 import test,{ num,fn as printFn ,myName } from "./test.js" 注意：一个模块中既可以按需导入也可以默认导入，一个模块中既可以按需导出也可以默认导出5.直接导入并执行代码import "./test2.js"; 6.webpack的概念webpack是一个流行的前端项目构建工具，可以解决目前web开发的困境。webpack提供了模块化支持，代码压缩混淆，解决js兼容问题，性能优化等特性，提高了开发效率和项目的可维护性7.webpack的基本使用A.创建项目目录并初始化创建项目，并打开项目所在目录的终端，输入命令： npm init -y B.创建首页及js文件在项目目录中创建index.html页面，并初始化页面结构：在页面中摆放一个ul，ul里面放置几个li 在项目目录中创建js文件夹，并在文件夹中创建index.js文件 C.安装jQuery打开项目目录终端，输入命令: npm install jQuery -S D.导入jQuery打开index.js文件，编写代码导入jQuery并实现功能： import $ from "jquery"; $(function(){ $("li:odd").css("background","cyan"); $("li:odd").css("background","pink"); }) 注意：此时项目运行会有错误，因为import $ from "jquery";这句代码属于ES6的新…

vue路由
type: item
date: 2022-10-04T23:24:55+00:00
description: 路由的本质就是一种对应关系，比如说我们在url地址中输入我们要访问的url地址之后，浏览器要去请求这个url地址对应的资源。 那么url地址和真实的资源之间就有一种对应的关系，就是路由 路由分为前端路由和后端路由1).后端路由是由服务器端进行实现，并完成资源的分发2).前端路由是依靠hash值(锚链接)的变化进行实现后端路由性能相对前端路由来说较低，所以，我们接下来主要学习的是前端路由前端路由的基本概念：根据不同的事件来显示不同的页面内容，即事件与事件处理函数之间的对应关系前端路由主要做的事情就是监听事件并分发执行事件处理函数2.前端路由的初体验前端路由是基于hash值的变化进行实现的（比如点击页面中的菜单或者按钮改变URL的hash值，根据hash值的变化来控制组件的切换）核心实现依靠一个事件，即监听hash值变化的事件window.onhashchange = function(){ //location.hash可以获取到最新的hash值 location.hash } 前端路由实现tab栏切换： Document 主页 科技 财经 娱乐 <component :is="comName"></component> 案例效果图：点击每个超链接之后，会进行相应的内容切换，如下：核心思路：在页面中有一个vue实例对象，vue实例对象中有四个组件，分别是tab栏切换需要显示的组件内容在页面中有四个超链接，如下：主页 科技 财经 娱乐 当我们点击这些超链接的时候，就会改变url地址中的hash值，当hash值被改变时，就会触发onhashchange事件在触发onhashchange事件的时候，我们根据hash值来让不同的组件进行显示：window.onhashchange = function() { // 通过 location.hash 获取到最新的 hash 值 console.log(location.hash); switch(location.hash.slice(1)){ case '/zhuye': //通过更改数据comName来指定显示的组件 //因为 <component :is="comName"></component> ，组件已经绑定了comName vm.comName = 'zhuye' break case '/keji': vm.comName = 'keji' break case '/caijing': vm.comName = 'caijing' break case '/yule': vm.comName = 'yule' break } } 3.Vue Router简介它是一个Vue.js官方提供的路由管理器。是一个功能更加强大的前端路由器，推荐使用。Vue Router和Vue.js非常契合，可以一起方便的实现SPA(single page web application,单页应用程序)应用程序的开发。Vue Router依赖于Vue，所以需要先引入Vue，再引入Vue RouterVue Router的特性：支持H5历史模式或者hash模式支持嵌套路由支持路由参数支持编程式路由支持命名路由支持路由导航守卫支持路由过渡动画特效支持路由懒加载支持路由滚动行为4.Vue Router的使用步骤(★★★)A.导入js文件B.添加路由链接:是路由中提供的标签，默认会被渲染为a标签，to属性默认被渲染为href属性，to属性的值会被渲染为#开头的hash地址UserLoginC.添加路由填充位（路由占位符）D.定义路由组件var User = { template:"This is User" }var Login = { template:"This is Login" }E.配置路由规则并创建路由实例var myRouter = new VueRouter({//routes是路由规则数组routes:[//每一个路由规则都是一个对象，对象中至少包含path和component两个属性//path表示 路由匹配的hash地址，component表示路由规则对应要展示的组件对象{path:"/user",component:User},{path:"/login",component:Login}]})F.将路由挂载到Vue实例中new Vue({el:"#app",//通过router属性挂载路由对象router:myRouter})小结：Vue Router的使用步骤还是比较清晰的，按照步骤一步一步就能完成路由操作A.导入js文件B.添加路由链接C.添加路由占位符(最后路由展示的组件就会在占位符的位置显示)D.定义路由组件E.配置路由规则并创建路由实例F.将路由挂载到Vue实例中补充：…

vue接口调用方式
type: item
date: 2022-10-03T16:51:58+00:00
description: 原生ajax 基于jQuery的ajax fetch axios 异步 JavaScript的执行环境是「单线程」 所谓单线程，是指JS引擎中负责解释和执行JavaScript代码的线程只有一个，也就是一次只能完成一项任务，这个任务执行完后才能执行下一个，它会「阻塞」其他任务。这个任务可称为主线程 异步模式可以一起执行多个任务 JS中常见的异步调用 定时任何 ajax 事件函数 promise 主要解决异步深层嵌套的问题 promise 提供了简洁的API 使得异步操作更加容易 基于Promise发送Ajax请求 Promise 基本API实例方法.then() 得到异步任务正确的结果 .catch() 获取异常信息 .finally() 成功与否都会执行（不是正式标准） 静态方法.all() Promise.all方法接受一个数组作参数，数组中的对象（p1、p2、p3）均为promise实例（如果不是一个promise，该项会被用Promise.resolve转换为一个promise)。它的状态由这三个promise实例决定 .race() Promise.race方法同样接受一个数组作参数。当p1, p2, p3中有一个实例的状态发生改变（变为fulfilled或rejected），p的状态就跟着改变。并把第一个改变状态的promise的返回值，传给p的回调函数 ​ fetch Fetch API是新的ajax解决方案 Fetch会返回Promise fetch不是ajax的进一步封装，而是原生js，没有使用XMLHttpRequest对象。 fetch(url, options).then(） fetch API 中的 HTTP 请求 fetch(url, options).then(） HTTP协议，它给我们提供了很多的方法，如POST，GET，DELETE，UPDATE，PATCH和PUT 默认的是 GET 请求 需要在 options 对象中 指定对应的 method method:请求使用的方法 post 和 普通 请求的时候 需要在options 中 设置 请求头 headers 和 body fetchAPI 中 响应格式 用fetch来获取数据，如果响应正常返回，我们首先看到的是一个response对象，其中包括返回的一堆原始字节，这些字节需要在收到后，需要我们通过调用方法将其转换为相应格式的数据，比如JSON，BLOB或者TEXT等等 /* Fetch响应结果的数据格式 */ fetch('http://localhost:3000/json').then(function(data){ // return data.json(); // 将获取到的数据使用 json 转换对象 return data.text(); // // 将获取到的数据 转换成字符串 }).then(function(data){ // console.log(data.uname) // console.log(typeof data) var obj = JSON.parse(data); console.log(obj.uname,obj.age,obj.gender) }) axios 基于promise用于浏览器和node.js的http客户端 支持浏览器和node.js 支持promise 能拦截请求和响应 自动转换JSON数据 能转换请求和响应数据 axios基础用法 get和 delete请求传递参数 通过传统的url 以 ? 的形式传递参数 restful 形式传递参数 通过params 形式传递参数 post 和 put 请求传递参数 通过选项传递参数 通过 URLSearchParams 传递参数 # 1. 发送get 请求 axios.get('http://localhost:3000/adata').then(function(ret){ # 拿到 ret 是一个对象 所有的对象都存在 ret 的data 属性里面 // 注意data属性是固定的用法，用于获取后台的实际数据 // console.log(ret.data) console.log(ret) }) # 2. get 请求传递参数 # 2.1 通过传统的url 以 ? 的形式传递参数 axios.get('http://localhost:3000/axios?id=123').then(function(ret){ console.log(ret.data) }) # 2.2 restful 形式传递参数 axios.get('http://localhost:3000/axios/123').then(function(ret){ co…

vue组件
type: item
date: 2022-09-24T06:07:40+00:00
description: 组件 (Component) 是 Vue.js 最强大的功能之一 组件可以扩展 HTML 元素，封装可重用的代 组件注册全局注册 Vue.component('组件名称', { }) 第1个参数是标签名称，第2个参数是一个选项对象 全局组件注册后，任何vue实例都可以用 组件基础用 <my-component></my-component> 组件注意事项 组件参数的data值必须是函数同时这个函数要求返回一个对象 组件模板必须是单个根元素 组件模板的内容可以是模板字符串 <button-counter></button-counter> <button-counter></button-counter> <button-counter></button-counter> <hello-world></hello-world> 局部注册 只能在当前注册它的vue实例中使用 <my-component></my-component> Vue 调试工具Vue组件之间传值父组件向子组件传值 父组件发送的形式是以属性的形式绑定值到子组件身上。 然后子组件用属性props接收 在props中使用驼峰形式，模板中需要使用短横线的形式字符串形式的模板中没有这个限制 {{pmsg}} <menu-item title='来自父组件的值'></menu-item> <menu-item :title='ptitle' content='hello'></menu-item> 子组件向父组件传值 子组件用$emit()触发事件 $emit() 第一个参数为 自定义的事件名称 第二个参数为需要传递的数据 父组件用v-on 监听子组件的事件 {{pmsg}} <menu-item :parr='parr' @enlarge-text='handle($event)'></menu-item> 兄弟之间的传递 兄弟之间传递数据需要借助于事件中心，通过事件中心传递数据 提供事件中心 var hub = new Vue() 传递数据方，通过一个事件触发hub.$emit(方法名，传递的数据) 接收数据方，通过mounted(){} 钩子中 触发hub.$on()方法名 销毁事件 通过hub.$off()方法名销毁之后无法进行传递数据 父组件 销毁事件 <test-tom></test-tom> <test-jerry></test-jerry> 组件插槽 组件的最大特性就是复用性，而用好插槽能大大提高组件的可复用能力 匿名插槽 <alert-box>有bug发生</alert-box> <alert-box>有一个警告</alert-box> <alert-box></alert-box> 具名插槽 具有名字的插槽 使用 中的 "name" 属性绑定元素 <base-layout> 标题信息 主要内容1 主要内容2 底部信息信息 </base-layout> <base-layout> 标题信息1 标题信息2 主要内容1 主要内容2 底部信息信息1 底部信息信息2 </base-layout> 作用域插槽 父组件对子组件加工处理 既可以复用子组件的slot，又可以使slot内容不一致 <fruit-list :list='list'> <!-- 2、 父组件中使用了 元素,而且包含scope="slotProps", slotProps在这里只是临时变量 ---> {{slotProps.info.name}} {{slotProps.info.name}} </fruit-list> 购物车案例1. 实现组件化布局 把静态页面转换成组件化模式 把组件渲染到页面上 <my-cart></my-cart> 2、实现 标题和结算功能组件 标题组件实现动态渲染 从父组件把标题数据传递过来 即 父向子组件传值 把传递过来的数据渲染到页面上 结算功能组件 从父组件把商品列表list 数据传递过来 即 父向子组件传值 把传递过来的数据计算最终价格渲染到页面上 <my-cart></my-cart> 3. 实现列表组件删除功能 从父组件把商品列表list 数据传递过来 即 父向子组件传值 把传递过来的数据渲染到页面上 点击删除按钮的时候删除对应的数据 给按钮添加点击事件把需要删除的id传递过来 子组件中不推荐操作父组件的数据有可能多个子组件使用父组件的数据 我们需要把数据传递给父组件让父组件操作数据 父组件删除对应的数据 <my-cart></my-cart> 4. 实现组件更新数据功能 上 将输入框中的默认数据动态渲染出来 输入框失去焦点的时候 更改商品的数量 子组件中不推荐操作数据 把这些数据传递给父组件 让父组件处理这些数据 父组件中接收子组件传递过来的数据并处理 …