Vue 的filters的作用是什么?

简单介绍一下

简单介绍一下过滤器,顾名思义,过滤就是一个数据经过了这个过滤之后出来另一样东西,可以是从中取得你想要的,或者给那个数据添加点什么装饰,那么过滤器则是过滤的工具。例如,从[‘abc’,‘abd’,‘ade’]数组中取得包含‘ab’的值,那么可通过过滤器筛选出来‘abc’和‘abd’;把‘Hello’变成‘Hello World’,那么可用过滤器给值‘Hello’后面添加上‘ World’;或者把时间节点改为时间戳等等都可以使用过滤器。

首先,过滤器可在new Vue实例前注册全局的,也可以在组件上写局部。

全局过滤器:

Vue.filter('globalFilter', function (value) {
  return value + "!!!"
})

组件过滤器(局部):

filters:{
    componentFilter:function(value){
          return value + "!!!"
    }
  },

上面有种写法有个需要注意的问题:全局注册时是filter,没有s的。而组件过滤器是filters,是有s的,这要注意了,虽然你写的时候没有s不报错,但是过滤器是没有效果的

下面我们来讲一下过滤器的使用方法
使用方式
  1. 在双花括号插值
{{ 'ok' | globalFilter }}
  1. 在v-bind表达式中使用
<div v-bind:data="'ok' | globalFilter" ></div>
参数写法
  1. {{ message | filterA | filterB }}
    上述代码中,message是作为参数传给filterA 函数,而filterA 函数的返回值作为参数传给filterB函数,最终结果显示是由filterB返回的。
<div>{{ '2018' | filterA | filterB }}</div>

filters: {
  filterA: function(value) {
    return value + '年'
  },
  filterB: function(value) {
    return value + '那年你很美!'
  }
}

结果:

2018年 那年你很美!

  1. {{ message | filterA('arg1', arg2) }}
    上述代码中,filterA的第一个参数是message,依次是‘arg1’,arg2
<div>{{ '2018' | filterA('07', '17') }}</div>

filters: {
  filterA: function(value, arg1, arg2) {
    return value + '-' + arg1 + '-' + arg2
  }
}

结果:

2018-07-17

  1. {{ ‘a’,‘b’ | filterB }}
    上述代码表示’a’和’b’分别作为参数传给filterB
<div>{{ 'Hello', 'World'| filterB }}</div>

filters: {
  filterB: function(value, value1) {
    return value + '' + value2
  }
}

结果:

Hello World

借鉴文章出处

Vue 的props的作用是什么

前言

官方文档:
组件实例的作用域是孤立的。这意味着不能 (也不应该) 在子组件的模板内直接引用父组件的数据。父组件的数据需要通过 prop 才能下发到子组件中.

也就是props是子组件访问父组件数据的唯一接口。
详细一点解释就是:
一个组件可以直接在模板里面渲染data里面的数据(双大括号)。
子组件不能直接在模板里面渲染父元素的数据。
如果子组件想要引用父元素的数据,那么就在prop里面声明一个变量(比如a),这个变量就可以引用父元素的数据。然后在模板里渲染这个变量(前面的a),这时候渲染出来的就是父元素里面的数据。

基本用法
<!--父组件-->
<template>
  <div>
      <hello-world2 :good = "good"></hello-world2> //向子组件传值
  </div>
</template>

<script>
  import helloWorld2 from "./HelloWorld2"  //引用子组件页面

  export default {
    name: "HelloWorld3",
    data() {
      return {
        good: "我是从hello word3传递过来的"
      }
    },
    components: {
      'hello-world2': helloWorld2   //注册子组件
    },
  }
</script>
<!--子组件-->
<template>
    <div>{{good}}</div>
</template>

<script>
  export default {
    props: ['good'], //通过props获取父组件传递过来的值
    data: function () {
      return {}
    },
    methods: {}
  }
</script>

总结: 父组件通过v-bind向子组件传值,子组件通过props来获取父组件传递过来的值,被引用的就是子组件

补充:kebab-case

camelCase vs. kebab-case:js中用驼峰式命名,在html中替换成短横线分隔式命名

<!--HTML 中使用 kebab-case -->
<child my-message="hello!"></child>
 
<script>
    Vue.component('child', {
        // 在 JavaScript 中使用 camelCase
        props: ['myMessage'],
        template: '<span>{{ myMessage }}</span>'
    })
</script>
单向数据流: props是单向绑定的

父组件的属性变化时,将传导给子组件,但是反过来不会。
每次父组件更新时,子组件的所有 props 都会更新为最新值。
不要在子组件内部改变 props。如果你这么做了,Vue 会在控制台给出警告。
在两种情况下,我们很容易忍不住想去修改 props 中数据:

  1. Props 作为初始值传入后,子组件想把它当作局部数据来用;
  2. Props 作为原始数据传入,由子组件处理成其它数据输出。

对这两种情况,正确的应对方式是:
定义一个局部变量,并用 prop 的值初始化它:

props: ['initialCounter'],
    data: function () {
      return { counter: this.initialCounter }
    }

定义一个计算属性,处理 prop 的值并返回:

props: ['size'],
    computed: {
      normalizedSize: function () {
        return this.size.trim().toLowerCase()
      }
    }

