1.内置组件component
渲染一个“元组件”为动态组件。依 is 的值,来决定哪个组件被渲染。
vue内置组件
<template>
<component
:is="viewName"
@updateView="updateView"
>
</component>
</template>
<script>
import studentGrowthPortfolio from './studentGrowthPortfolio.vue'; //学生 index
import fileDetails from './fileDetails.vue'; //成长档案 详情
export default {
data(){
return{
viewName:"studentGrowthPortfolio",
}
},
components:{
studentGrowthPortfolio,
fileDetails
},
mounted(){
this.viewName=this.$route.query.viewName?this.$route.query.viewName:this.viewName;
},
created () {
},
methods:{
/**
* 接收子组件数据
* @param data {Object}
* @return {Void} 无
*/
updateView(name){
this.viewName = name
if(!name){
this.$routePlugin.delQuery('viewName');
}else{
this.$routePlugin.addQuery({viewName:name});
}
},
},
}
</script>
<style scoped lang="less">
@import "~@/libs/less/theme/theme.less";
</style>
2.vue中使用svg-icon
1 在src目录新建一个icons目录,icons下添加svg文件夹,svg下面放iconfont的icon标签的svg标签文件,安装依赖
npm install svg-sprite-loader --save-dev
2.icons目录下建index.js
import Vue from 'vue'
import SvgIcon from '@/components/SvgIcon'// svg组件
// register globally
Vue.component('svg-icon', SvgIcon)
const requireAll = requireContext => requireContext.keys().map(requireContext)
const req = require.context('./svg', false, /\.svg$/)
const iconMap = requireAll(req)
3.封装一下icon,在components下新建SvgIcon文件
<template>
<svg :class="svgClass" aria-hidden="true">
<use :xlink:href="iconName"/>
</svg>
</template>
<script>
export default {
name: 'SvgIcon',
props: {
iconClass: {
type: String,
required: true
},
className: {
type: String,
default: ''
}
},
computed: {
iconName() {
return `#icon-${this.iconClass}`
},
svgClass() {
if (this.className) {
return 'svg-icon ' + this.className
} else {
return 'svg-icon'
}
}
}
}
</script>
<style scoped>
.svg-icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
</style>
4.在main.js中引入svg组件
5.vue.config.js的配置
'use strice'
const path = require('path')
const isProd = process.env.NODE_ENV === 'production'
const defaultSettings = require('./src/settings.js')
const name = defaultSettings.title || 'vue Element Admin' // page title
function resolve(dir) {
return path.join(__dirname, dir)
}
// All configuration item explanations can be find in https://cli.vuejs.org/config/
module.exports = {
/**
* You will need to set publicPath if you plan to deploy your site under a sub path,
* for example GitHub Pages. If you plan to deploy your site to https://foo.github.io/bar/,
* then publicPath should be set to "/bar/".
* In most cases please use '/' !!!
* Detail: https://cli.vuejs.org/config/#publicpath
*/
publicPath: isProd ? './' : '/',
lintOnSave: !isProd,
// productionSourceMap: false,
devServer: {
open: true,
overlay: {
warnings: false,
errors: true,
},
// before: require('./mock/mock-server.js'),
proxy: {
[process.env.VUE_APP_BASE_API]: {
target: process.env.VUE_APP_REMOTE_URL,
changeOrigin: true,
pathRewrite: {
['^' + process.env.VUE_APP_BASE_API]: '',
},
},
},
},
configureWebpack: {
// provide the app's title in webpack's name field, so that
// it can be accessed in index.html to inject the correct title.
name: name,
},
chainWebpack(config) {
// set svg-sprite-loader
config.module.rule('svg').exclude.add(resolve('src/icons')).end()
config.module
.rule('icons')
.test(/\.svg$/)
.include.add(resolve('src/icons'))
.end()
.use('svg-sprite-loader')
.loader('svg-sprite-loader')
.options({
symbolId: 'icon-[name]',
})
.end()
// set preserveWhitespace
config.module
.rule('vue')
.use('vue-loader')
.loader('vue-loader')
.tap(options => {
options.compilerOptions.preserveWhitespace = true
return options
})
.end()
config.when(isProd, config => {
config
.plugin('preload')
.tap(options => {
options[0].fileBlacklist = options[0].fileBlacklist || []
options[0].fileBlacklist.push(/runtime\..*\.js$/)
return options
})
.end()
config
.plugin('ScriptExtHtmlWebpackPlugin')
.after('html')
.use('script-ext-html-webpack-plugin', [
{
// `runtime` must same as runtimeChunk name. default is `runtime`
inline: /runtime\..*\.js$/,
},
])
.end()
config.optimization.splitChunks({
chunks: 'all',
cacheGroups: {
libs: {
name: 'chunk-libs',
test: /[\\/]node_modules[\\/]/,
priority: 10,
chunks: 'initial', // only package third parties that are initially dependent
},
elementUI: {
name: 'chunk-elementUI', // split elementUI into a single package
priority: 20, // the weight needs to be larger than libs and app or it will be packaged into libs or app
test: /[\\/]node_modules[\\/]_?element-ui(.*)/, // in order to adapt to cnpm
},
commons: {
name: 'chunk-commons',
test: resolve('src/components'), // can customize your rules
minChunks: 3, // minimum common number
priority: 5,
reuseExistingChunk: true,
},
},
})
config.optimization.runtimeChunk('single')
config
.plugin('HtmlHook')
.use(HtmlHook, [
{
version: require('./package.json').version,
date: new Date().toLocaleDateString(),
},
])
.end()
})
},
}
function HtmlHook(options) {
this.options = options || {}
}
HtmlHook.prototype.apply = function (compiler) {
compiler.hooks.compilation.tap('HtmlHook', compilation => {
const onBeforeEmit = (htmlPluginData, callback) => {
htmlPluginData.html +=
'\n<!-- ' +
Object.entries(this.options)
.map(([key, value]) => `${key}: ${value}`)
.join(' | ') +
' -->'
callback(null, htmlPluginData)
}
// HtmlWebPackPlugin - new
if (compilation.hooks.htmlWebpackPluginAfterHtmlProcessing) {
compilation.hooks.htmlWebpackPluginAfterHtmlProcessing.tapAsync(
'HtmlHook',
onBeforeEmit,
)
} else {
const HtmlWebpackPlugin = require('html-webpack-plugin')
if (HtmlWebpackPlugin.getHooks) {
const hooks = HtmlWebpackPlugin.getHooks(compilation)
const htmlPlugins = compilation.options.plugins.filter(
plugin => plugin instanceof HtmlWebpackPlugin,
)
if (htmlPlugins.length === 0) {
const message =
"Error running html-hook, are you sure you have html-webpack-plugin before it in your webpack config's plugins?"
throw new Error(message)
}
hooks.beforeEmit.tapAsync('HtmlHook', onBeforeEmit)
} else {
const message =
"Error running html-hook, are you sure you have html-webpack-plugin before it in your webpack config's plugins?"
throw new Error(message)
}
}
})
}
3.暂无数据通用组件
<script>
export default {
functional: true,
render(h, { props, children, data }) {
return (
<div class="c__empty" {...data}>
{children || [
<svg-icon icon-class="empty" />,
<p>{props.tips || '暂无数据'}</p>,
]}
</div>
)
},
}
</script>
<style lang="scss">
.c__empty {
text-align: center;
color: #8c8c8c;
.svg-icon {
font-size: 60px;
}
}
</style>
4.行内style backgroundImage
<div :style="{ backgroundImage: 'url(' + bgUrl + ')' }" style="height:500px">
</div>
5.vue中的 Vue.sync修饰符与this.$emit(‘update:xxx‘, newXXX)
以及配合使用computed的get和set方法
一 Vue中的数据是单向数据流:父级 prop 的更新会向下流动到子组件中,但是反过来则不行,即子组件无法直接修改父组件中的数据。
但我们常常会遇到需要在子组件中修改父组件数据的场景。.sync修饰符就可以帮助我们实现这种功能。
Vue通过prop进行双向数据绑定。子组件数据变化,一般只能通过 this.$emit(func, val) 回调父组件函数来传值给父组件。
Vue2.3版本引入sync,作为一个事件绑定语法糖,当子组件触发事件时,父组件会响应事件并实现数据更新。
二 computed中有get和set方法,(在默认的情况下只有get)
1.get方法是取,相当于我们可以在get中给这个计算属性中的变量赋值
2.set方法是改变时触发,这里的改变指的是当我们在computed中定义的变量的值发生改变是,会触发set方法,这样我们就可以在set方法中进行一些我们想要做的事,(比如说调用某个方法)
父组件
<Execute :isOpenExecute.sync="isOpenExecute" :rowId="rowId" />
子组件 (可以直接使用computed来配合改变父组件的属性值)
<template>
<el-dialog title="活动执行" :visible.sync="executeVisible" width="30%">
<span>内容</span>
<span slot="footer" class="dialog-footer">
<el-button @click="$emit('update:isOpenExecute', false)">取 消</el-button>
<el-button type="primary" @click="$emit('update:isOpenExecute', false)"
>确 定</el-button
>
</span>
</el-dialog>
</template>
<script>
export default {
data() {
return {}
},
props: {
isOpenExecute: {
type: Boolean,
default: false,
},
rowId: String,
},
computed: {
executeVisible: {
get(e) {
console.log(e.isOpenExecute, e.rowId)
//打开弹窗获取详情
if (e.isOpenExecute) {
this.getInfo(e.rowId)
}
return this.isOpenExecute
},
set(e) {
this.$emit('update:isOpenExecute', false)
},
},
},
methods: {
getInfo(id) {
console.log(id, '获取详情')
},
},
}
</script>
<style lang="scss" scoped></style>
6.自定义弹窗(带输入)
this.$prompt('', '原因', {
inputType: 'textarea',
confirmButtonText: '确定',
cancelButtonText: '取消',
inputPattern: /\S/,
inputErrorMessage: '原因不能为空',
inputValidator: (value) => {
// 点击按钮时,对文本框里面的值进行验证
if(!value) {
return inputErrorMessage;
}
}
}).then(({ value }) => {
console.log('输入框的值',value);
}).catch(() => {
})
7.导出表格数据
import table2excel from "@/utils/exccel";
handleExport() {
var column = [];
(this.$refs["myTable"] as any).$children.forEach((element) => {
// console.log(element);
if (element.title && element.title != "操作") {
let temp = {
title: element.title,
key: element.field, //key值对应表单数据字段名称
type: "text",
};
column.push(temp);
}
});
table2excel(column, this.tplDataLs, "模板"); //生成Excel表格,自动下载
}
/* eslint-disable */
let idTmr;
const getExplorer = () => {
let explorer = window.navigator.userAgent;
//ie
if (explorer.indexOf("MSIE") >= 0) {
return "ie";
}
//firefox
else if (explorer.indexOf("Firefox") >= 0) {
return "Firefox";
}
//Chrome
else if (explorer.indexOf("Chrome") >= 0) {
return "Chrome";
}
//Opera
else if (explorer.indexOf("Opera") >= 0) {
return "Opera";
}
//Safari
else if (explorer.indexOf("Safari") >= 0) {
return "Safari";
}
};
// 判断浏览器是否为IE
const exportToExcel = (data, name) => {
// 判断是否为IE
if (getExplorer() == "ie") {
tableToIE(data, name);
} else {
tableToNotIE(data, name);
}
};
const Cleanup = () => {
window.clearInterval(idTmr);
};
// ie浏览器下执行
const tableToIE = (data, name) => {
let curTbl = data;
let oXL = new ActiveXObject("Excel.Application");
//创建AX对象excel
let oWB = oXL.Workbooks.Add();
//获取workbook对象
let xlsheet = oWB.Worksheets(1);
//激活当前sheet
let sel = document.body.createTextRange();
sel.moveToElementText(curTbl);
//把表格中的内容移到TextRange中
sel.select;
//全选TextRange中内容
sel.execCommand("Copy");
//复制TextRange中内容
xlsheet.Paste();
//粘贴到活动的EXCEL中
oXL.Visible = true;
//设置excel可见属性
try {
let fname = oXL.Application.GetSaveAsFilename(
"Excel.xls",
"Excel Spreadsheets (*.xls), *.xls"
);
} catch (e) {
print("Nested catch caught " + e);
} finally {
oWB.SaveAs(fname);
oWB.Close((savechanges = false));
//xls.visible = false;
oXL.Quit();
oXL = null;
// 结束excel进程,退出完成
window.setInterval("Cleanup();", 1);
idTmr = window.setInterval("Cleanup();", 1);
}
};
// 非ie浏览器下执行
const tableToNotIE = (function() {
// 编码要用utf-8不然默认gbk会出现中文乱码
const uri = "data:application/vnd.ms-excel;base64,",
template =
'<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns="http://www.w3.org/TR/REC-html40"><head><meta charset="UTF-8"><!--[if gte mso 9]><xml><x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet><x:Name>{worksheet}</x:Name><x:WorksheetOptions><x:DisplayGridlines/></x:WorksheetOptions></x:ExcelWorksheet></x:ExcelWorksheets></x:ExcelWorkbook></xml><![endif]--></head><body><table>{table}</table></body></html>';
const base64 = function(s) {
return window.btoa(unescape(encodeURIComponent(s)));
};
const format = (s, c) => {
return s.replace(/{(\w+)}/g, (m, p) => {
return c[p];
});
};
return (table, name) => {
const ctx = {
worksheet: name,
table
};
const url = uri + base64(format(template, ctx));
if (navigator.userAgent.indexOf("Firefox") > -1) {
window.location.href = url;
} else {
const aLink = document.createElement("a");
aLink.href = url;
aLink.download = name || "";
let event;
if (window.MouseEvent) {
event = new MouseEvent("click");
} else {
event = document.createEvent("MouseEvents");
event.initMouseEvent(
"click",
true,
false,
window,
0,
0,
0,
0,
0,
false,
false,
false,
false,
0,
null
);
}
aLink.dispatchEvent(event);
}
};
})();
const resolveOptions = options => {
if (options.length === 1) {
return options[0];
}
return {
column: options[0] || [],
data: options[1] || [],
excelName: options[2] || "",
captionName: options[3]
};
};
// 导出函数
const table2excel = (...options) => {
function getTextHtml(val) {
return `<td style="text-align: center">${val}</td>`;
}
function getImageHtml(val, options) {
options = Object.assign({ width: 40, height: 60 }, options);
return `<td style="width: ${options.width}px; height: ${
options.height
}px; text-align: center; vertical-align: middle"><img src="${val}" width=${options.width *
0.99} height=${options.height * 0.99} /></td>`;
}
const typeMap = {
image: getImageHtml,
text: getTextHtml
};
const { column, data, excelName, captionName } = resolveOptions(options);
let caption = captionName
? `<caption style="font-weight:bold">${captionName}</caption>`
: "";
let thead = column.reduce((result, item) => {
result += `<th>${item.title}</th>`;
return result;
}, "");
thead = `<thead><tr>${thead}</tr></thead>`;
let tbody = data.reduce((result, row) => {
const temp = column.reduce((tds, col) => {
const options = {};
if (col.type === "image") {
if (row.size) {
options.width = row.size[0];
options.height = row.size[1];
} else {
col.width && (options.width = col.width);
col.height && (options.height = col.height);
}
}
tds += typeMap[col.type || "text"](row[col.key], options);
return tds;
}, "");
result += `<tr>${temp}</tr>`;
return result;
}, "");
tbody = `<tbody>${tbody}</tbody>`;
const table = caption + thead + tbody;
// 导出表格
exportToExcel(table, excelName);
};
export default table2excel;
标签:return,name,svg,vue2,组件,const,options,第三章
From: https://www.cnblogs.com/sclweb/p/17637839.html