vue-cli引用组件的方法

Step1 import组件

Step2 注册组件

1
2
3
4
5
6
7
8
9
10
<script>
import navigator from '@/components/Navigator'

export default {
name: 'App',
components: {
navigator
}
}
</script>

ES6:export和import

  • 2018-4-21

ES6模块主要有两个功能:export和importexport用于定义模块对外的接口(一般而言,一个独立的js文件对应一个模块),import用于在一个模块中加载另一个含有export接口的模块。

1.export和import

1.导入和导出单个变量

export.js

1
export var name='LoliMay' //导出name变量

import.js

1
2
3
4
5
6
7
8
9
import { name } from './export.js' //从export.js中导入name变量
export default {
data() {
return { }
},
created: function() {
alert(name) //弹出'LoliMay'
}
}

2.导入和导出多个变量

export.js

1
2
3
var name1 = 'George'
var name2 = 'LoliMay'
export { name1, name2 } //导出多个变量

import.js

1
2
3
4
5
6
7
8
9
10
import { name1, name2 } from './export.js' //从export.js中导入多个变量
export default {
data () {
return { }
},
created: function() {
alert(name1) //弹出'George'
alert(name2) //弹出'LoliMay'
}
}

3.导入和导出函数

export.js

1
2
3
4
function add(x, y) {
return x+y
}
export { add } //导出add函数

import.js

1
2
3
4
5
6
7
8
9
import { add } from './export.js' //导入add函数
export default {
data () {
return { }
},
created: function() {
alert(add(4,6)) //弹出'10'
}
}

由此可见,函数也是对象,它的导入和导出的格式同1一样。

2. export与export default的区别

  • 在一个文件模块中,exportimport可以有多个,export default仅有一个
  • 通过export方式导出,在导入时要加{},export default则不需要
  • 使用export default指定默认输出,导入时允许为这个模块取任意名字
  • export不能与var,let,const一起用
1
2
3
4
5
6
7
8
9
10
11
12
//export.js
export const str = 'I am LoliMay.' //在同一个文件模块中export可以出现多次
export function log(sth) {
return sth
}
var name = 'LoliMay'
export default name //在同一个文件模块中export default只能出现一次
export default var age //错误,export不能与var、let或const一起用

//import.js
import { str, log } from './export.js' //通过export方式导出,在导入时要加{}
import myName from './export.js' //通过export default方式导出,在导入时不需要加{},且可以取任意名字

封装seltiplist组件

1.编写组件

1.清单

依赖清单:

  • underscore.min.js JavaScript工具库

编写清单:

  • seltipoption.vue SelectTipOption,SelectTipList的子组件
  • seltiplist.vue SelectTipList,SelectTipOption的父组件
  • emitter.js 用于父子组件通讯

2.seltipoption.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<template>
<span class="tip" @click="selectOptionClick" :class="{'active':itemSelected }">{{currentLabel}}</span>
</template>
<script type="text/ecmascript-6">
import Emitter from '../util/emitter'
var underscore = require('../lib/underscore.min')
export default{
mixins: [Emitter],
componentName: 'seltipoption',
props: {
value: {
required: true
},
label: [String, Number]
},
computed: {
currentLabel () {
return this.label || ((typeof this.value === 'string' || typeof this.value === 'number') ? this.value : '')
},
parent () {
let result = this.$parent
while (!result.istipSelect) {
result = result.$parent
}
return result
},
itemSelected () {
if (!this.parent.multiple) {
return underscore._.isEqual(this.parent.value, this.value)
} else {
let isSelected = false
this.parent.value.forEach((item, index) => {
if (underscore._.isEqual(item, this.value)) {
isSelected = true
}
})
return isSelected
}
}
},
methods: {
selectOptionClick () {
this.dispatch('seltiplist', 'handleOptionClick', this.value)
}
}
}
</script>