注意在 JavaScript 中对象和数组是引用类型,指向同一个内存空间,如果 prop 是一个对象或数组,在子组件内部改变它会影响父组件的状态。

举个例子:

<div id="app3">
        <my-component :object='object'></my-component>
    </div>
    <script src="http://vuejs.org/js/vue.min.js"></script>
    <script>
        //
        var mycom = Vue.component('my-component', {
            //添加一个input改变子组件的childOject,那么父元素的object也会被改变,但是Vue没有报错!
            template: '<p>{{ object.name }} is {{ object.age }} years old.<br><input v-model="childObject.name" type="text"></p>',
            props: ['object','school'],
            data: function () {
                // 子组件的childObject 和 父组件的object 指向同一个对象
                return {
                    childObject: this.object
                }
            }
        });
        var app3 = new Vue({
            el: '#app3',
            data: {
                object:{
                    name: 'Xueying',
                    age: '21',
                },
                school:'SCUT',
            },
        })
    </script>
props验证

可以为prop指定验证规则,如果传入的数据不符合要求,Vue会发出警告。
具体验证规则见官方文档:Prop验证规则

$parent

$parent 也可以用来访问父组件的数据。

而且子组件可以通过$parent 来直接修改父组件的数据,不会报错!

可以使用props的时候,尽量使用props显式地传递数据(可以很清楚很快速地看出子组件引用了父组件的哪些数据)。

另外在一方面,直接在子组件中修改父组件的数据是很糟糕的做法,props单向数据流就没有这种顾虑了。

借鉴文章出处

Vue 中$emit 的作用是什么

前言
  1. 父组件可以使用 props 把数据传给子组件。
  2. 子组件可以使用 $emit 触发父组件的自定义事件。

vm.$emit( event, arg ) //触发当前实例上的事件

vm.$on( event, fn );//监听event事件后运行 fn;

例子
子组件:
<template>
  <div class="train-city">
    <h3>父组件传给子组件的toCity:{{sendData}}</h3> 
    <br/><button @click='select(`大连`)'>点击此处将‘大连’发射给父组件</button>
  </div>
</template>
<script>
  export default {
    name:'trainCity',
    props:['sendData'], // 用来接收父组件传给子组件的数据
    methods:{
      select(val) {
        let data = {
          cityname: val
        };
        this.$emit('showCityName',data);//select事件触发后,自动触发showCityName事件
      }
    }
  }
</script>
父组件:
<template>
    <div>
        <div>父组件的toCity{{toCity}}</div>
        <train-city @showCityName="updateCity" :sendData="toCity"></train-city>
    </div>
<template>
<script>
  import TrainCity from "./train-city";
  export default {
    name:'index',
    components: {TrainCity},
    data () {
      return {
        toCity:"北京"
      }
    },
    methods:{
      updateCity(data){//触发子组件城市选择-选择城市的事件
        this.toCity = data.cityname;//改变了父组件的值
        console.log('toCity:'+this.toCity)
      }
    }
  }
</script>
点击之前的数据

在这里插入图片描述

点击之后的数据

在这里插入图片描述

借鉴文章出处

axios 如何定义全局变量错误处理

使用过哪些elementui组件

ElementUI介绍
 <!‐‐ 引入ElementUI样式 ‐‐>
<link rel="stylesheet" href="https://unpkg.com/element‐ui/lib/themechalk/index.css">
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<!‐‐ 引入ElementUI组件库 ‐‐>
<script src="https://unpkg.com/element‐ui/lib/index.js"></script>

常用组件
Container 布局容器

用于布局的容器组件,方便快速搭建页面的基本结构:
- <el‐container>:外层容器。当子元素中包含 <el‐header> 或 <el‐footer> 时,全部子元素会垂直上下排列,否则会水平左右排列
- <el‐header>:顶栏容器

  • <el‐aside>:侧边栏容器
  • <el‐main>:主要区域容器
  • <el‐footer>:底栏容器
<body>
  <div id="app">
    <el-container>
      <el-header>Header</el-header>
      <el-container>
        <el-aside width="200px">Aside</el-aside>
        <el-container>
          <el-main>Main</el-main>
          <el-footer>Footer</el-footer>
        </el-container>
      </el-container>
    </el-container>
  </div>
  <style>
    .el-header,
    .el-footer {
      background-color: #B3C0D1;
      color: #333;
      text-align: left;
      line-height: 60px;
    }

    .el-aside {
      background-color: #D3DCE6;
      color: #333;
      text-align: center;
      line-height: 200px;
    }

    .el-main {
      background-color: #E9EEF3;
      color: #333;
      text-align: center;
      line-height: 590px;
    }
  </style>
</body>
<script>
  new Vue({
    el: '#app'
  });
</script>
Dropdown 下拉菜单

将动作或菜单折叠到下拉菜单中。

<el-dropdown split-button size="small" trigger="click">
    个人中心
    <el-dropdown-menu>
        <el-dropdown-item>退出系统</el-dropdown-item>
        <el-dropdown-item divided>修改密码</el-dropdown-item>
        <el-dropdown-item divided>联系管理员</el-dropdown-item>
    </el-dropdown-menu>
</el-dropdown>
  • <el-dropdown split-butto> 下拉按钮
  • <el-dropdown-menu> 下拉菜单
  • <el-dropdown-item> 下拉项
  • divided 分隔
NavMenu 导航菜单

