Mixin/Vuex;v-model/.sync的区别;拆store配getter;组件调action;页面转传值;组件传值;$nextTick;$set;vue.use;v2响应式缺陷proxy优点

Mixin和Vuex

  • Vuex公共状态管理,如果在一个组件中更改了Vuex中的某个数据,那么其它所有引用了Vuex中该数据的组件也会跟着变化。
  • Mixin中的数据和方法都是独立的,组件之间使用后是互相不影响的。

1、定义一个混入(mixin)

在我们的项目src目录下新建mixin文件夹,然后新建index.js文件,该文件存放我们的mixin代码。

// src/mixin/index.js
export const mixins = {
  data() { return {}; },
  computed: {},
  created() {},
  mounted() {},
  methods: {},
};

2、在组件中使用

import myMixins from "../mixins";   //导入混入(mixin)
mixins: [myMixins]     //使用混入(mixin)

v-model和.sync的区别

v-mode

是Vue.js提供的一个语法糖指令,用于在表单元素上实现双向数据绑定。它会自动监听输入框、下拉框、单选框等表单元素的值变化,并将其更新到Vue实例的数据中,同时,当Vue实例数据发生改变时,也会将新的值反映到表单元素上。它的语法如下:

<input v-model="message">

.sync修饰符

<!-- 父组件 -->
<template>
  <child-component :message.sync="message"></child-component>
</template>
<script>
export default {
  data() {
    return {
      message: ''
    }
  },
  methods: {
    updateMessage(newValue) {
      this.message = newValue;
    }
  },
  components: {
    ChildComponent
  }
}
</script>
<!-- 子组件 -->
<template>
  <input :value="message" @input="$emit('update:message', $event.target.value)">
</template>

父组件向子组件传递了一个message属性,并使用.sync修饰符,这样父组件会自动监听子组件触发的update:message事件,并在触发时更新父组件中的message属性。

合理拆分store并配置全局getter

示例:

正常访问方式如下:
 this.$store.state.user.userInfo.skill.info.age    // 18
使用全局getters优化
export defaut{ age: state => state.user.userInfo.skill.info.age -> 18 }
// 使用全局getters快捷访问方式,如下:
this.$store.gettes.age -> 18

组件中调用action发请求的流程

Mixin/Vuex;v-model/.sync的区别;拆store配getter;组件调action;页面转传值;组件传值;$nextTick;$set;vue.use;v2响应式缺陷proxy优点_第1张图片

页面跳转传值的方式-query¶ms

声明式导航的两种方式:

(1)query

to=“/path?参数名=值&参数名2=值” 接收传值:$route.query.参数名

(2)params

路由的路径中 routes: [ …,{ path: ‘/search/:words?’, component: Search } ] }) 接收传值:$route.params.参数名

声明式导航的两种方式:

(1)query

this.$router.push('/路径?参数名1=值&参数2=值')
/this.$router.push({  path: '/路径',query:{ 参数名1: '值',参数名2: '值' } })

/this.$router.push({ name: '路由名字',query: {参数名1: '值',参数名2: '值' }  })   //name跳转

接收传值:**$route.query.参数名**

(2)params

this.$router.push('/路径/参数值')
/this.$router.push({  path: '/路径/参数值'  })

/this.$router.push({name: '路由名字',params: {  参数名: '参数值',  }  })

接收传值:**$route.params.参数名**

组件之间传值的方式

(1)父传子

//父组件
<template>
  <div>
++    <son :data='name'></son> 
  </div>
</template>
<script>
++ import son from "./son.vue";//导入子组件
export default {
++  components: { son },//注册组件
  name: "父组件",
  data() {
    return {
      name: "Frazier", //父组件定义变量
    };
  },
};
</script>
//子组件
<template>
  <div>{{data}}</div>
</template>
<script>
export default {
components: { },
  name: '子组件',
++  props:["data"],
};
</script>

(2)子传父

//子组件
<template>
  <div>
    <button @click="lcalter">点我</button>
  </div>
</template>
<script>
export default {
...
  methods: {
    lcalter(){
++      this.$emit('lcclick')//通过emit来触发事件
    }
  },
};
</script>
//父组件
<template>
  <div>
++    <son @lcclick="lcclick"></son>//自定义一个事件
  </div>
</template>
 
<script>
...
  methods: {
    lcclick(){
      alert('子传父')
    }
  },
};
</script>

(3)兄弟组件通信(bus总线)

(1)在src中新建一个Bus.js的文件,然后导出一个空的vue实例
(2)在传输数据的一方引入Bus.js 然后通过Bus.e m i t ( “ 事 件 名 ” , " 参 数 " ) 来 来 派 发 事 件 , 数 据 是 以 emit(“事件名”,“参数”)来来派发事件,数据是以emit(“事件名”,“参数”)来来派发事件,数据是以emit()的参 数形式来传递
(3)在接受的数据的一方 引入 Bus.js 然后通过 Bus.$on(“事件名”,(data)=>{data是接受的数据})
1、新建bus.js,并引用

