Vue2中的一些小知识点

Vue2文件结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
├── node_modules
├── public
├── favicon.ico:页签图标
└── index.html:主页面
├── src
├── assets:存放静态资源
└── logo.png
├── component:存放组件
└── HelloWorld.vue
├── App.vue:汇总所有组件
└── main.js:入口文件
├── .gitignore:git版本管制忽略的配置
├── babel.config.js:babel的配置文件
├── package.json:应用包配置文件
├── REMDME.md:应用描述文件
└── package-lock.json:包版本控制文件

1.render函数

在Vue.js中, render 函数主要有以下作用:

  1. 编程式创建虚拟DOM - 相比模板语法,render函数给予开发者完全的JavaScript编程能力
  2. 更灵活的动态渲染 - 特别适合需要根据运行时条件动态生成大量内容的场景
  3. 模板编译替代方案 - 当不使用.vue单文件组件时,可直接用render函数替代模板编译

适用场景:

  • 需要根据动态参数创建复杂组件结构时
  • 需要实现高级抽象组件时
  • 需要直接操作虚拟DOM时
  • 需要配合JSX语法开发时
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
// 以下两种写法等效
<script>
import HelloWorld from './components/HelloWorld.vue'

export default {
name: 'App',
components: {
HelloWorld
},
render(h) {
return h('div', { attrs: { id: 'app' } }, [
h('img', { attrs: { alt: 'Vue logo', src: require('./assets/logo.png') } }),
h(HelloWorld, { props: { msg: 'Welcome to Your Vue.js App' } })
])
}
}
</script>

<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
/***************************************************************/
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png">
<HelloWorld msg="Welcome to Your Vue.js App"/>
</div>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue'

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

<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>

2.ref 属性

  1. 被用来给元素或子组件注册引用信息(id的替代者)

  2. 应用在html标签上获取的是真实DOM元素,应用在组件标签上是组件实例对象(vc)

  3. 使用方式:

​ 打标识:<h1 ref="xxx">......</h1> <School ref="xxx"></School>

  获取:this.$refs.xxx

​ 获取到的值:<h1 ref="xxx">......</h1>获取到的是元素标签,<School ref="xxx"></School>获取倒票的是子组件实例对象 VueComponent

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
<template>
<div>
<h1 ref="component">{{ msg }}</h1>
<Student ref="stu"></Student>
<School ref="sch"></School>
<button @click="showDOM">点我输出上方DOM元素</button>
</div>
</template>

<script>
//导入组件
import Student from "./components/Student"
import School from "./components/School"

export default {
name: "App",
//汇总所有的组件
components: {
School
,Student
},
data() {
return {
msg: "Hello Vue!",
};
},
methods: {
showDOM() {
console.log("h1 msg",this.$refs.component)
console.log("sch",this.$refs.sch)
console.log("stu",this.$refs.stu)
}
}
}

</script>

image-20250317210816332

3.配置 props

功能:让组件接收外部传过来的数据

  1. 传递数据

<Demo name="xxx"/>

  1. 接收数据:

​ 第一种方式(只接收)

props:['name']

​ 第二种方式(限制类型):

props:{

name:Number

}

​ 第三种方式(限制类型、限制必要性、指定默认值):

props:{

name:{

type:String, //类型

required:true, //必要性

default:'老王' //默认值

}

}

备注:props是只读的,Vue底层会检测你对props的修改,如果进行了修改,就会发出警告,若业务需求确实需要修改,那么请赋值props的内容到data中一份,然后去修改data中的数据。

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
<template>
<div>
<Student :name="studentName" :gender="studentGender" :age="studentAge"/>
<hr>
<Student ref="fillStudentDataFromRef" />
<hr>
<Student name="学生" gender="男" :age="19"/>
<hr>
</div>
</template>

<script>
//导入组件
import Student from "./components/StudentProps"

export default {
name: "App",
//汇总所有的组件
components: {
Student
},
data() {
return {
studentName: '',
studentGender: '',
studentAge: 0
};
},
created() {
// 填充数据
this.fillStudentData()
},
mounted() {
this.fillStudentDataFromRef()
},
methods: {
fillStudentData() {
// 随机生成学生信息 建议
this.studentName = '学生' + Math.floor(Math.random() * 100)
this.studentGender = Math.random() < 0.5 ? '男' : '女'
this.studentAge = 19
},
fillStudentDataFromRef() {
// 填充数据 不建议
// Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders.
// Instead, use a data or computed property based on the prop's value.
this.$refs.fillStudentDataFromRef.setStudentData({
name: '学生' + Math.floor(Math.random() * 100),
gender: Math.random() < 0.5 ? '男' : '女',
age: 19
})

}
}
}

</script>
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>
<h1>{{ msg }}</h1>
<h2>学生姓名: {{ name }}</h2>
<h2>学生性别: {{ gender }}</h2>
<h2>学生年龄: {{ age + 1 }}</h2>
</div>
</template>


<script>
//组件交互的代码
//export default school分别暴露
export default {
name: 'Student', //开发者工具最终呈现的名字为School
data() {
return {
msg: '学生信息',

}
},
// props:['name','gender','age'],
props: {
name: {
type: String,
required: true,
validator: (value) => value.length >= 2 // 添加姓名长度验证
},
gender: {
type: String,
required: true,
validator: (value) => ['男', '女'].includes(value) // 性别枚举验证
},
age: {
type: Number,
required: true,
validator: (value) => value > 0 && value < 150 // 年龄范围验证
}
},
methods: {
setStudentData(data) {
// 通过方法接收父组件数据
if (typeof data === 'object') {
this.name = data.name
this.gender = data.gender
this.age = data.age
}
}
}
};
</script>