为网站提供导航功能的菜单。

<el-menu>
    <el-submenu index="1">
        <template slot="title">
            <i class="el-icon-location"></i>
            <span slot="title">导航一</span>
        </template>
        <el-menu-item>选项1</el-menu-item>
        <el-menu-item>选项2</el-menu-item>
        <el-menu-item>选项3</el-menu-item>
    </el-submenu>
    <el-submenu index="2">
        <template slot="title">
            <i class="el-icon-menu"></i>
            <span slot="title">导航二</span>
        </template>
        <el-menu-item>选项1</el-menu-item>
        <el-menu-item>选项2</el-menu-item>
        <el-menu-item>选项3</el-menu-item>
    </el-submenu>
</el-menu>
  • <el-menu>:导航菜单
  • <el-submenu index="1">:导航按钮
  • <template slot="title">标题和名称
  • <i class="el-icon-menu">图标
  • <span slot="title">导航二</span>:导航标题
  • <el-menu-item>导航项
Table 表格

用于展示多条结构类似的数据,可对数据进行排序、筛选、对比或其他自定义操作。

<el-table :data="tableData" stripe>
    <el-table-column prop="date" label="日期"></el-table-column>
    <el-table-column prop="name" label="姓名"></el-table-column>
    <el-table-column prop="address" label="地址"></el-table-column>
    <el-table-column label="操作" align="center">
        <!--
        slot-scope:作用域插槽,可以获取表格数据
        scope:代表表格数据,可以通过scope.row来获取表格当前行数据,scope不是
        固定写法
        -->
        <template slot-scope="scope">
            <el-button type="primary" size="mini"
                       @click="handleUpdate(scope.row)">编辑
            </el-button>
            <el-button type="danger" size="mini"
                       @click="handleDelete(scope.row)">删除
            </el-button>
        </template>
    </el-table-column>
</el-table>
<script>
    new Vue({
        el: '#app',
        data: {
            tableData: [{
                date: '2016-05-02',
                name: '王小虎',
                address: '上海市普陀区金沙江路 1518 弄'
            }, {
                date: '2016-05-04',
                name: '王小虎',
                address: '上海市普陀区金沙江路 1517 弄'
            }, {
                date: '2016-05-01',
                name: '王小虎',
                address: '上海市普陀区金沙江路 1519 弄'
            }]
        },
        methods: {
            handleUpdate(row) {
                alert(row.date);
            },
            handleDelete(row) {
                alert(row.date);
            }
        }
    });
</script>
  • <el-table :data="tableData" stripe>:表格\数据绑定对象\样式
  • <el-table-column prop="date" label="日期">:表格行\数据绑定对象属性\表头
  • align="center":居中
  • slot-scope:作用域插槽,可以获取表格数据
  • scope:代表表格数据,可以通过scope.row来获取表格当前行数据,scope不是固定写法
  • <el-button type="primary" size="mini" @click="handleUpdate(scope.row)">按钮\类型\大小\事件绑定
Pagination 分页

当数据量过多时,使用分页分解数据。

<!--
current-change:内置的事件,当前页码改变时会触发,可以获取到改变之后的页码
-->
<el-pagination
        @current-change="handleCurrentChange"
        current-page="5"
        page-size="10"
        layout="total, prev, pager, next, jumper"
        :total="305">
</el-pagination>
<script>
    new Vue({
        el: '#app',
        methods: {
            handleCurrentChange(page) {
                alert(page);
            }
        }
    });
</script>
  • <el-pagination>分页
  1. @current-change="handleCurrentChange"内置的事件,当前页码改变时会触发,可以获取到改变之后的页码
  2. current-page="5"当前页码
  3. page-size="10"显示页码总数
  4. layout="total, prev, pager, next, jumper"需要显示的分页组件
  5. :total="305"总数据条数
Message 消息提示

常用于主动操作后的反馈提示。

<el-button :plain="true" @click="open1">消息</el-button>
<el-button :plain="true" @click="open2">成功</el-button>
<el-button :plain="true" @click="open3">警告</el-button>
<el-button :plain="true" @click="open4">错误</el-button>
<script>
    new Vue({
        el: '#app',
        methods: {
            open1() {
                this.$message('这是一条消息提示');
            },
            open2() {
                this.$message({
                    message: '恭喜你,这是一条成功消息',
                    type: 'success'
                });
            },
            open3() {
                this.$message({
                    message: '警告哦,这是一条警告消息',
                    type: 'warning'
                });
            },
            open4() {
                this.$message.error('错了哦,这是一条错误消息');
            }
        }
    })
</script>
  • this.$message触发钩子
  1. message提示内容
  2. type: 'success'提示类型
  • this.$message.error("")异常警告和内容
Tabs 标签页

分隔内容上有关联但属于不同类别的数据集合。

<h3>基础的、简洁的标签页</h3>
<!--
通过value属性来指定当前选中的标签页
-->
<el-tabs value="first">
    <el-tab-pane label="用户管理" name="first">用户管理</el-tab-pane>
    <el-tab-pane label="配置管理" name="second">配置管理</el-tab-pane>
    <el-tab-pane label="角色管理" name="third">角色管理</el-tab-pane>
    <el-tab-pane label="定时任务补偿" name="fourth">定时任务补偿</el-tab-pane>