/**bus.js**/
import Vue from 'vue'
const bus = new Vue()
export default bus

2、在A组件页面里

<template>
      <div class="components-a">
           <button @click="abtn">A按钮</button>
      </div>
</template>
<script>
++import bus from '@/assets/bus.js';
export default {
      data () {
        return {
                ‘msg':"我是组件A"
        }
      },
      methods:{
           abtn(){
++                   eventVue.$emit("myFun",this.msg)   //$emit这个方法会触发一个事件
           }
      }
}
</script>

3.在B组件:

<template>
     <div class="components-a">
         <div>{{btext}}</div>
     </div>
</template>
<script>
++import bus from '@/assets/bus.js';
export default {
   name: 'app',
   data () {
        return {
           'btext':"我是B组件内容"
        }
   },
   created(){
       this.bbtn();
   },
   methods:{
       bbtn(){
++            eventVue.$on("myFun",(message)=>{   //这里最好用箭头函数,不然this指向有问题
++                 this.btext = message      
            })
       }
    }
}
</script>

(4)ref/refs(父子组件通信)

父组件通过ref/refs调用子组件方法

//父组件
<template>
  <div>
    <button @click="sayHello">sayHello</button>
    <child ref="childForRef"></child>    //子组件
  </div>
</template>
<script>
import child from './child.vue'  //引入子组件
  export default {
    components: { child },  //注册子组件
...
    methods: {
      sayHello() {
++        this.$refs.childForRef.sayHello()     //调用子组件方法
      }
    }
  }
</script>
//子组件
<template>
  <div>child 的内容</div>
</template>
<script>
export default {
...
  methods: {
++    sayHello () {
      console.log('hello');
    }
  }
}
</script>

(5)全局变量

定义一个全局变量,在有值的组件直接赋值,在需要的组件内直接使用就可以了

在main里面注册组件

//全局组件
import MyList from './components/MyList.vue'
Vue.component(MyList.name,MyList)

在要引入的组件写上 name: “LoginName”,

<LoginName ref="login"></LoginName>

全局变量第二种方法:

在Vue实例之外定义一个全局变量,例如在main.js或单独的一个文件中:

// main.js 或单独的一个文件,例如 globals.js

// 定义全局变量
Vue.prototype.$myGlobalVariable = '这是一个全局变量';

在需要使用该全局变量的组件中,可以直接引用并使用它:

<template>
  <div>
    <!-- 直接使用全局变量 -->
    <p>{{ $myGlobalVariable }}</p>
  </div>
</template>

<script>
export default {
  name: 'MyComponent',
  mounted() {
    // 可以在组件内部直接使用全局变量
    console.log(this.$myGlobalVariable);
  }
}
</script>

(6)promise传参

promise 中 resolve 如何传递多个参数

//类似与这样使用,但实际上后面两个参数无法获取
promise = new Promise((resolve,reject)=>{
    let a = 1
    let b = 2
    let c = 3
    resolve(a,b,c) 
})
promise.then((a,b,c)=>{
    console.log(a,b,c)
})

resolve() 只能接受并处理一个参数,多余的参数会被忽略掉。
如果想多个用数组,或者对象方式。

数组

promise = new Promise((resolve,reject)=>{
    resolve([1,2,3]) 
})
promise.then((arr)=>{
    console.log(arr[0],arr[1],arr[2])
})

对象

promise = new Promise((resolve,reject)=>{
    resolve({a:1,b:2,c:3}) 
})
promise.then(obj=>{
    console.log(obj.a,obj.b,obj.c)
})

(7)$parent

// 获父组件的数据
this.$parent.foo
// 写入父组件的数据
this.$parent.foo = 2
// 访问父组件的计算属性
this.$parent.bar 
// 调用父组件的方法
this.$parent.baz()
//在子组件传给父组件例子中,可以使用this.$parent.getNum(100)传值给父组件。

(8)Vuex通信

组件通过 dispatch 到 actions,actions 是异步操作,再 actions中通过 commit 到 mutations,mutations 再通过逻辑操作改变 state,从而同步到组件,更新其数据状态

$nextTick

用于在下一次DOM更新循环结束后执行回调函数。

1.在created中进行dom操作

使用原因 : created()执行的时候DOM还未进行任何渲染。

<template>
  <div class="hello">
    <button ref="text">{{ msg }}</button>
  </div>
</template>
<script>
export default {
  name: 'HelloWorld',
  data() {
    return {
      msg: '我是按钮的文字',
    }
  },
  created() {
  	console.log(this.$refs.text.innerHTML) 
    that.$nextTick(function () {
      console.log(this.$refs.text.innerHTML) //我是按钮的文字
    })
  },
}
</script>

2.重置组件的操作

<template>
  <div>
    <my-tick v-if="show" />
    <button @click="reset">重置</button>
  </div>
</template>

