winney

It is never too old to learn.

0%
winney

1、设置配置文件

  • 方法一:在根目录中新建vue.config.js文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
module.exports = {
runtimeCompiler: true,
devServer: {
proxy: {
// 匹配请求路径中的字符,
// 如果符合就用这个代理对象代理本次请求,路径为target的网址,
// changeOrigin为是否跨域,
// 如果不想始终传递这个前缀,可以重写路径
// pathRewrite为是否将指定字符串转换一个再发过去。
'/api': {
target: 'http://ttapi.research.itcast.cn/',
ws: true,
changeOrigin: true,
pathRewrite: {
'^/api': ''
}
}
}
}
}
  • 方法二:在根目录中,新建config>index.js文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
module.exports = {
dev: {
proxyTable: {
'/api': {
target: 'http://ttapi.research.itcast.cn/', // 接口的域名
secure: false, // 如果是https接口,需要配置这个参数
changeOrigin: true, // 如果接口跨域,需要进行这个参数配置
pathRewrite: {
'^/api': '' // '/api/a/user' =='localhost:8080/user'
}
}
}
}
}

2、axios请求方法的写法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
axios.get('http://ttapi.research.itcast.cn/app/v1_0/comments', {
params: {
type: 'a',
source: this.source,
offset: this.offset,
limit: this.limit
}
})
.then(function (response) {
console.log('response')
console.log(response)
})
.catch(function (error) {
console.log(error)
})

name属性是父组件传过来的,除了数组,对象,其他都不允许修改

props里面的数据,除了数组,对象,其他都不允许修改,所以不能用于页面元素的v-model属性中,因为v-model是双向绑定的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<van-field
v-model="localName"
...
/>
props: {
name: {
type: String,
required: true
}
},

data () {
return {
localName: this.name
}
},

当传递给子组件的数据既要使用又要修改,这种情况下我们可以使用v-model简写:

例如:父组件的name

1
2
:name="user.name"
@update-name="user.name=$event"

修改为:

1
v-model="user.name"

子组件也要跟着修改:

1
2
3
4
5
6
7
8
props: {
value: {
type: String,
required: true
}
},

this.$emit('input', this.localName)

v-model=”user.name”

默认传递一个名字叫value的数据: :value=”user.name”

默认监听input事件: @input=”user.name=$event”

v-model的本质还是父子组件通信,它仅仅是简化了父组件的使用,子组件还是按照原来那样使用

注:在同一个子组件传递中,v-model只能使用一次

1
2
3
4
5
这样是错误的:
<update-name
v-model="user.name"
v-model="user.photo"
/>
在同一个子组件传递中,v-model只能使用一次,如果有多个数据需要保持同步,使用.sync修饰符
1
2
3
4
<update-name
v-model="user.name"
:gender.sync="user.photo"
/>

注:我们一般把最常用的数据设计为v-model绑定,把不太常用的数据设计为.sync

销毁组件的一种方法:

1、加上v-if来控制渲染

1
2
3
4
5
<update-name
v-if="isEditNameShow"
v-model="user.name"
@close="isEditNameShow=false"
/>

在Vue中操作DOM,要给该元素添加ref属性

例如:点击头像,选择图片来修改头像

1、给input file添加ref属性

1
2
3
4
5
6
7
8
9
<input type="file" hidden ref="file">
<van-cell title="头像" is-link center @click="$refs.file.click()">
<van-image
width="30"
height="30"
round fit="cover"
:src="user.photo"
/>
</van-cell>

2、控制选择的文件类型:accept属性

1
<input type="file" hidden ref="file" accept="image/*">

3、监听文件的change事件

1
2
3
4
5
6
7
<input
type="file"
hidden
ref="file"
accept="image/*"
@change="onFileChange"
>

4、解决选择相同文件不触发change事件,手动清空file的value值

1
2
3
4
5
6
onFileChange() {
....

// 手动清空file的value值
this.$refs.file.value = ''
}

5、展示弹出层,在弹出层预览图片

1
2
3
4
5
6
7
8
9
10
11
onFileChange() {
// 展示弹出层
this.isEditPhotoShow = true

// 在弹出层预览选择的图片
const blod = window.URL.createObjectURL(this.$refs.file.files[0])
this.previewImage = blod

// 手动清空file的value值
this.$refs.file.value = ''
}

6、父传,子收。并展示预览图片

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
父传:
<update-photo
:image="previewImage"
/>
子收:
props: {
image: {
type: String,
required: true
}
},

<div class="update-photo">
<img :src="image">
</div>

7、修改父子组件传值的文件格式

如果Content-Type 要求是 multipart/form-data,则一定要提交FormData数据对象,专门用于文件上传的,不能提交{}对象,没用

所以要修改父组件传过来子组件的文件格式,保留原来的文件格式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
父组件:
onFileChange() {
....
const blod = this.$refs.file.files[0]
this.previewImage = blod
....
}

<update-photo
:file="previewImage"
@close="isEditPhotoShow=false"
/>
子组件:
props: {
file: {
// type: String,
required: true
}
},
data () {
return {
image: window.URL.createObjectURL(this.file)
}
},

8、处理接口传参

1
2
3
4
5
6
// 文件格式处理
const fd = new FormData()
fd.append('photo', this.file)
// photo为参数名,this.file为参数值

await updateUserPhoto(fd)

9、处理图片裁切,使用 cropperjs 这个跟vue没有关系,其他项目也可以使用) 也可以在Awesome 中搜crop找裁切工具

  • 1、安装
1
cnpm install cropperjs
  • 2、引入
1
2
import 'cropperjs/dist/cropper.css'
import Cropper from 'cropperjs'
  • 3、使用:放在mounted里面
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<img :src="image" ref="image">