</el-tabs>
<h3>选项卡样式的标签页</h3>
<el-tabs value="first" type="card">
    <el-tab-pane label="用户管理" name="first">用户管理</el-tab-pane>
    <el-tab-pane label="配置管理" name="second">配置管理</el-tab-pane>
    <el-tab-pane label="角色管理" name="third">角色管理</el-tab-pane>
    <el-tab-pane label="定时任务补偿" name="fourth">定时任务补偿</el-tab-pane>
</el-tabs>
<h3>卡片化的标签页</h3>
<el-tabs value="first" type="border-card">
    <el-tab-pane label="用户管理" name="first">用户管理</el-tab-pane>
    <el-tab-pane label="配置管理" name="second">配置管理</el-tab-pane>
    <el-tab-pane label="角色管理" name="third">角色管理</el-tab-pane>
    <el-tab-pane label="定时任务补偿" name="fourth">定时任务补偿</el-tab-pane>
</el-tabs>
<script>
    new Vue({
        el: '#app'
    })
</script>
  • <el-tabs value="first">选项卡\默认选择项
  • <el-tab-pane label="用户管理" name="first">选项\显示名\标识name
    1.2.8 Form 表单
    由输入框、选择器、单选框、多选框等控件组成,用以收集、校验、提交数据。在 Form 组件中,每一个表单域由一个 Form-Item 组件构成,表单域中可以放置各种类型的表单控件,包括 Input、Select、Checkbox、Radio、Switch、DatePicker、TimePicker。
<div id="app">
    <el-form :model="ruleForm" :rules="rules" ref="ruleForm" 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="region">
            <el-select v-model="ruleForm.region" placeholder="请选择活动区域">
                <el-option label="区域一" value="shanghai"></el-option>
                <el-option label="区域二" value="beijing"></el-option>
            </el-select>
        </el-form-item>
        <el-form-item label="活动时间" required>
            <el-col :span="11">
                <el-form-item prop="date1">
                    <el-date-picker type="date" placeholder="选择日期" v-model="ruleForm.date1"
                                    style="width: 100%;"></el-date-picker>
                </el-form-item>
            </el-col>
            <el-col class="line" :span="2">-</el-col>
            <el-col :span="11">
                <el-form-item prop="date2">
                    <el-time-picker placeholder="选择时间" v-model="ruleForm.date2" style="width: 100%;"></el-time-picker>
                </el-form-item>
            </el-col>
        </el-form-item>
        <el-form-item label="即时配送" prop="delivery">
            <el-switch v-model="ruleForm.delivery"></el-switch>
        </el-form-item>
        <el-form-item label="活动性质" prop="type">
            <el-checkbox-group v-model="ruleForm.type">
                <el-checkbox label="美食/餐厅线上活动" name="type"></el-checkbox>
                <el-checkbox label="地推活动" name="type"></el-checkbox>
                <el-checkbox label="线下主题活动" name="type"></el-checkbox>
                <el-checkbox label="单纯品牌曝光" name="type"></el-checkbox>
            </el-checkbox-group>
        </el-form-item>
        <el-form-item label="特殊资源" prop="resource">
            <el-radio-group v-model="ruleForm.resource">
                <el-radio label="线上品牌商赞助"></el-radio>
                <el-radio label="线下场地免费"></el-radio>
            </el-radio-group>
        </el-form-item>
        <el-form-item label="活动形式" prop="desc">
            <el-input type="textarea" v-model="ruleForm.desc"></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>
</div>
<script>
    new Vue({
        el: "#app",
        data: {
            ruleForm: {
                name: '',
                region: '',
                date1: '',
                date2: '',
                delivery: false,
                type: [],
                resource: '',
                desc: ''
            },
            rules: {
                name: [
                    {required: true, message: '请输入活动名称', trigger: 'blur'},
                    {min: 3, max: 5, message: '长度在 3 到 5 个字符', trigger: 'blur'}
                ],
                region: [
                    {required: true, message: '请选择活动区域', trigger: 'change'}
                ],
                date1: [
                    {type: 'date', required: true, message: '请选择日期', trigger: 'change'}
                ],
                date2: [
                    {type: 'date', required: true, message: '请选择时间', trigger: 'change'}
                ],
                type: [
                    {type: 'array', required: true, message: '请至少选择一个活动性质', trigger: 'change'}
                ],
                resource: [
                    {required: true, message: '请选择活动资源', trigger: 'change'}
                ],
                desc: [
                    {required: true, message: '请填写活动形式', trigger: 'blur'}
                ]
            }
        },
        methods: {
            submitForm(formName) {
                this.$refs[formName].validate((valid) => {
                   alert(valid)
            });

            },
            resetForm(formName) {
                this.$refs[formName].resetFields();
            }
        }
    })
</script>
  • <el-form :model="ruleForm" :rules="rules" ref="ruleForm" >:表单/绑定数据模板/绑定校验
  • <el-form-item label="活动名称" prop="name">表单项\显示内容\数据模板属性绑定
  • <el-input v-model="ruleForm.name">表单输入框/数据绑定
  1. <el-select v-model="ruleForm.region" placeholder="请选择活动区域">:下拉框/数据绑定/提示
  • <el-option label="区域一" value="shanghai"></el-option>:下拉项/数据项
  1. ref绑定校验信息

借鉴文章出处