<script>
import MyTick from './components/MyTick.vue'
export default {
  components: { MyTick },
  data() {
    return {
      show: true,
    }
  },
  methods: {
    reset() {
      // 刷新: 先移除 再添加
      // vue的设计: 方法执行到结尾, 把最终的效果更新DOM, 所以false没执行
      // 原生DOM: 每行代码的执行都会刷新DOM
      this.show = false
      // 在本次渲染完毕后, 立刻执行下一个任务:  nextTick
      this.$nextTick(() => (this.show = true))
      //$nextTick: 在本次渲染结束后的下一次渲染中, 例如执行 true 的操作
    },
  },
}
</script>

3.获取更新后的DOM元素的尺寸或位置

mounted() {
  this.$nextTick(() => {
    // 这里可以执行DOM相关的操作,例如获取更新后的DOM元素
    const element = document.getElementById('my-element');
    const elementWidth = element.offsetWidth;
  });
}

4.异步更新后的回调,例:在数据获取、API调用等完成后进行一些更新数据、操作DOM等的操作

methods: {
  fetchData() {
    // 异步获取数据
    fetchDataAsync().then((data) => {
      // 更新数据
      this.data = data;
      // 在DOM更新后执行回调函数
      this.$nextTick(() => {
        // 这里可以执行一些操作,例如处理数据、更新DOM等
        this.processData();
      });
    });
  },
  processData() {
    // 处理数据
    // ...
  }
}

5.页面刷新之后,input框获取焦点

6.组件之间的通信

父组件修改了传递给子组件的props,并希望在子组件中立即响应这些变化时,可以使用$nextTick来确保在DOM更新后再进行操作

<template>
  <div>
    <button @click="changeValue">Change Value</button>
    <child-component :value="propValue" @value-updated="handleValueUpdated"></child-component>
  </div>
</template>

<script>
export default {
  data() {
    return {
      propValue: 'Initial Value'
    };
  },
  methods: {
    changeValue() {
      this.propValue = 'New Value';

      this.$nextTick(() => {
        console.log('DOM Updated');
      });
    },
    handleValueUpdated(newValue) {
      console.log('Child Value Updated:', newValue);
    }
  }
};
</script>
<template>
  <div>
    <p>Value: {{ value }}</p>
  </div>
</template>

<script>
export default {
  props: ['value'],
  watch: {
    value(newValue) {
      this.$emit('value-updated', newValue);
    }
  }
};
</script>

$set的应用场景

由于javaScript的限制,vue不能检测除了push,pop,shift等等以外的数组变化

数组:

this.$set(Array, index, newValue)

对象:

this.$set(Object, key, value)

使用vue.use对自定义组件|指令进行快速注册

// 导入所需的自定义组件和指令
import MyComponent from './components/MyComponent.vue';
import MyDirective from './directives/MyDirective';

// 在Vue.use中注册组件和指令
Vue.use({
  install(Vue) {
    // 注册自定义组件
    Vue.component('my-component', MyComponent);

    // 注册自定义指令
    Vue.directive('my-directive', MyDirective);
  },
});

v2响应式的缺陷及对应proxy的优点

在Vue 2中,响应式系统的缺陷主要有以下几个问题:

  1. 对象新增属性或删除属性无法响应:Vue 2只能在初始化实例时对属性进行响应式处理,后续新增的属性或删除的属性无法实时触发更新。
  2. 数组索引和length的响应性问题:Vue 2无法检测到直接通过索引或修改length的方式进行的数组变动,需要使用特定的变异方法(如push、pop等)才能响应变化。
  3. **深层属性的监听问题:**Vue 2默认只能响应对象的一层属性变化,无法递归地监听嵌套对象的属性变化。

下面是使用Proxy实现响应式的优点的示例代码:

// 创建响应式对象
function reactive(obj) {
  return new Proxy(obj, {
    get(target, key) {
      // 返回属性值
      return Reflect.get(target, key);
    },
    set(target, key, value) {
      // 更新属性值
      Reflect.set(target, key, value);
      // 执行触发更新的操作
      // ...
    },
    deleteProperty(target, key) {
      // 删除属性
      Reflect.deleteProperty(target, key);
      // 执行触发更新的操作
      // ...
    }
  });
}

// 创建响应式对象
const obj = reactive({ count: 0 });

console.log(obj.count); // 输出: 0

// 更新属性值
obj.count = 1;

console.log(obj.count); // 输出: 1

// 删除属性
delete obj.count;

console.log(obj.count); // 输出: undefined
// 创建响应式对象
function reactive(obj) {
  return new Proxy(obj, {
    get(target, key) {
      // 返回属性值
      return Reflect.get(target, key);
    },
    set(target, key, value) {
      // 更新属性值
      Reflect.set(target, key, value);
      // 执行触发更新的操作
      // ...
    },
    deleteProperty(target, key) {
      // 删除属性
      Reflect.deleteProperty(target, key);
      // 执行触发更新的操作
      // ...
    }
  });
}

// 创建响应式对象
const obj = reactive({ count: 0 });

console.log(obj.count); // 输出: 0

// 更新属性值
obj.count = 1;

console.log(obj.count); // 输出: 1

// 删除属性
delete obj.count;

console.log(obj.count); // 输出: undefined

你可能感兴趣的:(vue.js,前端)