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. 自己从0开始学习Unity的笔记 V (C#的数组练习)

    今天练习了数组输入,先从最简单的开始,因为我输入完这些之后,觉得应该有更简单的方法,先来介绍一下我做的练习代码 //做一个最多能容纳10个数字的,用户可以输入任意1-10个数字,判断长度,输出数字 ] ...

  2. Asp.NetCore安全验证之JWT

    本文只是介绍了下基于AspNetCore自带的System.IdentityModel.Tokens.Jwt.dll工具在项目中Token的应用. 我这里谈到的很浅显就两点: 一,超时时间 二,数据的 ...

  3. Cesium开发实践汇总

    一.简介.开发环境搭建 二.Viewer控件 三.地图图层介绍 四.地形介绍 五.坐标变换 六.CZML 七.3D模型

  4. 【VS2015】故障修复之dep6100,dep6200

    问题描述:把uwp程序往手机上(或者往模拟器上)部署时,vs ide提示我错误信息dep6100和dep6200,报告说“连接不到设备”. 这可把我愁坏了,各种方法都不行,最后发现问题出在Hyper- ...

  5. 正则表达式的Wed验证应用(40)

    电子邮件地址的校验 <?php /* 校验邮件地址*/ function checkMail($email) { //用户名,由“\w”格式字符.“-”或“.”组成 $email_name= & ...

  6. 516. Longest Palindromic Subsequence

    Given a string s, find the longest palindromic subsequence's length in s. You may assume that the ma ...

  7. 【ocp-12c】最新Oracle OCP-071考试题库(43题)

    43.(9-2)choose three Which three tasks can be performed by DDL statements? A) preventing data retrie ...

  8. 手动启动 oracle 服务

      手动启动 Oracle 服务 为了学习,我们常常会在个人PC上安装 Oracle 数据库,这大大影响了计算机的运行速度,尤其是计算机开机速度,如果 Oracle 使用频率并不是非常高,我们可以禁止 ...

  9. Python【每日一问】16

    问: [基础题]TCP/UDP/HTTP协议区别 [提高题]在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数, ...

  10. poj 2796 Feel Good单调栈

    Feel Good Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 20408   Accepted: 5632 Case T ...