平时在项目开发过程中会用到一些知识点,自己觉得有些用,便整理下来供以后自己去回顾。
- 1、混入(mixins)
- 2、Vue.nextTick()
- 3、Vue.set( target, key, value )
- 4、Vue.extend()
- 5、delimiters
- 6、BEM设计模式
- 7、组件间通信的几种方式
- 8、立即触发watch的方法
1、混入(mixins)
混入 (mixins) 是一种分发 Vue 组件中可复用功能的非常灵活的方式。混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被混入该组件本身的选项。
例子:定义一个混入
var myMixin = {
data: function () {
return {
message: 'hello',
foo: 'abc'
}
},
created: function () {
this.hello()
},
methods: {
hello: function () {
console.log('hello from mixin!')
},
getName:function(name){
console.log("我在迷信中名字是:"+name);
},
getAge:function(age){
console.log("我今年"+age+"岁了")
}
}
}
//在vue中进行使用
var vm=new Vue({
mixins: [myMixin],
data: function () {
return {
message: 'goodbye',
bar: 'def'
}
},
created: function () {
console.log("created:"+JSON.stringify(this.$data))
},
methods:{
getName:function(name){
console.log("我在vue中的名字为:"+name);
}
}
})
复制代码
同名钩子函数将混合为一个数组,因此都将被调用。另外,混合对象的钩子将在组件自身钩子之前调用。因而在钩子函数created()中的输出为:
'created:hello from mixin!' 第一行;
'created:{ "message": "goodbye", "foo": "abc", "bar": "def" }' 第二行;
复制代码
在值为对象的这些Vue属性中,例如 methods, components 和 directives,将被混合为同一个对象。当mixin对象和Vue实例两个对象中键名冲突时,取Vue实例对象的键值对。 因此在调用methods中的方法时。会将Vue实例中没有的,mixin中有的添加到Vue实例中去。
vm.getName("黎明");//我在vue中的名字为:黎明。
vm.getAge(20);//我今年20岁了。
复制代码
mixin有点跟jQuery中的$.extend()和es6的object.assign()方法在功能上有些相似。
2、Vue.nextTick()
在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。
在项目开发过程中遇到dom元素被隐藏或显示等都没元素状态发生改变时,最好是使用nextTick()方法,不然可能不能正常获取dom元素的属性信息。
new Vue({
el: '.app',
data: {
msg: 'Hello Vue.',
isShow:false
},
methods: {
changeState() {
this.isShow = !this.isShow;
this.$nextTick(() => {
//this.isShow改变后,导致dom树被更新后要执行的代码
})
}
}
})
复制代码
3、Vue.set( target, key, value )
target:要更改的数据源(可以是对象或者数组)
key:要更改的具体数据
value :重新赋的值
向响应式对象中添加一个属性,并确保这个新属性同样是响应式的,且触发视图更新。它必须用于向响应式对象上添加新属性,因为 Vue 无法探测普通的新增属性 。
比如 this.myObject.newProperty = 'hi'
复制代码
例子如下:
<div id="app">
<input v-model="arr[0].name" />
<ul>
<li v-for="(item,index) in arr" :key="index">
{{index}}——{{item.name}}
</li>
</ul>
<button @click="changeArr">使用传统js方法修改数组</button>
<button@click="changeArrBySet">使用Vue.set方法修改数组</button>
</div>
<script type="text/javascript">
window.onload=function(){
new Vue({
el:"#app",
data:{
arr:[{name:"张三",age:20},{name:"李四",age:26},{name:"王五",age:20}]
},
methods:{
changeArr(){
this.arr[0]={name:"张大",age:40};
console.log("使用传统js方法修改数组");
},
changeArrBySet(){
this.$set(this.arr,0,{name:"张大",age:40});
console.log("使用传统js方法修改数组");
}
}
})
}
</script>
复制代码
点击事件操作结果如下所示:
从上面的输出结果我们可以看出,我们调用使用this.arr[0]={name:"张大",age:40};来修改数据元素时并没有改变视图中的元素。 而我们通过使用this.$set(this.arr,0,{name:"张大",age:40});能够实时修改视图元素。总结:通过数组的变异方法(Vue数组变异方法)我们可以动态控制数据的增减,但是我们却无法做到对某一条数据的修改,修改数据我们可以使用Vue.set()方法。
4、Vue.extend()
使用基础 Vue 构造器,创建一个“子类”。参数是一个包含组件选项的对象。data 选项是特例,需要注意 - 在 Vue.extend() 中它必须是函数。
这里就我个人理解其实就是在定义组件,支持我们在框架中是直接定义.vue文件。使用这种情况比较多的是在页面中单独引入vue.js文件,然后在页面中定义组件用的。在框架中开发中这种全局方法用的比较少。
例子:
<div id="app">
<todo :todo-data="dataList"></todo>
</div>
// 构建一个子组件
var todoItem = Vue.extend({
template: ` <li> {{ text }} </li> `,
props: {
text: {
type: String,
default: ''
}
}
})
// 构建一个父组件
var todoWarp = Vue.extend({
template: `
<ul>
<todo-item
v-for="(item, index) in todoData"
v-text="item.text"
></todo-item>
</ul>
`,
props: {
todoData: {
type: Array,
default: []
}
},
// 局部注册子组件
components: {
todoItem: todoItem
}
})
// 注册到全局
Vue.component('todo', todoWarp);
new Vue({
el: '#app',
data: {
dataList: [
{ id: 0, text: '蔬菜' },
{ id: 1, text: '奶酪' },
{ id: 2, text: '随便其它什么人吃的东西' }
]
}})
复制代码
通过Vue.extend()方法构造的组件必须通过 Vue.component('todo', todoWarp)注册到全局,才可以在页面中使用该组件。也可以在组件构造器中 components: { todoItem: todoItem }来将通过Vue.extend()构造的组件进行局部注册,作为其他组件的子组件。
Vue.extend()返回的是一个构造函数,因此还可以这样使用。
<div id="mount-point"></div>
// 创建构造器
var Profile = Vue.extend({
template: '<p>{{firstName}} {{lastName}} aka {{alias}}</p>',
data: function () {
return {
firstName: 'Walter',
lastName: 'White',
alias: 'Heisenberg'
}
}
})
// 创建 Profile 实例,并挂载到一个元素上。
new Profile().$mount('#mount-point')
<div id="mount-point"></div>将会被渲染成<p>Walter White aka Heisenberg</p>
复制代码
5、delimiters
delimiters的作用是改变我们插值的符号。Vue默认的插值是双大括号{{}}。但有时我们会有需求更改这个插值的形式。
delimiters:['${','}']
复制代码
现在我们的插值形式就变成了${}。代替了{{ }}。
6、BEM设计模式
BEM是(Block Element Modifier)的简称,翻译为块级元素修饰符。是由Yandex团队提出的一种前端命名方法论。这种巧妙的命名方法让你的CSS类对其他开发者来说更加透明而且更有意义。BEM命名约定更加严格,而且包含更多的信息,它们用于一个团队开发一个耗时的大项目。
B: 表示块,可以抽象成一个组件
E: 表示元素,组件下的一个元素,多个元素形成一个组件
M:表示修饰符,可以用来表示元素的状态,比如激活状态,颜色,大小
__主要用来表示块(B)和元素(E)间的连接。
--用来表示块或者元素与状态的连接。
常见样式设置格式
.button{} // 块
.button__text{} //元素
.button--primary{}//修饰符
假如有如下代码,其class名称如下所示
<div class="button button--primary">
<span class="button__text">蓝色按钮</span>
</div>
<div class="button button--success">
<span class="button__text">绿色按钮</span>
</div>
<div class="button button--warning">
<span class="button__text">红色按钮</span>
</div>
复制代码
7、组价间通信的几种方式
1、props
这是父子间组件通信的常见方式,一般用于父组件向子组件传递数据,并且是响应式的。一般情况下子组件不会去直接改变从父组件同过prop传过来的数据,一般会在子组件data中定义一个变量来进行接收:
注意:这种通信方式是响应式的,一般情况下是用于单项通信的(父向子传递数据),但是如果在通过prop特性传的是一个引用类型的数据(如Object和Array)时,在子组件修改该引用类型的数据时,也会改变父组件中该prop的值。
props:{
name:{
type:String,
dafault:""
},
age:{
type:Number,
dafault:0
}
}
data(){
return{
perName=this.name
}
}
复制代码
2、 $emit和$on
这种通信方式主要是解决子组件向父组件传递数据的问题。 //子组件中
<button @click="send"></button>
...
methods:{
send(){
this.$emit("sendMsg","我是子组件的数据")
}
}
//父组件中
...
created(){
this.$on("sendMsg",data=>{
console.log(data);//"我是子组件的数据"
})
}
复制代码
3、vuex
这种通信方式属于全局通信方式,一般vuex用在中大型项目中。 主要是有以下几个核心概念:1、state: 用于保存整个项目中用到的全局变量,是响应式的。与之对应的是mapState函数(当一个组件需要获取多个状态时候,将这些状态都声明为计算属性会有些重复和冗余。为了解决这个问题,我们可以使用 mapState 辅助函数帮助我们生成计算属性)具体的用法可以参考官方文档。 (Vuex)[vuex.vuejs.org/zh/guide/st…]
2、getters: 可以认为是 store 的计算属性,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。 mapGetters: mapGetters 辅助函数仅仅是将 store 中的 getter 映射到局部计算属性:
3、Mutation: 更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数。
注意: 1、Mutation 必须是同步函数;2、使用常量替代 Mutation 事件类型;3、Mutation 需遵守 Vue 的响应规则。
mapMutations 辅助函数将组件中的 methods 映射为 store.commit 调用(需要在根节点注入 store)。
4、Action: Action 提交的是 mutation,而不是直接变更状态。 Action 可以包含任意异步操作。Action 通过 store.dispatch 方法触发。 在组件中分发 Action:this.$store.dispatch('xxx') 分发 action,或者使用 mapActions 辅助函数将组件的 methods 映射为 store.dispatch 调用(需要先在根节点注入 store)。
5、Module Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割。
4、$attrs和$listeners
attrs: 包含了父作用域中不被 prop 所识别 (且获取) 的特性绑定 (class 和 style 除外)。当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定 (class 和 style 除外),并且可以通过 v-bind="$attrs" 传入内部组件。通常配合 inheritAttrs 选项一起使用。 inheritAttrs为true时,表示在该组件上显示哪些非prop属性,为false则不显示。
listeners: 包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on="$listeners" 传入内部组件。
5、provide和inject
provide 选项应该是一个对象或返回一个对象的函数。该对象包含可注入其子孙的属性。 子孙组件通过inject注入获取到祖级和父级provide的数据。
注意:provide 和 inject 绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的属性还是可响应的。
provide与inject 实现数据响应式的两种方式:
1、provide祖先组件的实例,然后在子孙组件中注入依赖,这样就可以在子孙组件中直接修改祖先组件的实例的属性,不过这种方法有个缺点就是这个实例上挂载很多没有必要的东西比如props,methods 2、使用2.6最新API Vue.observable 优化响应式 provide(推荐)
6、$parent / $children与 ref
ref:如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例。
parent / children:访问父 / 子实例
这两种都是直接得到组件实例,使用后可以直接调用组件的方法或访问数据。这两种方法的弊端是,无法在跨级或兄弟间通信。
7、eventBus
这种通信方式可以跨组件通讯,经常用于兄弟组件间通讯。这种通讯方式的实现是通过新建一个vue实例,然后在需要通信的组件间引入,通过emit方法触发事件,通过on来监听相应事件来实现通讯的功能。更详细的请参考大神的介绍——(vue组件间通信六种方式)juejin.im/post/5cde0b…
8、立即触发watch的方法
watch:{
"type":function(){
handler(){
//注意这里不要使用箭头函数,否则取不到vue实例
console.log(this.msg);
},
immediate:true
}
}
复制代码