Vue front-end page development experience record

This blog post records some experience in the development of vue projects, including: class dynamic binding, subpage refresh, injecting functions into subpages, data loading effects, editing after clicking, file uploading, data paging, form submission, etc. Use records.

1. Class dynamic binding

Bind different class styles according to the value of the variable, where the value of ftype can be full_label, zero_label, has_label three class style names

        <div class="folderImg" :class="ftype" @click="to_url('showimglist',fd.name)">
          <i class="el-icon-folder-opened avatar-uploader-icon"></i>
        </div>

The corresponding class settings are

.full_label {
    
    
  background-image: url(../../assets/full_label.png);
  background-repeat:no-repeat;
  background-size:100% 100%;
  -moz-background-size:100% 100%;
}

.zero_label {
    
    
  background-image: url(../../assets/zero_label.png);
  background-repeat:no-repeat;
  background-size:100% 100%;
  -moz-background-size:100% 100%;
}

.has_label {
    
    
  background-image: url(../../assets/has_label.png);
  background-repeat:no-repeat;
  background-size:100% 100%;
  -moz-background-size:100% 100%;
}

2. Refresh the subpage | Inject the function into the subpage

Set the subpage invisible by means of v-if, and then set the subpage visible in this.$nextTick, so as to realize the refresh of the subpage. Then encapsulate it as a reload function, inject the function into the subpage, and call it on the subpage.
Specific reference: https://www.jb51.net/article/260561.htm

<template>
  <div id="app">
    <!--img src="./assets/logo.png"-->
    <router-view v-if="isRouterAlive"></router-view>
  </div>
</template>
<script>
import axios from 'axios'
export default {
      
      
  name: 'App',
  provide () {
      
       //设置被注入到子页面的函数
    return {
      
      
      reload: this.reload,
    }
  },
  data () {
      
      
    return {
      
      
      isRouterAlive: true,
    }
  },
  methods: {
      
      
    reload () {
      
      
      this.isRouterAlive = false
      this.$nextTick(function () {
      
      
        this.isRouterAlive = true
      })
    },
  }
}
</script>

Set inject in the js of the subpage to refresh the content on the subpage

//子页面
  <script>   
  export default {
      
      
    name: 'showanalysis',
    inject: ['reload'], //接收父页面注入的内容
  }
  </script>

3. Data loading effect

Used for the process interface in the result returned by the server (the effect is triggered when the front end calls the background interface, and the display is canceled after the result is obtained)

For details, refer to https://element.faas.ele.me/#/zh-CN/component/loading#loading-jia-zai
insert image description here
. The specific usage example is as follows. Add the v-loading attribute to the element to bind the variable loading. The default is false. Display effect; when other time-consuming operations are triggered, modify loading to true to display the loading effect; when the operation is completed, modify loading to false.

<template>
  <div class="demo-image"
  v-loading="loading"
  element-loading-text="等待服务器处理中"
  element-loading-spinner="el-icon-loading"
  element-loading-background="rgba(0, 0, 0, 0.8)"
 >
  </div>
</template>
  
<script>

export default {
      
      
  name: 'showdatafolder',
  data() {
      
      
    return {
      
      
      loading: false,
    }
  },
  }
}
</script>

4. Percentage of width and height

Use vh, vw to control the element's width and height percentages relative to the screen. vh and wh are viewport units, which are relative length units. wh is the width relative to the viewport, "1vw" is equal to "1%" of the viewport width; and vh is the height relative to the viewport, "1vh" is equal to "1%" of the viewport height

Specific reference: https://www.php.cn/faq/489349.html

5. Edit after clicking

The text class control is converted into an input control after being clicked, and the text class space is transformed after losing focus.
The following is the combination of the el-button control and the el-input control. When the el-button is clicked, the corresponding el-input is displayed. When the el-input loses focus, it is displayed as the el-button again.

<el-input
  class="input-new-tag"
  v-if="inputVisible"
  v-model="inputValue"
  ref="saveTagInput"  #为控件取了一个名字
  size="small"
  @keyup.enter.native="handleInputConfirm"
  @blur="handleInputConfirm"
>
</el-input>
<el-button v-else class="button-new-tag" size="small" @click="showInput">+ New Tag</el-button>


