目录标题
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不报错,但是过滤器是没有效果的
下面我们来讲一下过滤器的使用方法
使用方式
- 在双花括号插值
{{ 'ok' | globalFilter }}
- 在v-bind表达式中使用
<div v-bind:data="'ok' | globalFilter" ></div>
参数写法
{{ 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年 那年你很美!
{{ 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
- {{ ‘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 中数据:
- Props 作为初始值传入后,子组件想把它当作局部数据来用;
- 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 的作用是什么
前言
- 父组件可以使用 props 把数据传给子组件。
- 子组件可以使用 $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>
分页
@current-change="handleCurrentChange"
内置的事件,当前页码改变时会触发,可以获取到改变之后的页码current-page="5"
当前页码page-size="10"
显示页码总数layout="total, prev, pager, next, jumper"
需要显示的分页组件: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
触发钩子
message
提示内容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">
表单输入框/数据绑定
<el-select v-model="ruleForm.region" placeholder="请选择活动区域">
:下拉框/数据绑定/提示
<el-option label="区域一" value="shanghai"></el-option>
:下拉项/数据项
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;
}