表格如何实现分页加载

vue实现简单的分页功能
变量:
步骤1:计算页数
 data() {
    return {
      // 假设这是后台传来的数据来源
      data: [],
      // 所有页面的数据
      totalPage: [],
      // 每页显示数量
      pageSize: 5,
      // 共几页
      pageNum: 1,
      // 当前显示的数据
      dataShow: "",
      // 默认当前显示第一页
      currentPage: 0
    };
  },
步骤二:根据页数对数据分组,并存进每一页
    // 这里简单模拟一下后台传过来的数据
    for (let i = 0; i < 601; i++) {
      this.data.push({ name: "liu" ,look:"very handsome"});
    }
    // 根据后台数据的条数和每页显示数量算出一共几页,得0时设为1 ;
    this.pageNum = Math.ceil(this.data.length / this.pageSize) || 1;
步骤三:设置默认显示页,上一页下一页,只需要切换当前页面的索引值就行了
   for (let i = 0; i < this.pageNum; i++) {
      // 每一页都是一个数组 形如 [['第一页的数据'],['第二页的数据'],['第三页数据']]
      // 根据每页显示数量 将后台的数据分割到 每一页,假设pageSize为5, 则第一页是1-5条,即slice(0,5),第二页是6-10条,即slice(5,10)...
      this.totalPage[i] = this.data.slice(this.pageSize * i, this.pageSize * (i + 1))
    }
   // 获取到数据后显示第一页内容
    this.dataShow = this.totalPage[this.currentPage];

借鉴文章出处

表单验证如何实现

最简单的表单验证

在官方文档中,尤大已经提供了一个表单验证的示例,这个示例让我想起给某银行做自动化工具时的情景,因为这两者都是采用MVVM的思想,所以,理解起来是非常容易的,即:通过一个列表来存储错误信息,而这个错误信息会绑定到视图层,所以,验证的过程其实就是向这个列表里添加错误信息的过程。我们一起来看这个例子:

<div>
    <h2>你好,请登录</h2>
    <div>
        <form id="loginFrom">
            <div>
                <label>邮箱</label>
                <input type="text" class="form-control" id="inputEmail3" placeholder="Email" v-model="email">
                </div>
            </div>
            <div>
                <label>密码</label>
                <input type="password" class="form-control" id="inputPassword3" placeholder="Password" v-model="password">
            </div>
            <div>
               <button type="button" class="btn btn-default login" v-on:click="login()">登录</button>
            </div>
            <div v-if="errorList.length > 0">
                <div class="alert alert-danger" role="alert">{{errorList.join(';')}}</div>
            </div>
        </form>
    </div>
</div>
<script>
var vm = new Vue({
    el: '#loginFrom',
    data: {
        email: "",
        password: "",
        errorList: []
    },
    methods: {
        validate: function () {
            this.errorList = []
            if (this.email == '') {
                this.errorList.push('请输入邮箱');
            } else {
                var reg = /^([a-zA-Z]|[0-9])(\w|\-)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/;
                if (!reg.test(this.email)) {
                    this.errorList.push('请输入有效的邮箱');
                }
            }
            if (this.password == '') {
                this.errorList.push('请输入密码');
            } else {
                if (this.password.length < 6) {
                    this.errorList.push('密码长度不得少于6位');
                }
            }

            return this.errorList.length <= 0;
        },
        login: function () {
            if (this.validate()) {
                alert('登录成功');
            }
        }
    }
});
</script>

为了排除无关内容对大家的影响,写这个例子的时候,博主排除了一切复杂的HTML结构和CSS样式,经过简单润色以后,这个例子的效果展示如下,果然GUI满足了人们颜控的一面,可让这个世界高速运行的是CLI,Bootstrap是博主这种“全栈工程师”的最爱之一。这种验证方式简直是人类本能的反应,可这恰好是最糟糕的一个例子,因为这个代码完全没法复用,可以想象得到,如果再继续增加针对密码强度,譬如大小写、数字等等的验证,这个代码会混乱成什么样子,所以,这是最简单的表单验证,同样是最糟糕的表单验证。

借鉴文章出处

function 和 箭头函数 的区别是什么

箭头函数是普通函数的简写,可以更优雅的定义一个函数,和普通函数相比,有以下几点差异:
1、函数体内的 this 对象,就是定义时所在的对象,而不是使用时所在的对象。
2、不可以使用 arguments 对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。
3、不可以使用 yield 命令,因此箭头函数不能用作 Generator 函数。
4、不可以使用 new 命令,因为:
  • 没有自己的 this,无法调用 call,apply。
  • 没有 prototype 属性 ,而 new 命令在执行时需要将构造函数的 prototype 赋值给新的对象的 proto
function newFunc(father, ...rest) {
  var result = {};
  result.__proto__ = father.prototype;
  var result2 = father.apply(result, rest);
  if (
    (typeof result2 === 'object' || typeof result2 === 'function') &&
    result2 !== null
  ) {
    return result2;
  }
  return result;
}

Vue 组件封装怎么做

vue组件的定义

● 组件(Component)是Vue.js最强大的功能之一

● 组件可以扩展HTML元素,封装可重用代码

● 在较高层面上,组件是自定义元素,Vue.js的编译器为他添加特殊功能

● 有些情况下,组件也可以表现用 is 特性进行了扩展的原生的HTML元素