mounted() {
const image = this.$refs.image
const cropper = new Cropper(image, {
viewMode: 1,
dragMode: 'move',
aspectRatio: 1,
// autoCropArea: 1,
cropBoxMovable: false,
cropBoxResizable: false,
background: false,
movable: true
})
console.log(cropper)
},
  • 4、让裁切区居中显示
1
2
3
4
5
6
7
8
9
.update-photo{
position: absolute;
top: 50%;
margin-top: -185px;
margin-left: -185px;
height: 370px;
left: 50%;
width:370px;
}
  • 5、获取裁切结果,getCroppedCanvas()
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
 data () {
return {
image: window.URL.createObjectURL(this.file),
cropper: null
}
},

使用Promise返回一个裁切对象,用于async
getCroppedCanvas() {
return new Promise(resolve => {
// 因为cropper定义在mounted中,在这里无法使用,
为了能够在这里能调用cropper,将cropper放在data中
this.cropper.getCroppedCanvas().toBlob((file) => {
resolve(file)
})
})
},

getCroppedCanvas返回的Promise对象,在这里面使用:
async onConfirm() {
.....
const file = await this.getCroppedCanvas()
const img = window.URL.createObjectURL(file)

// 文件格式处理
const fd = new FormData()
fd.append('photo', file)

await updateUserPhoto(fd)

this.$emit('close')
this.$emit('update-photo', img)

this.$toast.success('保存成功')
}

如果存在clipboard,先将它销毁

1
2
3
if(clipboard) {
clipboard.destroy();
}
Clipboard官网使用教程
复制成功和复制失败的提示
1
2
3
4
5
6
7
8
9
10
11
12
var u = navigator.userAgent;
clipboard.on('success', function(e) {
layer.msg('复制成功', {time: 1000});
e.clearSelection();
});
clipboard.on('error', function(e) {
if(u.indexOf('UCBrowser') > -1){
layer.msg('您的浏览器不支持,请长按内容手动复制!', {time: 1000});
} else {
layer.msg('复制失败', {time: 1000});
}
});
如果提示信息弹两次
1
2
3
4
5
自己写一个copySuccessTip提示信息
$(".copySuccessTip").addClass("mymove");
setTimeout(function() {
$(".copySuccessTip").removeClass("mymove");
},1000);

解决clipboard复制弹多次提示的问题

1、使用destroy(在单页面里面,回来页面,如果存在这个对象,就删除。)

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
// 如果存在clipboard,先将它销毁
if(clipboard){
clipboard.destroy();
}

var clipboard =new ClipboardJS('.copyBtn', {
text: function(trigger){
var txt = $(trigger).data( "clipboard-text");
return txt; // 返回需要复制的内容
}
});

var u = navigator.userAgent;

clipboard.on('success', function(e){
layer.msg('复制成功');
e.clearselection();
});

clipboard.on('error', function(e) {
if(u.indexOf("UCBrowser") >-1){
layer.msg('您的浏览器不支持,请长按内容手动复制!');
}else {
layer.msg('复制失败');
}
});

2、换成setTimeout,不用layer.msg(copySuccessTip的样式模拟layer.msg的样式即可)

1
2
3
4
5
6
7
clipboard.on('success', function(e){
$('.copySuccessTip').show();

setTimeout(function(){
$('.copySuccessTip').hide();
}, 1000);
});

这里以Chrome浏览器做演示

一、展开某元素的所有子节点

展开所有子节点.png (952×488) (raw.githubusercontent.com)

  1. 选中需要被展开的元素前面的三角箭头
  2. 按下键盘上的‘Alt’键
  3. 单击鼠标
  4. ”modal-dialog"里面的子节点都展开

收起

  1. 选中需要被展开的元素前面的三角箭头,单击鼠标,再单击鼠标,看到里面的子节点都是展开状态。
  2. 选中需要被展开的元素前面的三角箭头,按下键盘上的‘Alt’键,单击鼠标,再单击鼠标,看到里面的子节点是收起状态。

二、控制台写多行代码

在控制台,编写多行代码时,实现换行的快捷键:Shift + Enter

控制台写多行代码快捷键.png (448×264) (raw.githubusercontent.com)

三、全局搜索资源中的匹配代码/匹配文本

快捷键:Ctrl + Shift + F

注意:输入快捷键之前,在浏览器已经按了F12,也就是已经打开浏览器的开发者工具

如果没有打开浏览器的开发者工具就按Ctrl + Shift + F,输入法会切换到繁体字,如果不小心切换到繁体字状态,可以再按一次Ctrl + Shift + F,就切回来简体。(前提是操作系统中使用 Ctrl + Shift + F 快捷键来切换输入法的字体,如果不是,忽略)

全局搜索资源匹配文本1.png (896×360) (raw.githubusercontent.com)

全局搜索资源匹配文本2.png (715×582) (raw.githubusercontent.com)

这效果类似于在代码编辑器中,对项目进行全局搜索一样。但是有时在查看学习和了解别人网站时,可以使用这种全局搜索查找。

四、控制台中复制变量

有时候在控制台打印出来的变量值,想复制到其他地方。简单的变量,直接选中复制即可。但是对于对象数组这样的变量,选中复制粘贴之后,不是想要的效果。如果想复制对象数组这样的变量值,使用copy(变量名),然后粘贴即可。

1
copy(变量名)

控制台复制复杂变量.png (564×512) (raw.githubusercontent.com)

兼容各个浏览器的事件监听代码

Chrome的插件扩展程序安装目录是什么?在哪个文件夹?

浏览器调试工具如何查看placeholder值

打包备份/转移安装微软Edge和谷歌Chrome浏览器的扩展程序/插件【手把手保姆级教程】