4. mixin(混入)

功能:可以把多个组件公用的配置提取成一个混入对象

使用方式:

第一步定义混合,例如:

1
2
3
4
5
{
data(){......},
methods:{......}
......
}

第二部使用混入 ,例如:

1
2
(1).全局混入:Vue.mixin(xxx)
(2).局部混入:mixins:['xxx']

注意:不同组件中的mixin是相互独立的!

4.1 局部混入

App.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<template>
<div>
<Student />
<hr>
<School />
</div>
</template>

<script>
//导入组件
import Student from "./components/Student"
import School from "./components/School"

export default {
name: "App",
//汇总所有的组件
components: {
Student,
School
}
}
</script>

Student.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<template>
<div @click="showInfo">
<h2>学生姓名:{{ name }}</h2>
<h2>学生年龄:{{ age }}</h2>
</div>
</template>


<script>

import { infoMixin } from "@/info_mixin";

export default {
name: 'Student',
data(){
return {
name:'panyue',
age:21
}
},
mixins:[infoMixin],
};
</script>

School.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
<template>
<div @click="showInfo" class="demo">
<h2>学校名称:{{ name }}</h2>
<h2>学校地址:{{ address }}</h2>
</div>
</template>

<style>
.demo{
background: skyblue;
}
</style>


<script>
import { infoMixin } from '@/info_mixin';
export default {
name: 'School',
data(){
return {
name:'武汉科技大学',
address: '武汉'
}
},
mixins: [infoMixin]
};
</script>

infomixin.js

1
2
3
4
5
6
7
export const infoMixin = {
methods: {
showInfo(){
alert(this.name);
}
}
}

image-20250318135203933

4.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
<template>
<div>
<Student />
<hr>
<School />
</div>
</template>

<script>
//导入组件
import Student from "./components/Student"
import School from "./components/School"

export default {
name: "App",
//汇总所有的组件
components: {
Student,
School
}
}
</script>

Student.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<template>
<div @click="showInfo">
<h2>学生姓名:{{ name }}</h2>
<h2>学生年龄:{{ age }}</h2>
</div>
</template>

<script>

export default {
name: 'Student',
data(){
return {
name:'panyue',
age:21
}
},
};
</script>

School.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
<template>
<div @click="showInfo" class="demo">
<h2>学校名称:{{ name }}</h2>
<h2>学校地址:{{ address }}</h2>
</div>
</template>

<style>
.demo{
background: skyblue;
}
</style>


<script>
export default {
name: 'School',
data(){
return {
name:'武汉科技大学',
address: '武汉'
}
},
};
</script>

infomixin.js

1
2
3
4
5
6
7
export const infoMixin = {
methods: {
showInfo(){
alert(this.name);
}
}
}

main.js

1
2
3
4
5
6
7
8
import Vue from 'vue'
import App from './App.vue'
import {infoMixin} from './info_mixin'
Vue.config.productionTip = false
Vue.mixin(infoMixin)
new Vue({
render: h => h(App),
}).$mount('#app')

image-20250318135203933

4. 3 mixin的优缺点

从上面的例子看来,使用mixin的好处多多,但是凡是都有两面性,这里总结几点优缺点供大家参考:

4.3.1 优点

  • 提高代码复用性
  • 无需传递状态
  • 维护方便,只需要修改一个地方即可

4.3.2 缺点

  • 命名冲突
  • 滥用的话后期很难维护
  • 不好追溯源,排查问题稍显麻烦
  • 不能轻易的重复代码

代码地址:https://github.com/Jacobshash/vue_test/tree/master/src_mixin

5.Scoped样式

作用:让样式在局部生效,防止冲突。

写法:<style scoped>

1
2
3
4
5
<style scoped>
.sscope{
background: orangered;
}
</style>

代码地址:https://github.com/Jacobshash/vue_test/tree/master/src_scoped

6.插件

功能:用于增强Vue

本质:包含install方法的一个对象,install的第一个参数是Vue,第二个以后的参数是插件使用者传递的数据。

定义插件:

 `export const myPlugins = {`

      `install(Vue,a,b) {`

       `}`

}

使用插件:Vue.use(myPlugins )

6.1 定义并使用插件

my_plugins.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
import { infoMixin } from './info_mixin.js'

export const myPlugins = {
install(Vue,a,b) {

Vue.filter('mySlice', function (value) {
return value.slice(0, 4);
})

Vue.directive('fbind', {
bind(element, binding) {
element.value = binding.value;
},
inserted(element) {
element.focus();
},
update(element, binding) {
element.value = binding.value;
}
})

Vue.mixin(infoMixin)

Vue.prototype.myPlugins = function (x, y) {
alert('myPlugins'+ x+ y+a+b);
}
}
}

main.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import Vue from 'vue'
import App from './App.vue'

import { myPlugins } from './my_plugins'

Vue.config.productionTip = false

Vue.use(myPlugins,"a","b")

// Vue.mixin(infoMixin)

new Vue({
render: h => h(App),
}).$mount('#app')

代码地址:https://github.com/Jacobshash/vue_test/tree/master/src_plugin

7.插槽

8.自定义指令

9.路由管理

10.状态管理