● 所有的Vue组件同时也都是Vue实例,所以可以接受相同的选项对象(除了一些根级特有的选项),并提供相同的生命周期钩子
vue组件的功能

1)能够把页面抽象成多个相对独立的模块

2)实现代码重用,提高开发效率和代码质量,使得代码易于维护
Vue组件封装过程

● 首先,使用Vue.extend()创建一个组件

● 然后,使用Vue.component()方法注册组件

● 接着,如果子组件需要数据,可以在props中接受定义

● 最后,子组件修改好数据之后,想把数据传递给父组件,可以使用emit()方法
组件使用流程详细介绍

组件创建—有3中方法,extend()
A、调用Vue.extend(),创建名为myCom的组件,template定义模板的标签,模板的内容需写在该标签下
var myCom = Vue.extend({
    template: '<div>这是我的组件</div>'
})
B、标签创建,需要加上id属性
<template id="myCom">
    <div>这是template标签构建的组件</div>
</template>
C、
<script type="text/x-template" id="myCom1">
    <div>这是script标签构建的组件</div>
</script>
2、注册组件----有2中方法,全局注册,局部注册
// A1、全局注册:一次注册( 调用Vue.component( 组件名称,为组件创建时定义的变量 ) ),可在多个Vue实例中使用。
// 我们先用全局注册,注册上面例子中创建的myCom组件
Vue.component('my-com',myCom)

// A2、全局注册语法糖:不需要创建直接注册的写法
Vue.component('my-com',{
    'template':'<div>这是我的组件</div>'
})

// 'my-com'为给组件自定义的名字,在使用时会用到,后面myCom对应的就是上面构建的组件变量。
// A3、如果是用template及script标签构建的组件,第二个参数就改为它们标签上的id值
Vue.component('my-com',{
    template: '#myCom'
})
// B1、局部注册:只能在注册该组件的实例中使用,一处注册,一处使用
var app = new Vue({
    el: '#app',
    components: {
        'my-com': myCom
    }
})

// B2、局部注册语法糖:
var app = new Vue({
    el: '#app',
    components: {
        'my-com': {
           template: '<div>这是我的组件</div>'
        }
    }
})

// B3、<template><script>创建的组件,局部注册
var app = new Vue({
    el: '#app',
    components: {
        'my-com': {
           template: '#myCom'
        }
    }
})
3、调用组件

只需要在调用组件的地方,写上组件名字的标签即可

<div>
    /*调用组件*/
    <my-com></my-com>
</div>
4、栗子
A、全局注册:新建一个html文件,引入vue.js,并且定义2个vue实例app1和app2
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vue组件</title>
    <script src="vue.js"></script>
</head>
<body>
    <div id="app1">
        <my-com></my-com>
    </div>
    <div id="app2">
        <my-com></my-com>
    </div>
 
    <script>
        /*创建组件*/
        var myCom = Vue.extend({
            template: '<div>这是我的组件</div>'
        });
        /*全局注册组件*/
        Vue.component('my-com',myCom);
 
        /*定义vue实例app1*/
        var app1 = new Vue({
            el: '#app1'
        });
 
        /*定义vue实例app2*/
        var app2 = new Vue({
            el: '#app2'
        });
    </script>
</body>
</html>

显示效果:

在这里插入图片描述
可以看到,全局注册的组件在实例app1和实例app2中都可以被调用。

B、局部注册:将创建的组件注册到实例app1下
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vue组件</title>
    <script src="vue.js"></script>
</head>
<body>
    <div id="app1">
        <my-com></my-com>
    </div>
    <div id="app2">
        <my-com></my-com>
    </div>
 
    <script>
        var myCom = Vue.extend({
            template: '<div>这是我的组件</div>'
        });
 
        // Vue.component('my-com',myCom);
        /*局部注册组件*/
        var app1 = new Vue({
            el: '#app1',
            components:{
                'my-com':myCom
            }
        });
 
        var app2 = new Vue({
            el: '#app2'
        });
    </script>
</body>
</html>

在这里插入图片描述
可以看到只渲染了app1实例下的组件,app2实例虽然调用了该组件,但是因为这个组件没有在其内部注册,也没有全局注册,所以报错说找不到该组件。

C、template 和script标签创建组件
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vue组件</title>
    <script src="vue.js"></script>
</head>
<body>
    <div id="app1">
        <my-com></my-com>
        <my-com1></my-com1>
    </div>
 
    <template id="myCom">
        <div>这是template标签构建的组件</div>
    </template>
 
    <script type="text/x-template" id="myCom1">
        <div>这是script标签构建的组件</div>
    </script>
 
    <script>
        Vue.component('my-com1',{ //全局注册
            template: '#myCom1'
        });
 
        var app1 = new Vue({
            el: '#app1',
            components:{
                'my-com':{
                    template: '#myCom'  //局部注册
                }
            }
        });
    </script>
</body>
</html>

显示效果:
在这里插入图片描述

5、异步组件

vue作为一个轻量级前端框架,其核心就是组件化开发。我们一般常用的是用脚手架vue-cli来进行开发和管理,一个个组件即为一个个vue页面,这种叫单文件组件。我们在引用组件之时只需将组件页面引入,再注册即可使用。

