@Bios
2019-10-09T09:50:49.000000Z
字数 12293
阅读 1715
Vue
ElementUi
<template>
<ul class="tab clearfix">
<li v-for="(tab,index) in tabs" @click="changeTab(index,tab.view)" :class="{active:currentActive===index}">
{{tab.type}}
</li>
</ul>
</template>
<script>
import GroupFile from 'components/group/GroupFile'
import GroupSetting from 'components/group/GroupSetting'
import MembersList from 'components/group/MembersList'
export default {
// view 为组件名
data() {
return {
tabs:[
{type:'互动交流',view:'GroupChat'},
{type:'文件共享',view:'GroupFile'},
{type:'小组设置',view:'GroupSetting'}
]
}
},
methods:{
// tab切换 添加active类
changeTab(index,view) {
this.currentActive = index
this.currentView = view
}
},
components: {
GroupChat,
GroupFile,
GroupSetting
}
}
</script>
<template>
<el-table
ref="multipleTable"
:data="tableData"
border
tooltip-effect="dark"
style="width: 100%"
@selection-change="handleSelectionChange"
>
<el-table-column
type="selection"
width="55">
</el-table-column>
<el-table-column
prop="filename"
label="文件名"
width="500">
</el-table-column>
……
</el-table>
</template>
<script>
export default{
data() {
return {
multipleSelection: [] //存放选择项
}
},
computed:{
isSelected() {
if (this.multipleSelection.length > 0) {
return false
} else {
return true
}
}
},
methods:{
handleSelectionChange(val) {
// val是个为当前选中行
this.multipleSelection = val
}
}
}
</script>
……结构与上面一样 在删除按钮上绑定delet()方法
delet() {
//console.log(this.multipleSelection)
this.tableData.splice(this.multipleSelection,this.multipleSelection.length)
this.$refs.multipleTable.clearSelection(); // 清空用户的选择,否则它会自动向上选中this.multipleSelection.length个数据
}
<template>
<el-table
:data="listTableData"
border
style="width: 100%">
<el-table-column
prop="name"
label="名称"
>
</el-table-column>
<el-table-column
label="是否使用"
width="150">
<template scope="scope">
<el-radio class="radio" v-model="scope.row.useradio" label="1">是</el-radio>
<el-radio class="radio" v-model="scope.row.useradio" label="2">否</el-radio>
</template>
</el-table-column>
<el-table-column
label="是否必填"
width="150">
<template scope="scope">
<el-radio class="radio" v-model="scope.row.needradio" label="1">是</el-radio>
<el-radio class="radio" v-model="scope.row.needradio" label="2">否</el-radio>
</template>
</el-table-column>
</el-table>
</template>
<script>
export default{
data() {
return {
listTableData:[
{
name:'主要学习经历',
useradio:'1',
needradio:'1'
},
{
name:'主要工作经历',
useradio:'1',
needradio:'1'
}
]
}
}
}
</script>
跳转传参
<router-link :to="{name:'预选编委',query:{bookid:scope.row.bookid,edit:1}}">
路由判断
data() {
return {
edit:''
}
}
created(){
if(this.$route.query.edit===1) {
this.edit=true
}else {
this.edit=false
}
}
是否展示
<el-table-column
v-if="!edit"
label="是否编委"
align="center"
>
<template scope="scope">
<el-tag :type="scope.row.isMember==='编委'?'success':'danger'">{{ scope.row.isMember}}</el-tag>
</template>
</el-table-column>
这个方法的参数是一个整数,意思是在 history 记录中向前或者后退多少步,类似 window.history.go(n)
。
例子
// 在浏览器记录中前进一步,等同于 history.forward()
router.go(1)
// 后退一步记录,等同于 history.back()
router.go(-1)
// 前进 3 步记录
router.go(3)
// 如果 history 记录不够用,那就默默地失败呗
router.go(-100)
router.go(100)
// 弹出层 字段跟表格一样
form: {
username:'',
name: '',
phone:'',
email:'',
role:'',
use:''
},
// 表格数据
tableData:[
{
name:'张三',
username:'zs',
email:'123@qq.com',
role:'主任项目编辑',
phone:'1383838438',
use:false
},
……
]
// 点击修改
modify(index, data) {
//this.form = data[index] 要通过遍历的方式赋值,而不能直接将对象赋值,这样数据会及时修改(内存地址赋值了)
for (var key in data[index]){
this.form[key] = data[index][key]
// use要在页面中呈现"启用""停用",在赋值的时候做处理
if (this.form.use){
this.form.use = "启用"
} else {
this.form.use = "停用"
}
}
},
<template>
<div class="topic_exam">
<el-tabs v-model="activeName" type="border-card" >
<el-tab-pane label="转发部门" name="first" v-if="Identity.isAdmin || Identity.isOpts">
<forward-depart :activeName.sync='activeName' @changeActive='changeActive'></forward-depart>
</el-tab-pane>
<el-tab-pane label="分配编辑" name="second" v-if="Identity.isAdmin || Identity.isDirector">
<distribute-editor :activeName.sync='activeName' @changeActive='changeActive'></distribute-editor>
</el-tab-pane>
<el-tab-pane label="受理" name="third" v-if="Identity.isAdmin || Identity.isEditor">
<acceptance :activeName.sync='activeName' @changeActive='changeActive'></acceptance>
</el-tab-pane>
</el-tabs>
</div>
</template>
<script type="text/javascript">
import forwardDepart from './forwardDepart.vue'
import distributeEditor from './distributeEditor.vue'
import acceptance from './acceptance.vue'
export default{
data(){
return{
Identity:{}
}
},
computed:{
activeName:{ // 设置一个set方法可以避免错误
get: function () {
if (this.Identity.isAdmin || this.Identity.isOpts) {
return 'first';
} else if (this.Identity.isAdmin || this.Identity.isDirector) {
return 'second';
} else if (this.Identity.isAdmin || this.Identity.isEditor) {
return 'third';
}
},
set: function () {
}
}
},
created(){
this.activeName = this.$route.query.active || 'first';
this.identity();
},
components: {
forwardDepart,distributeEditor,acceptance
},
methods:{
changeActive(val){
this.activeName=val;
},
identity(){
this.$axios.get('/pmpheep/topic/identity').then(response=> {
let res = response.data;
if (res.code == '1') {
this.Identity = res.data;
}
})
}
}
}
</script>
<style scoped>
.topic_exam .el-tabs--border-card{
border: 0;
box-shadow: none;
}
</style>
// 单个checkbox
<input type="checkbox" v-model="a"> {{a}} <br/>
// 多个checkbox
爱好:<input type="checkbox" v-model="b" value="游泳"> 游泳
<input type="checkbox" v-model="b" value="爬山"> 爬山
<input type="checkbox" v-model="b" value="睡觉"> 睡觉
data:{
return {
a : false,
b:['游泳','爬山'] // b可以取到checkbox的value值
}
}
<div v-if="dialogForm.type!='judgement'&&dialogForm.type!='Q&A'">
<el-form-item v-for="(item,index) in dialogForm.surveyQuestionOptionList"
:key="item.key"
:label="'选项'+(index+1) +':'"
:prop="'surveyQuestionOptionList.' + index + '.optionContent'"
:rules="{
required:true, message:'选项不能为空', trigger:'blur'
}"
>
// 最重要的是prop 一定要带上`.optionContent`,也就是你绑定值的key
<el-input placeholder="请输入选项" class="dialog_input" v-model="item.optionContent"></el-input>
<i class="el-icon-delete delete-icon" @click="deleteDlalogOption(index)"></i>
</el-form-item>
<el-button type="primary" size="small" class="marginB10" @click="addDialogOption">添加选项</el-button>
</div>
goToExam(id){
// params传参只能用name引入
this.$router.push({name:'ForntExam',params:{id:id}});
}
<div class="single">
<h4>单选题(只有一个正确答案)</h4>
<ul>
<li class="marginB10" v-for="(item,index) in singleQuestions" :key="item.id">
<p class="question-title">{{index+1}} 、{{item.name}}()</p>
<span class="option"
v-if="item.type!='judgement'&&item.type!='Q&A'"item
v-for="(item1,index1) in item.selection" :key="item1.id">
<el-radio v-model="item.sanswer" :label="options[index1]" :key="index1">{{options[index1]}}、{{item1}}</el-radio>
</span>
</li>
</ul>
</div>
init(){
if(this.id == '' || !this.id ){
this.$router.push({path:'forntexamindex'});
return
} else {
this.$axios.get('/api/getExamInfo',{
params:{
id: this.id
}
}).then(response => {
let res = response.data;
if(res.status == '0') {
for(let key in this.paperData) {
this.paperData[key] = res.result[key];
}
res.result._questions.forEach(item => {
if(item.type=='single'){
item.sanswer = ''; // 重要的在这
this.singleQuestions.push(item);
} else if(item.type == 'multi'){
this.multiQuestions.push(item);
} else if(item.type == 'Q&A') {
this.QAQuestions.push(item);
} else if(item.type == 'judgement'){
this.judgeQuestions.push(item);
}
})
}
}).catch(err => {
this.$message.error(err);
})
}
}
this.$axios.get('https://www.easy-mock.com/mock/5b616f2e0f34b755cbc58bb4/demo').then(function(res){
console.log(this);
})
闭包问题,要使用箭头函数
// 全局注册自定义指令
Vue.directive('focus', {
// 当被绑定的元素插入到 DOM 中时……
inserted: function (el) {
// 聚焦元素
console.log(el)
el.focus()
}
})
全局注册(directive),局部注册(directives)
.fade-enter,.fade-leave-to{
opacity: 0;
}
.fade-enter-active,.fade-leave-active{
transition: opacity 3s;
}
<transition name="fade">
<div v-show="show">显示/隐藏</div>
</transition>
# 可以通过 appear 特性设置节点在初始渲染的过渡
<transition
name="fade"
appear
enter-active-class="animated fadeIn"
leave-active-class="animated slideInLeft"
appear-class="animated fadeIn"
>
<div v-show="show">显示/隐藏</div>
</transition>
有时候有些数据是后端配置的,obu hu不会时常更新,但是又保不齐那天会更新,用localStorage + vuex 存取的方式已经不适用了,当然可以只用vuex,在这里尝试一下mixins 和 sessionStorage 的方式。用vuex 的话,如果getter拿不到数据,我们还得手动触发一下action去发送请求,我觉得比较麻烦,写成mixins的话,整个逻辑就写一遍,其他地方都可以用了。
import {
getGovAgen
} from '@/api/policy_api';
export default {
data() {
return {
gov_agen_options: []
};
},
mounted() {
this.getGovAgen();
},
methods: {
// 获取发文体系
getGovAgen() {
let options = JSON.parse(sessionStorage.getItem('gov_agen'));
if (options) {
this.gov_agen_options = options;
} else {
getGovAgen().then(res => {
if (res.code == 200) {
this.gov_agen_options = res.data;
sessionStorage.setItem('gov_agen', JSON.stringify(res.data));
}
});
}
}
}
};
后台管理系统,刷新当前路由,而不是刷新整个页面。provide不仅可以注入变量,还可以是方法。
// layout.vue
<template>
<header/>
<siderbar/>
<div>
<router-view v-if="isRouterAlive"/>
</div>
<footer/>
</template>
<script>
export default {
provide() {
return {
reload: this.reload
};
},
data() {
return {
isRouterAlive: true
};
},
methods: {
// 刷新页面
reload() {
this.isRouterAlive = false;
this.$nextTick(() => {
this.isRouterAlive = true;
});
}
}
};
</script>
// child.vue
export default{
inject: ['reload'],
methods: {
reload() {
this.reload();
}
}
}
提示:
provide
和inject
绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的属性还是可响应的。
/deep/ .el-tag.el-tag--info.el-tag--small.el-tag--light {
display: flex;
align-items: center;
}
/deep/ .el-select__tags-text {
max-width: 200px;
display: inline-block;
height: 22px;
overflow: hidden;
text-overflow: ellipsis;
}
let routeUrl = this.$router.resolve({
path: path,
query: {type: type}
});
window.open(routeUrl.href, '_blank');
我们先来看一个完整的 URL:https://www.baidu.com/blog/guide/vuePlugin.html#vue-router
。其中 https://www.baidu.com
是网站根目录,/blog/guide/
是子目录,vuePlugin.html
是子目录下的文件(如果只有目录,没有指定文件,会默认请求index.html
文件),而#vue-router
就是哈希值。
vue 是单页应用,打包之后只有一个 index.html
,将他部署到服务器上之后,访问对应文件的目录就是访问这个文件。
hash 模式:网址后面跟着 hash
值,hash
值对应每一个 router
的名称,hash
值改变意味着router
改变,监听 onhashchange
事件,来替换页面内容。
history 模式:网址后面跟着‘假的目录名’,其值就是 router
的名称,而浏览器会去请求这个目录的文件(并不存在,会 404),所以 history
模式需要服务器配合,配置 404 页面重定向到到我们的 index.html
,然后 vue-router
会根据目录的名称来替换页面内容。
优缺点:
hash
模式的 #
号很丑,使用的是 onhashchange
事件切换路由,兼容性会好一点,不需要服务器配合
history
模式好看点,但是本地开发、网站上线,都需要服务器额外配置,并且还需要自己写 404 页面,使用的是 HTML5 的 history
API,兼容性差一点。
两者的配置区别在于:
const router = new VueRouter({
mode: 'history', //"hash"模式是默认的,无需配置
base: '/',//默认配置
routes: [...]
})
复制代码vue-cli3 的 vue.config.js 配置:
module.exports = {
publicPath: "./", // hash模式打包用
// publicPath: "/", // history模式打包用
devServer: {
open: true,
port: 88,
// historyApiFallback: true, //history模式本地开发用
}
}
复制代码如果是网站部署在根目录,router
的 base
就不用填。如果整个单页应用服务在 /app/
下,然后 base
就应该设为 "/app/"
,同时打包配置(vue.config.js)
的 publicPath
也应该设置成/app/
。
vue-cli3生成新项目的时候会有选择路由的模式,选择history模式就会帮你都配置好。
...
routes: [
{
path: '/',
name: 'home',
component: Home,
meta: {auth: true}
},
]
...
router.beforeEach((to, from, next) => {
if(to.meta.auth) {
const token = localStorage.getItem('token');
if(token){
next()
} else {
// 没有登录跳到登录页,登录之后,直接跳转到to.path
next({
path: '/login',
query: {redirect: to.path}
})
}
} else {
next()
}
})
这种方式不存在跨域。
// vue.config.js
module.exports = {
configureWebpack: {
devServer: {
before(app) {
app.get('/api/goods', (req, res) => {
res.json({
code: 0,
list: [
{id:1,name:'苹果'},
{id:2,name:'香蕉'}
]
})
})
}
}
}
}
axios.get('/api/goods').then(res => {})
// public/mock/member.json
[
{"id":0,"name":"finget","age":23},
{"id":1,"name":"finget1","age":23},
{"id":2,"name":"finget2","age":23},
{"id":3,"name":"finget3","age":23}
]
// vue.config.js
module.exports = {
configureWebpack: {
devServer: {
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true,
pathRewrite: {
'^/api': '/mock'
}
}
}
}
}
}
axios.get('/api/member.json').then(res => {})
//引入mockjs
const Mock = require('mockjs')
// 获取 mock.Random 对象
const Random = Mock.Random;
//使用mockjs模拟数据
Mock.mock('/api/data', (req, res) => {//当post或get请求到/api/data路由时Mock会拦截请求并返回上面的数据
let list = [];
for(let i = 0; i < 30; i++) {
let listObject = {
title: Random.csentence(5, 10),//随机生成一段中文文本。
company: Random.csentence(5, 10),
attention_degree: Random.integer(100, 9999),//返回一个随机的整数。
photo: Random.image('114x83', '#00405d', '#FFF', 'Mock.js')
}
list.push(listObject);
}
return {
data: list
}
})
<el-form-item
label="地址"
class="flex-1 is-required"
prop="address"
:rules="[
{validator: addressValidator, trigger: 'blur'}
]"
></el-form-item>
methods: {
// 详细地址validator
addressValidator(rule, value, callback) {
if (this.form.address === '' || this.form.region.length === 0) {
callback(new Error('请选择省市区并填写详细地址'));
} else {
callback();
}
}
}
1.动态新增
<el-form-item
:label="'租金'+(index+1)"
class="flex-1"
:prop="'payment.rent_period.'+index+'.rent_fee'"
:rules ="{
pattern: /^[1-9]{1,9}$/, message: '只能输入正整数,且不超过10位数', trigger:'change'
}"
>
2.关联验证
<el-form-item
class="flex-1"
label="租金时间段"
:prop="'payment.rent_period.'+index+'.start_time'"
:rules="item.rent_fee?{required: true, message:'请填写租金时间段', trigger: 'change'}:{}"
>