<script>
  export default {
      
      
    data() {
      
      
      return {
      
      
        dynamicTags: ['标签一', '标签二', '标签三'],
        inputVisible: false,
        inputValue: ''
      };
    },
    methods: {
      
      
      showInput() {
      
      
        this.inputVisible = true;
        this.$nextTick(_ => {
      
      
          this.$refs.saveTagInput.$refs.input.focus();//设置指定控件获取输入焦点
        });
      },
      handleInputConfirm() {
      
      
        let inputValue = this.inputValue;
        if (inputValue) {
      
      
          this.dynamicTags.push(inputValue);
        }
        this.inputVisible = false;
        this.inputValue = '';
      }
    }
  }
</script>

Key analysis:
1. Through v-if='inputVisible' , v-elsethe binding variable inputVisible, set the display switch between el-button and el-input.
2. Set ref for the el-input control, which is to name the control. When the button is clicked, trigger showInput事件, set el-input to be visible, and get the input focus
3. By setting @blur与@keyup.enter.nativethe properties of el-input, monitor the operation after the input is completed, and set inputVisible = falsethe input box to be invisible, and inputValue = '' the value of the input box is empty`

Code reference from: https://element.faas.ele.me/#/zh-CN/component/tag

before click effect

insert image description here
The effect of control input
insert image description here

6. File upload

Here is only the simplest way to upload files. Please refer to https://element.faas.ele.me/#/zh-CN/component/upload for multiple file uploads (essentially calling the file upload interface multiple times).

html page

Set action to null, mainly to :before-uploadimplement file upload in the bound function

      <el-upload class="upload-demo" drag action="null" :before-upload="beforeAvatarUpload">
        <i class="el-icon-upload"></i>
        <div class="el-upload__text">将pt文件拖到此处,或<em>点击上传</em></div>
        <div class="el-upload__tip" slot="tip">只能上传pt文件,且不超过500kb</div>
      </el-upload>

js implementation

In the beforeAvatarUpload function, you can judge the file suffix and file size, and finally use axios to create a post request to submit the file to the backend

    beforeAvatarUpload(file) {
    
    
      import axios from 'axios'
      const isAllow = file.name.indexOf('.pt') > 0 || file.name.indexOf('.PT') > 0;
      const isLt200M = file.size / 1024 / 1024 / 200;
      if (!isAllow) {
    
    
        this.$message.error("只允许上传pt文件!");
        return false
      } else if (!isLt200M) {
    
    
        this.$message.error('上传模型大小不能超过 200MB!');
        return false
      } else {
    
    
        //手动进行文件上传
        let formData = new FormData();
        formData.append("file", file);
        axios({
    
    
          url: "/api/uploader",//上传文件接口
          method: "post",
          headers: {
    
    
            "Content-Type": "multipart/form-data",
          },
          data: formData,
        }).then((res) => {
    
    
          this.$message({
    
    
            title: '结果提示',
            message: res.data.msg,
            type: 'success'
          });
          this.reload();
        });
      }
      return false
    },

backend code

The backend is implemented based on flask

@app.route('/uploader',methods=['GET','POST'])
def uploader():
    if request.method == 'POST':
        f = request.files['file']#跟表单里file中的name要一样
        spath=os.path.join(runDir, f.filename)
        print(spath)
        f.save(spath)
        json={
    
    'code':0,'msg':'文件上传成功!'}
        return jsonify(json) 
    else:
        return 'please uplaod file use post method!'

For more information, please refer to https://element.faas.ele.me/#/zh-CN/component/upload

7. Data pagination

The usage of the paging control is introduced in detail in element-ui, but it is not accompanied by any specific case introduction. https://element.faas.ele.me/#/zh-CN/component/pagination

html page

The first component is grid-content, and the v-for loop in it corresponds to the variable img_list, which is used to display the specific content of the paging. The
second part is the el-pagination control, which corresponds to the specific paging control. You can control the position of the content of the paging component by modifying the text corresponding to the layout

<template>
  <div class="demo-image"
  >
    <el-row>
        <div class="grid-content">
          <div class="block" v-for="d in img_list" :key="d">
            <div class="demo-image__preview">
              <el-image style="width: 200px; height: 200px" :src="d" :preview-src-list="img_list">
              </el-image>
              <div class="bottom clearfix">
                <el-button type="text" class="button" @click="to_url('labelimg',{'currentImage':d})">标注</el-button>
                <el-button type="text" class="button" @click="delete_img(d)">删除</el-button>
              </div>
            </div>
          </div>
        </div>
    </el-row>
    <el-row>
        <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="0"
          :page-sizes="[6, 8, 10, 12, 15, 18]" :page-size="default_page_size"
          layout="total, sizes, prev, pager, next, jumper" :total="all_img_list.length">
        </el-pagination>
    </el-row>

  </div>
</template>

js implementation

The main variables involved are all_img_list | all data, img_list | current page data, default_page_size | the amount of data on each page, default_page | current page.
When the page is initialized, all the data is obtained from the mounted function and set to all_img_list, and the content of the current page is intercepted according to default_page_size and default_page and set to img_list.

<script>
import axios from 'axios'
export default {
      
      
  name: 'showimglist',
  data() {
      
      
    return {
      
      
      all_img_list: [],
      img_list: [],
      default_page_size: 10,
      default_page: 1,
    }
  },
  mounted() {
      
      
    if(this.$route.query.dname){
      
      
      localStorage.setItem('dname', this.$route.query.dname);
    }
    let dname = localStorage.getItem('dname');//this.$route.params.dname;
    this.dname=dname;
    if (dname) {
      
      
      let formData = new FormData();
      formData.append("dname", dname);
      axios({
      
      
        url: '/api/datamanage_get_imglist',//上传文件接口
        method: "post",
        headers: {
      
      
          "Content-Type": "multipart/form-data",
        },
        data: formData,
      }).then((res) => {
      
      
        this.all_img_list = res.data;
        this.img_list = this.all_img_list.slice(0, this.default_page_size)
      });
    }
  },
  methods: {
      
      
    handleSizeChange(val) {
      
      
      this.default_page_size = val;
      this.img_list = this.all_img_list.slice((this.default_page - 1) * this.default_page_size, this.default_page * this.default_page_size);
    },
    handleCurrentChange(val) {
      
      
      this.default_page = val
      this.img_list = this.all_img_list.slice((this.default_page - 1) * this.default_page_size, this.default_page * this.default_page_size);
    },
    
  }
}
</script>

In the above code, handleSizeChange is used to monitor changes in the number of pages, and handleCurrentChange is used to detect changes in the number of pages

backend implementation

The pagination here has nothing to do with the backend in essence. The data corresponding to the page number is not requested from the backend every time the page is paginated, but only intercepted from the existing data.
When the total data is large, the data can be obtained from the backend in real time in handleSizeChange and handleCurrentChange.

The final page effect is as follows
insert image description here

8. Form submission

form implementation

The following form is bound to a json object :model="ruleForm", so v-model="ruleForm.name"the el-form-item is bound to ruleForm.name, and :rules="rules"the validation rules are also bound, and ref="ruleForm" the form is named ruleForm.
The form is submitted by the submitForm event

  <el-form :model="ruleForm" :rules="rules" ref="ruleForm"  
  style="padding: 30px;width:400px;background-color: bisque;" label-width="100px" class="demo-ruleForm">
    <el-form-item label="用户名" prop="name">
      <el-input v-model="ruleForm.name"></el-input>
    </el-form-item>
    <el-form-item label="密码" prop="pwd">
      <el-input type="password" v-model="ruleForm.pwd"></el-input>
    </el-form-item>
    <el-form-item>
      <el-button type="primary" @click="submitForm('ruleForm')">立即登录</el-button>
      <el-button @click="resetForm('ruleForm')">重置</el-button>
    </el-form-item>
  </el-form>

Form Validation and Submission

The ruleForm object is the data model bound to the form.
The rules are the verification rules for the specific fields of the form. Multiple rules can be set for each field. The
submitForm function realizes the verification and submission of the form

 export default {
    
    
    name: 'login',
    data() {
    
    
      return {
    
    
        ruleForm: {
    
    
          name: '',
          pwd: '',
        },
        rules: {
    
    
          name: [
            {
    
     required: true, message: '请输入用户名', trigger: 'blur' },
            {
    
     min: 3, max: 5, message: '长度在 3 到 5 个字符', trigger: 'blur' }
          ],
          pwd: [
            {
    
     required: true, message: '请输入密码', trigger: 'blur' },
            {
    
     min: 3, max: 5, message: '长度在 3 到 5 个字符', trigger: 'blur' }
          ],
        }
      };
    },
      methods: {
    
    
        submitForm(formName) {
    
    
          this.$refs[formName].validate((valid) => {
    
    
            if (valid) {
    
    //表单验证成功,进入后台主页
              this.$router.push({
    
    name:'mainframe'});
            } else {
    
    
              console.log('error submit!!');
              return false;
            }
          });
        },
        resetForm(formName) {
    
    
          this.$refs[formName].resetFields();
        }
      }
    }

insert image description here

Guess you like

Origin blog.csdn.net/a486259/article/details/132132449
Recommended