2. 常见需求

01. 父子组件通信

a. 父 -> 子(父组件传递数据给子组件)

使用 props,具体查看文档 - 使用 Prop 传递数据(cn.vuejs.org/v2/guide/co…

b. 父 -> 子(在父组件上调用子组件内的方法)

使用 ref,具体查看文档 - 子组件索引(cn.vuejs.org/v2/guide/co…

<!--父组件 template-->
<div id="parent">
<!--子组件-->
<user-profile ref="profile"></user-profile>
</div>
// 父组件 script
this.$refs.profile.someMethod();

注意:如果在子组件上设置 ref 属性,则可以通过 this.$refs 获取到该子组件对象,如果在普通的 html 标签上设置 ref 属性,则获取到的是 Dom 节点。

c. 子 -> 父(在父组件上获取子组件内的数据)

同上,也是利用 ref

// 父组件 script
let childData = this.$refs.profile.someData;

d. 子 -> 父(子组件内触发事件,父组件监听事件)

父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件,具体查看文档 - 使用 v-on 绑定自定义事件(cn.vuejs.org/v2/guide/co…

<!--父组件 template-->
<div id="parent">
<!--子组件-->
<user-profile @childTrigger="parentHandle"></user-profile>
</div>
// 父组件 script
methods: {
parentHandle(params){
// 这个方法在子组件 emit childTrigger 事件后会执行
// params 为子组件里触发事件时传的参数
}
}
// 子组件 user-profile script
this.$emit('childTrigger', params);

e. 子 -> 父(子组件传值,父组件里使用,具体实现见 03

01总结:
应用场景示例:在父组件上打开侧边栏子组件,可以传 prop visible(true)来控制侧边栏打开;侧边栏内部有关闭按钮,就在点击关闭按钮后触发一个事件,父组件监听事件执行方法将 data visible 改为 false
PS:父组件传值到子组件,传的值是 Object 类型,子组件使用 v-model 可以修改该值(将某个表单元素的 v-model 设为该值),父组件可直接获取到改变后的值。

02. 全局函数

有时候会用到一些工具类函数,希望可以全局调用,而不是局限于某个组件中。

Step 1:
项目根目录/static/js/ 目录下新建一个 util.js 文件,将常用的工具函数写在这里面。

Step 2:
index.html 里面引入 util.js,就可以在 .vue 文件里使用那些方法了,如下:

<body>
<div id="app"></div>
<!-- 引入常用 js 方法 -->
<script type="text/javascript" src="/static/js/util.js"></script>
<!-- built files will be auto injected -->
</body>

02总结:
使用这个方法可以使得一些使用频率高的函数可以在所有 .vue 文件中被调用,笨拙而又简单。

03. slot

以前看文档时一直不理解如何使用 slot,现在用多了 elementui 的组件之后,就渐渐发现了它的实用性。
简单来说,使用 slot 可以使我们做到:在父组件里使用子组件时,在子组件里插入一些自定义的内容(html 代码啥的),具体查看文档:cn.vuejs.org/v2/guide/co…
更神奇的功能是 作用域插槽,可以让我们在父组件里使用子组件时,获取子组件传来的数据,具体查看文档:cn.vuejs.org/v2/guide/co…

简单应用示例

<!-- a-button 子组件 -->
<button type="button" class="a-button" @click="$emit('btn-click')"><slot></slot></button>
<!-- 这里监听了 button 的 click 事件,然后又触发了 btn-click 事件 -->
<!-- 父组件 -->
<a-button @btn-click="handleClick">这里写的东西会覆盖子组件里的 slot 标签所在的位置</a-button>
<!-- 这里监听了子元素触发的 btn-click 事件,然后执行 handleClick 函数 -->

渲染结果:

<button type="button" class="a-button">这里写的东西会覆盖子组件里的 slot 标签所在的位置</button>

可以应用简单的 slot 来达到为不同的按钮填充文字的目的:

<a-button @click="handleClick">详情</a-button>
<a-button @click="handleClick">搜索</a-button> <!-- 渲染结果 -->
<button type="button" class="a-button">详情</button>
<button type="button" class="a-button">搜索</button>

作用域插槽示例

<!-- 子组件 -->
<div class="child">
<!-- slot 这个位置会在子组件被使用时被父组件传来的 html 代码覆盖 -->
<!-- slot 上的 text/child 就相当于传给父组件的 props (假设 name 为子组件的 data,name: someChild) -->
<slot text="hello from child" :child="name"></slot>
</div>

在父级中,具有特殊属性 scope<template> 元素,表示它是作用域插槽的模板。scope 的值对应一个临时变量名,此变量接收从子组件中传递的 prop 对象:

<!-- 父组件 -->
<div class="parent">
<child>
<template scope="props">
<span>hello from parent</span>
<span>{{ props.text }}</span>
<span>{{ props.child }}</span>
</template>
</child>
</div>

渲染结果:

<div class="parent">
<div class="child">
<span>hello from parent</span>
<span>hello from child</span>
<span>someChild</span>
</div>
</div>

03总结:
应用场景示例:elementui 的 button 组件中有简单插槽的使用,table 组件则使用到了 作用域插槽

<!-- button 组件 -->
<el-button>默认按钮</el-button>
<el-button type="primary">主要按钮</el-button>
<el-button type="text">文字按钮</el-button> <!-- table 组件 -->
<el-table
:data="tableData">
<el-table-column
prop="zip"
label="邮编"
width="120">
</el-table-column>
<el-table-column
fixed="right"
label="操作"
width="100">
<template scope="scope">
<el-button
<!-- 可以通过 scope.$index 获取到当前行的索引 -->
@click.native.prevent="deleteRow(scope.$index)">
移除
</el-button>
</template>
</el-table-column>
</el-table>

04. router 使用小记

vue-router 的使用,简单来说就是通过配置,实现在不同的 url 路径下,页面渲染不同的组件。具体查看文档:vue-router 2

使用示例
一级路由:

<!-- App.vue -->
<!-- 该组件为最高级父组件,使用 router-view 来根据路径确定要显示的子组件 -->
<template>
<div id="app">
<!-- router-view 位置用来显示组件,如显示下面的 index.vue -->
<router-view></router-view>
</div>
</template>

二级路由(路由可嵌套):

<!-- page/index.vue -->
<!-- 该组件包含一个顶部栏和侧边菜单栏,内容区使用 router-view 来根据 url 路径显示子组件 -->
<template>
<div class="index">
<!-- 顶部导航条 -->
<header class="main-header">
...
</header>
<!-- /顶部导航条 -->
<!-- 侧边导航栏 -->
<aside class="main-sidebar sidebar-gradient">
...
</aside>
<!-- /侧边导航栏 -->
<!-- 根据页面一级菜单的点击而进行切换的内容区 -->
<transition name="fade">
<!-- router-view 位置用来显示组件 -->
<router-view></router-view>
</transition>
<!-- /内容区 -->
</div>
</template>

router 配置:

// router/index.js

import Vue from 'vue';
import Router from 'vue-router';
// 引入组件
import index from 'page/index'; // 该组件包含一个顶部栏和侧边菜单栏,内容区使用 router-view 来根据 url 路径显示子组件
import notFoundComponent from 'page/404'; // 该组件为 404 页面,当你路由使用 history 模式时需要用到
import monitorIndex from 'page/monitor/index'; // 该组件为一个监控页面,用于显示在 page/index.vue 页面上的 router-view 处(即页面的内容区域) Vue.use(Router); // 定义 scrollBehavior 方法
const scrollBehavior = (to, from, savedPosition) => {
if (savedPosition) {
return savedPosition
} else {
return { x: 0, y: 0 }
}
} export default new Router({
mode: 'history',
// mode 默认 hash 值,但是 hash (url中包含 # 符号)不太好看也不符合我们一般的网址浏览习惯
// 当你使用 history 模式时,URL 就像正常的 URL,例如 http://yoursite.com/user/id,也好看! linkActiveClass: 'active',
// 默认值: 'router-link-active',就是当前组件被激活,相应路由会自动添加类 'router-link-active',这里是为了全局设置激活类名,如果不设置,直接用默认的也是可以的
// 如:使用 router-link 组件来导航,通过传入 `to` 属性指定链接
// <router-link to="/foo">Go to Foo</router-link>
// <router-link> 默认会被渲染成一个 `<a>` 标签,'/foo' 路由下的组件显示时,该 a 标签上会自动添加类 'active' scrollBehavior: scrollBehavior,
// 通过这个属性(是个函数),可以让应用像浏览器的原生表现那样,在按下 后退/前进 按钮时,简单地让页面滚动到顶部或原来的位置,如果不设置,则组件切换时滚动条位置不变 routes: [
{
// 一级路由
path: '/',
component: index,
children: [
// 二级路由
// -----------默认首页-------------
// 当 / 匹配成功,monitorIndex 会被渲染在 index 的 <router-view> 中
{ path: '', component: monitorIndex, alias: 'index.html' },
// 这里的 alias 'index.html' 为当前页面的别名
// http://localhost:8080/index.html 等同于 http://localhost:8080/ // -----------监控中心-------------
{
// 当 /monitor 匹配成功,
// monitorIndex 会被渲染在 index 的 <router-view> 中
path: 'monitor',
name: '监控中心',
component: monitorIndex
}
]
}, // 同一个路径可以匹配多个路由,此时,匹配的优先级就按照路由的定义顺序:谁先定义的,谁的优先级就最高
// 因此下面的路由配置为备用,如果某个路径未被配置显示相应的组件,则显示 404 页面
{ path: '*', component: notFoundComponent }
]
});

引入 router 配置:

// main.js 

import Vue from 'vue';

// 引入 element ui 组件
import { Dropdown, DropdownMenu ...} from 'element-ui'; // 引入 App.vue
import App from './App'; // 引入 router 配置
import router from './router'; // 默认会找到 router 文件夹下的 index.js 文件 // 引入项目图标的 sprite css,可以简单的通过这种方式引入 css 文件
import './assets/css/sprite.css' // 使用 element ui 组件
Vue.use(Dropdown)
Vue.use(DropdownMenu)
... new Vue({
el: '#app',
router, // 使用 router 配置
template: '<App/>',
components: { App },
});

04总结:
关于 vue-router 的使用,看文档一般都能解决你的疑问,vue-router 2
其他参考文章:Vue.js系列之vue-router(中)(4)
PS:使用 history 模式的话,还需要 后台配置 支持。因为我们的应用是个单页客户端应用,如果后台没有正确的配置,当用户在浏览器直接访问 http://oursite.com/user/id 就会返回 404(因为的确找不到该页面),这就不好看了。并且在后台配置后,还需要前端来提供 404 页面,我上面的示例代码中有提到,可供参考。

05. 测试接口

使用 Vue 开发单页应用时,前后端分离开发,进度不一。因此前端有时候就需要自己模拟接口的 json 文件,然后直接使用异步请求方法(如 ajax) 去获取数据,渲染页面,测试代码等。

Step 1:
项目根目录/static/api/ 目录下新建一个 test.json 文件,写入模拟的接口数据:

{
"status": true,
"data": {
...
}
}

Step 2:
.vue 组件文件里任意需要请求数据的方法里(如 created 钩子,或者某个 methods 方法里)编写相关代码:

let vm = this;
// ajax 请求数据
$.ajax({
type: 'GET',
url: 'static/api/test.json',
data: '',
beforeSend: function() {
// 显示 Loading
vm.loading = true;
},
complete: function() {
// 隐藏 Loading
vm.loading = false;
},
success: function(data) {
// 处理返回数据
...
},
error: function() {
// 数据请求失败,给用户适当的反馈信息
...
},
dataType: 'json'
});

05总结:
在后端尚未提供接口时,我都是用这个方法来测试前端获取数据和处理数据的代码是否正确。

3. 零碎问题

01. prop 传值小技巧

我们可以为组件的 props 指定验证规格。如果传入的数据不符合规格,Vue 会发出警告。当组件给其他人使用时,这很有用。

示例如下:

  props: {
// 基础类型检测 (`null` 意思是任何类型都可以)
propA: Number,
// 多种类型
propB: [String, Number],
// 必传且是字符串
propC: {
type: String,
required: true
},
// 数字,有默认值
propD: {
type: Number,
default: 100
},
// 数组/对象的默认值应当由一个工厂函数返回
propE: {
type: Object,
default: function () {
return { message: 'hello' }
}
},
// 自定义验证函数
propF: {
validator: function (value) {
return value > 10
}
}
}

愚蠢的我每次想要传 Number 或者 Boolean 类型的值到子组件时,都在父组件里定义好值,然后再绑定到子组件上:

// 这样会报错,因为 show type 为 Boolean,rows type 为 Number
// 默认情况下直接传值,子组件接收到的都是 String 类型 // template
<child show="true" rows="6"></child>
// 于是我这样做:

// template
<child :show="show" :rows="rows"></child> // script
show: true,
rows: 6
// 实际上可以直接这样做:

// template
<child :show="true" :rows="6"></child> // 官网如是说:如果想传递一个实际的 number,需要使用 v-bind ,从而让它的值被当作 JavaScript 表达式计算。

小技巧:当某个 prop 类型为 Boolean 时,可以直接把该 prop 的名称写在组件上,默认会传 true,不写的话默认为 false。比如 <child show :rows="6"></child> 这么写,子组件内部就能收到 show 为 true。

02. autoprefixer

有些人会问如何在项目里使用 autoprefixer 插件,事实上使用 vue-cliwebpack 模板生成的项目里已经带有 autoprefixer 的使用了,如下图:

autoprefixer

03. build 时不生成 .map 文件

对项目进行 npm run build 操作后,发现生成的文件超大(比想象中的大),尤其是那些 .map 文件,不过,我们可以通过配置选择不生成该类文件。

// 项目根目录/config/index.js

var path = require('path')

module.exports = {
build: {
...
productionSourceMap: false, // 将该值设为 false,就不会生成 .map 文件了 // Gzip off by default as many popular static hosts such as
// Surge or Netlify already gzip all static assets for you.
// Before setting to `true`, make sure to:
// npm install --save-dev compression-webpack-plugin
productionGzip: false,
productionGzipExtensions: ['js', 'css'],
...
},
dev: {
...
}
}

原文链接:https://juejin.im/post/58f37bfe5c497d006c90ca28

【转载】Vue 2.x 实战之后台管理系统开发(二)的更多相关文章

  1. [转载]Vue 2.x 实战之后台管理系统开发(一)

    2. 开发前须知 我的后台管理系统项目运用了如下框架/插件: Vue 2.x —— 项目所使用的 js 框架,我所使用的版本是:2.1.10 vue-router 2 —— Vue 2.x 配套路由, ...

  2. asp.net mvc+jquery easyui开发实战教程之网站后台管理系统开发4- 后台模板html页面创建

    上一篇教程<asp.net mvc+jquery easyui开发实战教程之网站后台管理系统开发3-登录模块开发>完成了本项目的登录模块,登录后就需要进入后台管理首页了,需要准备一个后台模 ...

  3. asp.net mvc+jquery easyui开发实战教程之网站后台管理系统开发2-Model层建立

    上篇(asp.net mvc+jquery easyui开发实战教程之网站后台管理系统开发1-准备工作)文章讲解了开发过程中的准备工作,主要创建了项目数据库及项目,本文主要讲解项目M层的实现,M层这里 ...

  4. vue-manage-system 后台管理系统开发总结

    前言 vue-manage-system,一个基于 Vue.js 和 element-ui 的后台管理系统模板,从2016年年底第一个commit,到现在差不多两年了,GitHub上也有了 5k st ...

  5. 简易版CMS后台管理系统开发流程

    目录 简易版CMS后台管理系统开发流程 MVC5+EF6 简易版CMS(非接口) 第一章:新建项目 MVC5+EF6 简易版CMS(非接口) 第二章:建数据模型 MVC5+EF6 简易版CMS(非接口 ...

  6. vue从入门到女装??:从零开始搭建后台管理系统(二)用vue-docute生成线上文档

    教程 vue从入门到女装??:从零开始搭建后台管理系统(一)安装框架 一个系统开发完成了总要有操作说明手册,接口文档之类的东西吧?这种要全部纯手写就很麻烦了,可以借助一些插件,比如: vue-docu ...

  7. 如何使用Vue.js来搭建一个后台管理系统

    目录 使用的技术 基础但不好版 1.初始化项目 2.实现初始页内容自定义 3.使用路由 原始代码 自建页面 修改路由 4.测试路由跳转 补充 子路由版 嵌套router-view 定义子路由 修改菜单 ...

  8. asp.net mvc+jquery easyui开发实战教程之网站后台管理系统开发3-登录模块开发

    进行本文之前需要在数据库用户表里面增加一条用户数据,直接手动添加即可,未安全考虑密码一定要使用Md5加密后的,这里提供666666的Md5密文为(c831b04de153469d),本文完成登录模块的 ...

  9. asp.net mvc+jquery easyui开发实战教程之网站后台管理系统开发1-准备工作

    /****** Object: 新闻表 Script Date: 2017/9/2 星期六 15:11:12 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENT ...

随机推荐

  1. SQL查询速度慢的原因分析和解决方案

    SQL查询速度慢的原因分析和解决方案 查询速度慢的原因很多,常见如下几种: 1.没有索引或者没有用到索引(这是查询慢最常见的问题,是程序设计的缺陷) 2.I/O吞吐量小,形成了瓶颈效应. 3.没有创建 ...

  2. ES6学习之const声明常量的学习

    在ES中const关键字用来声明常量,const声明的一经定义不能修改 和let特性差不多, ; console.log(a); a = ; //报错 const定义完常量后必须赋值,后面不允许再次赋 ...

  3. Linux基础实验(二)

    一)基础实验: 1. 新建文件a.txt,并用权限模式.权限值两种方式修改权限为rwxrwx--x     新建文件:touch a.txt    权限模式:chmod ug=rwx o=x a.tx ...

  4. PAT乙级1091-1095

    1091 N-自守数 (15 分) 如果某个数 K 的平方乘以 N 以后,结果的末尾几位数等于 K,那么就称这个数为“N-自守数”.例如 3,而 2 的末尾两位正好是 9,所以 9 是一个 3-自守数 ...

  5. “全栈2019”Java异常第六章:finally代码块作用域详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java异 ...

  6. 使用html2canvas截图并用jspdf打印的问题

    之前的方案确实可以打印出a4的大小的pdf,但是也呈现了诸多问题,因为这种方法是截图然后再进行打印的,所以打印出来的效果是模糊的,思前想后决定放弃了这种方式. 最终还是决定使用浏览器自带的打印方法. ...

  7. COGS1752. [BOI2007]摩基亚Mokia(CDQ,树状数组)

    题目描述 摩尔瓦多的移动电话公司摩基亚(Mokia)设计出了一种新的用户定位系统.和其他的定位系统一样,它能够迅速回答任何形如“用户C的位置在哪?”的问题,精确到毫米.但其真正高科技之处在于,它能够回 ...

  8. C++中重载、覆盖和隐藏

    一,多态性 1,(1)声明了基类的指针,该指针指向基类,该指针永远调用自己的成员函数,不管函数是否为虚函数. (2)声明了派生类的指针,该指针指向该派生类,该指针永远调用自己的成员函数,不管函数是否为 ...

  9. C#控制台输出退格实现变换闪烁的字符效果

    C#控制台输出退格实现变换闪烁的字符效果,传统的Console.Clear()方法能清除控制台上的所有内容. 如果用 Console.Write('\u0008');可以实现输出退格,这样就可以方便地 ...

  10. linux安装spark-2.3.0集群

    (安装spark集群的前提是服务器已经配置了jdk并且安装hadoop集群(主要是hdfs)并正常启动,hadoop集群安装可参考<hadoop集群搭建(hdfs)>) 1.配置scala ...