当项目比较大型,结构比较复杂时,我们一般选用vue-cli脚手架去构建项目。因为vue-cli集成了webpack环境,使用单文件组件,开发更简单,易上手,尤其是在对组件的处理上。对于原生vue.js,我们就得将组件构建在同一个html的script标签下或者html的外部js中,所有组件集中在一块,不容易管理,这也是原生vue,js的一点不便之处

vue.js可以将异步组件定义为一个工厂函数。

使用$.get获取本地文件会跨域,所以要将项目部署到服务器中

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vue组件</title>
    <script src="vue.js"></script>
    <script type="text/javascript" src='jquery-3.1.1.min.js'></script>
</head>
<body>
    <div id="app1">
        <head-com></head-com>
    </div>
    <script>
        Vue.component('head-com', function (resolve, reject) {
            $.get("a.html").then(function (res) {
                resolve({
                    template: res
                })
            });
        });
 
        var app1 = new Vue({
            el: '#app1'
        });
 
    </script>
</body>
</html>

显示效果如下:
在这里插入图片描述

6、Vue中的props数据流

通过在注册组件中申明需要使用的props,然后通过props中与模板中传入的对应的属性名,去取用这些值

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vue组件</title>
    <script src="vue.js"></script>
    <script type="text/javascript" src='jquery-3.1.1.min.js'></script>
</head>
<body>
    <div id='app'>
       <my-component name="jiangjiang" come-from="guilin"></my-component>
       <!-- 然后在模板中通过属性传值的方式进行数据的注入 -->
    </div>
    <script>
        Vue.component('my-component', {
          props: ['name', 'comeFrom'],    //在注册组件的时候通过props选项声明了要取用的多个prop
          // 在注册组件的模板中使用到props选项中声明的值
          template: '<p>我叫:{{name}}, 我来自:{{comeFrom}}</p>',
          created: function () {
            console.log('在created钩子函数中被调用')
            console.log('我叫:', this.name)
            console.log('我来自:', this.comeFrom)
          }
        })
 
 
        new Vue({
          el: '#app'
        })
 
 
    </script>
</body>
</html>

在这里插入图片描述
注意:

A、props取值的方式
// 在注册组件的模板内部template,直接通过prop的名称取值就Ok
template: '<p>我叫:{{name}}, 我来自:{{comeFrom}}</p>'

// 不在注册组件的模板内部template,用this.prop的方式
 console.log('我来自:', this.comeFrom)
B、在template选项属性中,可以写驼峰命名法,也可以写短横线命名法
  在HTML(模板)中,只能写短横线命名法

原因:vue组件的模板可以放在两个地方

a、Vue组件的template选项属性中,作为模板字符串

b、放在.html中[ 用script template标签创建的组件 ],作为HTML

问题在于HTML不区分大小写,所以在vue注册组件中通用的驼峰命名法,不适用于HTML中的Vue模板,在HTML中写入props属性,必须写短横线命名法(把原来props属性中的每个prop大写换成小写,并且在前面加“-”)

// 将6中的
    <div id='app'>
       <my-component name="jiangjiang" come-from="guilin"></my-component>
       <!-- 然后在模板中通过属性传值的方式进行数据的注入 -->
    </div>
// 改成
    <div id='app'>
       <my-component name="jiangjiang" comeFrom="guilin"></my-component>
       <!-- 然后在模板中通过属性传值的方式进行数据的注入 -->
    </div>

显示效果,第二个没有显示
在这里插入图片描述
异步组件的实现原理;异步组件的3种实现方式—工厂函数、Promise、高级函数

异步组件实现的本质是2次渲染,先渲染成注释节点,当组件加载成功后,在通过forceRender重新渲染

高级异步组件可以通过简单的配置实现loading resolve reject timeout 4种状态

借鉴文章出处

v-model 怎么实现

前言

在 Vue 中,v-model 是一个常用的指令,用于实现表单元素和组件之间的双向绑定。当我们使用原生的表单元素时,直接使用 v-model 是很方便的,但是对于自定义组件来说,要实现类似的双向绑定功能就需要一些额外的处理。

本篇文章将介绍几种在自定义组件中实现 v-model 的方式,主要如下:

使用 v-model 属性:适用于表单元素

定义 model 属性:适用于非表单元素

除了以上的两种方式外,还有我们通常使用的.sync 修饰符[1](2.3.0+ 新增),主要区别在于使用方式的不同,前者直接使用 v-model,后者使用 .sync 修饰符进行绑定

一. 单向数据流

所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外变更父级组件的状态,从而导致你的应用的数据流向难以理解。

注意:每次父级组件发生变更时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变 prop。虽然可以,但是如果你这样做了,Vue 会在浏览器的控制台中发出警告。
二. 基础原理浅析

v-model 实际上就是 props:value 和 $emit(‘input’) 的组合语法糖,简单来说,v-model 的使用其实做了两个比较重要的操作,理解这两个操作,我们就可以轻松实现组件的自定义 v-model

v-bind 绑定 value 属性的值 - props:value;

v-on 绑定 input 事件监听到函数中,函数会获取最新的值赋值到绑定的属性中 - $emit(‘input’);

三. 实现 v-model 的两种方式
1. 直接使用 v-model 属性

适用于表单元素,或者原组件已经实现了 v-model,需要我们进行二次封装