3.seltiplist.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<template>
<div>
<slot></slot>
</div>
</template>
<script type="text/ecmascript-6">
import Emitter from '../util/emitter'
var underscore = require('../lib/underscore.min')
export default{
mixins: [Emitter],
componentName: 'seltiplist',
data () {
return {
istipSelect: true
}
},
props: {
value: {},
multiple: {
type: Boolean,
default: false
}
},

mounted () {
this.$on('handleOptionClick', this.handleOptionSelect)
},
methods: {
handleOptionSelect (val) {
if (this.multiple && underscore._.isArray(this.value)) {
let optionIndex = this.value.indexOf(val)
this.value.forEach((item, index) => {
if (underscore._.isEqual(item, val)) {
optionIndex = index
}
})
if (optionIndex < 0) {
this.value.push(val)
} else {
this.value.splice(optionIndex, 1)
}
} else {
if (val !== this.value) {
this.$emit('input', val)
} else {
this.$emit('input', '')
}
}
}
}
}
</script>

4.emitter.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
function broadcast (componentName, eventName, params) {
this.$children.forEach(child => {
var name = child.$options.componentName
if (name === componentName) {
child.$emit.apply(child, [eventName].concat(params))
} else {
broadcast.apply(child, [componentName, eventName].concat(params))
}
})
}
export default {
methods: {
dispatch (componentName, eventName, params) {
var parent = this.$parent || this.$root
var name = parent.$options.componentName

while (parent && (!name || name !== componentName)) {
parent = parent.$parent

if (parent) {
name = parent.$options.componentName
}
}
if (parent) {
parent.$emit.apply(parent, [eventName].concat(params))
}
},
broadcast (componentName, eventName, params) {
broadcast.call(this, componentName, eventName, params)
}
}
}

2.使用组件

App.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
<template>
<div style="width: 1100px;margin: 40px auto">
<div class="conditionbox">
<div class="selectlist">
<div class="title">地区</div>
<div class="select-box">
<seltiplist v-model="loacl_select">
<seltipoption v-for=" item in local " :label="item.label" :value="item" :key="item.id"></seltipoption>
</seltiplist>
</div>
</div>
<div class="selectlist">
<div class="title">薪资要求</div>
<div class="select-box">
<seltiplist v-model="salary_select">
<seltipoption v-for=" item in salary " :label="item.label" :value="item" :key="item.id"></seltipoption>
</seltiplist>
</div>
</div>
<div class="selectlist">
<div class="title">福利待遇</div>
<div class="select-box">
<seltiplist :multiple="true" v-model="treatment_select">
<seltipoption v-for=" item in treatment " :label="item.label" :value="item" :key="item.id"></seltipoption>
</seltiplist>
</div>
</div>
<div class="selectlist">
<div class="title">已选条件</div>
<div class="select-box">
<span class="tip active" v-if="loacl_select">{{loacl_select.label}}</span>
<span class="tip active" v-if="salary_select">{{salary_select.label}}</span>
<span class="tip active" v-for="item in treatment_select" :key="item.id">{{item.label}}</span>
</div>
</div>
</div>
</div>
</template>
<script>
import seltiplist from './components/seltiplist.vue'
import seltipoption from './components/seltipoption.vue'

export default {
components: {
seltiplist,
seltipoption
},
data () {
return {
loacl_select: '',
treatment_select: [
{
id: 4,
label: '项目奖金'
}
],
salary_select: '',
local: [
{
id: 1,
label: '北京'
},
{
id: 2,
label: '安徽'
},
{
id: 3,
label: '上海'
},
{
id: 4,
label: '广州'
},
{
id: 5,
label: '青岛'
}
],
treatment: [
{
id: 1,
label: '五险一金'
},
{
id: 2,
label: '交通补助'
},
{
id: 3,
label: '带薪年假'
},
{
id: 4,
label: '项目奖金'
}
],
salary: [
{
id: 1,
label: '4000以下'
},
{
id: 2,
label: '4000-6000'
},
{
id: 3,
label: '6000-8000'
},
{
id: 4,
label: '8000以上'
}
]
}
},
methods: {}
}
</script>
<style>
body,
html {
margin: 0;
padding: 0;
font-family: PingFang SC, Hiragino Sans GB, Microsoft Yahei, SimSun, Arial,
Helvetica Neue, Helvetica;
-webkit-font-smoothing: antialiased;
line-height: 1.42857143;
color: #666;
font-size: 14px;
background: #fdfbfb;
}

.conditionbox {
width: 100%;
margin-top: 10px;
background: #fff;
padding: 20px;
}

.selectlist {
padding-top: 10px;
padding-bottom: 10px;
}

.selectlist .title {
display: inline-block;
width: 98px;
margin-left: 10px;
font-weight: 700;
font-size: 15px;
margin-top: 3px;
}