以 input 表单元素为例,在 vue 中,我们可以直接使用 v-model 进行绑定数据,当我们在实现自定义组件custom-component进行封装 input 时,我们的组件对外暴露时也需要使用 v-model,看下面我们应该如何实现:

在自定义组件中,我们可以通过在组件内部使用 value 属性和手动触发 input 事件来实现 v-model 的双向绑定效果。具体实现如下:

<template>
  <input v-model="newValue" />
</template>
 
<script>
  export default {
    props: {
      value: {
        type: Boolean,
        default: false,
      },
    },
    computed: {
      newValue: {
        get() {
          return this.value;
        },
        set(val) {
          this.$emit("input", val);
        },
      },
    },
  };
</script>

使用custom-component

<custom-component v-model="newValue" />

在上述代码中,我们通过 value 属性接收父组件传入的值,并且使用 computed 的 set 属性用来监听值的更新,手动触发 $emit(‘input’, value) 来将新值传递给父组件,从而实现双向绑定的效果。

2. 定义 model 属性
适用于非表单元素,完全非表单元素自定义的组件

Vue 允许我们在定义组件中通过定义 model 属性来简化 v-model 的使用。通过定义 model 属性,我们可以指定组件中哪个属性的值应该作 v-model 的值。

假如我们实现一个计数器的组件custom-counter,在页面中显示两个按钮,点击按钮可以进行数值的加减操作,具体示例如下:

<template>
  <div>
    <button @click="increment">+</button>
    <span>{{ value }}</span>
    <button @click="decrement">-</button>
  </div>
</template>
 
<script>
  export default {
    // 当 model 为默认值时,可以将其省略
    model: {
      prop: "value", // 默认是 value
      event: "input", // 默认是 input
    },
    props: {
      value: {
        type: Number,
        default: 0,
      },
    },
    methods: {
      increment() {
        this.$emit("input", this.value + 1);
      },
      decrement() {
        this.$emit("input", this.value - 1);
      },
    },
  };
</script>
提示:当 model 为默认值时,可以将其省略

请添加图片描述
在上面的示例中,CustomCounter组件接收一个value属性来接收父组件传递的值,并在点击按钮时修改value属性的值。通过调用this.$emit(‘input’, newValue)触发input事件,将新的value值传递给父组件进行更新。

在父组件中,使用v-model将父组件中的count属性绑定到CustomCounter组件的value属性上,绑定 input 事件监听到函数中,从而实现了数据的双向绑定。

model 是允许 vue 自定义组件使用 v-model 的关键,虽然有时我们不显性的使用它,也不影响我们在自定义组件中使用 v-model 指令,这只是因为被设置默认值。而有的时候,显示的使用,并自定义 model 的 prop 和 event 会有益。

注意:允许一个自定义组件在使用 v-model 时定制 prop 和 event。默认情况下,一个组件上的 v-model 会把 value 用作 prop 且把 input 用作 event,但是一些输入类型比如单选框和复选框按钮可能想使用 value prop 来达到不同的目的。使用 model 选项可以回避这些情况产生的冲突。
四. .sync 修饰符
适用于提供于多个双向绑定的 prop,灵活提供你想要绑定的 property 名

在有些情况下,我们可能需要对一个 prop 进行 “双向绑定”。但是,真正的双向绑定会带来维护上的问题,因为子组件可以变更父组件,且在父组件和子组件两侧都没有明显的变更来源。

这也是为什么我们推荐以 update:myPropName 的模式触发事件取而代之。

举个例子,还是上面的计数器的例子,在一个包含 count prop 的计数组件中,我们可以用以下方法表达对其赋新值的意图:

this.$emit("update:count", newCount);

然后父组件可以监听那个事件并根据需要更新一个本地的数据 property。例如:

<custom-counter v-bind:count="count" v-on:update:count="count = $event" />

我们为这种模式提供一个缩写,即 .sync 修饰符,如下:

<custom-counter :count.sync="count"></custom-counter>

以上的两种写法是等价的

注意:带有 .sync 修饰符的 v-bind 不能和表达式一起使用 (例如 v-bind:count.sync=”count + 1” 是无效的)。取而代之的是,你只能提供你想要绑定的 property 名,类似 v-model。
五. 总结

本篇文章介绍了在 Vue 自定义组中实现 v-model 的几种方式,包括定义 model 属性和使用 v-model 属性。通过以上案例实际分析,相信大家都已经了解这几种方式的创建以及应用场景,以便更加灵活地应用到实际项目中。

以上面两种方式为例,我们可以灵活地根据自己的需求选择合适的方式来实现自定义组件 v-model。如果是表单元素,可以直接使用 v-model 属性;如果是非表单元素,可以通过定义 model 属性指定组件中哪个属性的值应该作 v-model 的值。

除此之外,使用 .sync 修饰符也是进行自定义组件双向绑定的优秀选择,因此在实际开发中,选择适合自己项目需求的方式是最重要的。

借鉴链接展示

https://v2.cn.vuejs.org/v2/guide/components-props.html

https://v2.cn.vuejs.org/v2/guide/components-custom-events.html
https://v2.cn.vuejs.org/v2/guide/components-custom-events.html#sync-%E4%BF%AE%E9%A5%B0%E7%AC%A6

借鉴链接出处

插槽 使用

父子组件 的使用

一个管理系统有不同权限用户,怎么实现

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