.selectlist .select-box {
width: 897px;

position: relative;
display: inline-block;
}
span.tip {
padding: 3px 6px;
cursor: pointer;
border-radius: 3px;
font-weight: 600;
margin: 1px 2px;
color: #465364;
}
span.tip:hover {
color: #fff;
background: #465364;
}
span.tip.active {
color: #fff;
background: #465364;
}
</style>

3.代码解释

1.两个组件

一个标签组件seltipoption,方便用v-for进行渲染

一个父组件seltiplist管理v-model接收seltipoption事件

2.实现自定义组件v-model数据双向绑定

如果要让组件的v-model生效,则这个组件它必须:

  1. 接收一个value属性。

  2. 在有新的value时触发input事件,直接赋值给this.value是无效的,无法触发更新。

  3. 当为多选项时,更新seltiplist的value数组即可,但是当为单选项时,需要使用this.$emit('input', val)来触发更新

3.父子组件通讯

seltipoption.vue响应click事件后,通过this.dispatch('seltiplist', 'handleOptionClick', this.value)触发父组件seltiplist.vue的监听this.$on('handleOptionSelect')实现组件间的通讯。

4.seltipoption的选择状态判断

  • 当为单选时,判断seltipoptionvalue是都等于seltiplistvalue
  • 当为多选时,seltipoptionvalue存在seltiplistvalue数组中

5.为了判断两个value值是否相等

此处引入工具库underscore.min.js

Shirt+Enter与Enter按键功能互换

1
2
3
4
5
#IfWinActive, ahk_class Chrome_WidgetWin_1
Enter::+Enter
return
$+Enter:: Send {Enter}
return

安装vux组件库

vux是一款优秀的移动端UI组件库,强烈推荐使用,下面分享一下自己的踩坑记录~

vue从入门到放弃

哈哈,虽然标题是这样起的,但是Web工程化的好处可是大大的呀,方便项目的前期构建同时也有利于后期维护,所以还是尽早入坑吧~

GET与POST的区别

  • 2018-3-21

1. 参数

  • GET传递的参数只能带URL后面,文本格式QueryString,各浏览器一般有长度限制,一般认为是2083,如果有中文字符则更短。提交到服务端的数据量小。
  • POST可以传递application/x-www-form-urlencoded的类似QueryString、multipart/form-data的二进制报文形式(支持文件信息嵌入报文传输)、纯文本或二进制的body参数。提交到服务器端的数据量大。

2. 缓存

  • GET默认可以复用前面的请求数据作为缓存结果返回,此时以完整的URL作为缓存数据的KEY。

    有时候为了强制每次GET请求都是新数据,我们可以在URL后面加上一个随机参数、时间戳或版本号。比如,在jQuery.ajax()方法中,如果把cache=false,则会在GET请求参数中附加_={timesatmp}来禁用缓存。

  • POST则一般不会被缓存因素影响。

3. 安全性

  • 默认对于nginx的access log,会自动记录GET和POST的完整URL,包括其中带的参数。
  • 而对于POST来说,请求的报文却不会被记录,这对于敏感数据来说POST更安全一些。

注:这两者都是明文传送,只是GET的URL会被记录在浏览器和Web服务器的日志中,而POST发完就发完了,不存在什么历史和日志什么的。但是如果被抓了包,GET和POST都没什么卵用,HTTPS该用还是得用。

4. 用途

  • GET用于从服务端获取数据,包括静态资源的加载、动态数据的展示等。
  • POST用于向数据提交数据,比如新增、删除、修改数据等。

总的来说,可以重复的交互,比如取个数据、跳个页面用GET,不可以重复的操作,比如创建一个条目、修改一条记录用POST。

更改子元素的margin,但是父元素和子元素整体相对body偏移

如题,现附上解答了我的疑问的原文地址

第一位答主说,原因是父元素没有边界 我经过实际验证,他说的是对的,特地记下以备忘!

HTML实战:导航栏二级菜单

1. 框架结构

1
div#menu>ul>(li>a.drop+div.dropdown_1column>div.dropdown_1column-inner>ul>li*4)*4

在右键菜单中添加.html文件

Step1 修改注册表

这里推荐使用右键菜单管理工具修改,手动修改比较繁琐。

RightMenuMar点击下载

打开工具后,点击新建,再在右侧面板右击选择增加拓展项