一、vue数据响应式原理和双向绑定原理
1). 双向数据绑定是建立在单向数据绑定(model==>View)的基础之上的
2). 双向数据绑定的实现流程:
a. 在解析v-model指令时, 给当前元素添加input监听
b. 当input的value发生改变时, 将最新的值赋值给当前表达式所对应的data属性
二、vue自定义指令(私有,全局)
1.私有自定义指令
自定义指令需要在directives节点下创建私有自定义指令,创建好的指令通过v-指令名放到元素中
2.定义全局自定义属性
全局自定义指令要在main.js下定义,使用Vue.directive() 函数。
详解:
1.什么是自定义事件
vue 官方提供了 v-text,v-for,v-model,v-if 等常用指令。除此之外 vue 还允许开发者自定义指令。
- 私有自定义指令
- 全局自定义指令
(1)私有自定义指令
自定义指令需要在directives节点下创建私有自定义指令,创建好的指令通过v-指令名放到元素中
<template>
<div id="App">
<p v-color>这个文字编程红色</p>
</div>
</template>
<script>
export default {
data() {
return {
}
},
//自定义指令的节点
directives:{
//创建一个color指令,执行配置对象。
color:{
//当指令帮到元素上的时候,聚会出发bind函数
//el参数标识当前绑定的dom对象
bind(el){
el.style.color="red"
}
}
}
}
</script>
上述中,如果给元素添加颜色,只能绑定唯一的值,不能自己设定颜色,
在vue中,可以通过hinding.value获取属性绑定的颜色值。
<template>
<div id="App">
<p v-color='red'>通过属性值绑定的颜色变颜色</p>
<p v-color="'blue'">自己在v-color中自己设置颜色,需要通过字符串形式传入</p>
</div>
</template>
<script>
export default {
data() {
return {
color:'red'
}
},
directives:{
color:{
bind(el,binding){
el.style.color=binding.value
}
}
}
}
</script>
update 函数
bind
函数只调用一次:当指令第一次绑定到元素时调用update
函数会在每次 DOM 更新时被调用update
函数在指令绑定的时候不会被调用!
<template>
<div id="App">
<p v-color='red'>通过属性值绑定的颜色变颜色</p>
<p v-color="'blue'">自己在v-color中自己设置颜色,需要通过字符串形式传入</p>
<button @click="color='blue'">点击变换颜色</button>
</div>
</template>
<script>
export default {
data() {
return {
color:'red'
}
},
directives:{
color:{
//只能被触发一次
bind(el,binding){
el.style.color=binding.value
},
//在每次dom更新的时候触发
update(el,binding){
el.style.color=binding.value
}
}
}
}
</script>
自定义指令的简写形式
简写形式可以包含bind和update两个函数,减少代码的重复,直接将指令变成函数。
<template>
<div id="App">
<p v-color='red'>通过属性值绑定的颜色变颜色</p>
<p v-color="'blue'">自己在v-color中自己设置颜色,需要通过字符串形式传入</p>
<button @click="color='blue'">点击变换颜色</button>
</div>
</template>
<script>
export default {
data() {
return {
color:'red'
}
},
directives:{
//将指令对象改写成指令函数
color(el,binding){
el.style.color=binding.value
}
}
}
</script>
(2)定义全局自定义属性
全局自定义指令要在main.js下定义,使用Vue.directive() 函数。
Vue.directive('color', {
bind(el, binding) {
el.style.color = binding.value
},
update(el, binding) {
el.style.color = binding.value
}
})
或者
这是借助ES6的箭头函数形式
Vue.directive('color', (el,binding)=>el.style.color=binding.value)
三、vue2和vue3区别,以及发生哪些变化
1.生命周期的变化
整体来看,变化不大,只是名字大部分需要 + on
,功能上类似。使用上 Vue3组合式 API 需引入;Vue2 选项 API 则可直接调用,如下所示。
// vue3
<script setup>
import { onMounted } from 'vue'
onMounted(() => {
...
})
// 可将不同的逻辑拆开成多个onMounted,依然按顺序执行,不被覆盖
onMounted(() => {
...
})
</script>
// vue2
<script>
export default {
mounted() {
...
},
}
</script>
常用生命周期表格如下所示。
Vue2.x | Vue3 |
---|---|
beforeCreate | setup( ) |
created | setup( ) |
beforeMount | onBeforeMount |
mounted | onMounted |
beforeUpdate | onBeforeUpdate |
updated | onUpdated |
beforeDestroy | onBeforeUnmount |
destroyed | onUnmounted |
2.多根节点 vue3支持碎片化(Fragment)
Vue3组件中有多个根节点
Vue2中,我们需要去将组件包裹在<div>
中,否则报错警告。
优点:减少标签层级,减少内存占用
<template>
<header>...</header>
<main>...</main>
<footer>...</footer>
</template>
3.vue2和vue3选用api不同(v2和v3最大的不同点)
vue2:采用选项式 API (Options API),
代码风格:date选项写数据,methods选项写函数,一个功能逻辑的代码分散
优点:易于学习和使用,写代码的位置已经约定好了
缺点:代码组织性差,相似的逻辑代码不便于复用,逻辑复杂代码多了不好阅读。
vue3:组合式 API (Composition API),
代码风格:一个功能逻辑的代码组织在一起(包括数据,函数、、、)
优点:功能逻辑复杂繁多情况下,各个功能逻辑代码组织再一起,便于阅读和维护
缺点:需要有良好的代码组织能力和拆分逻辑能力
vue3支持选项式api和组合式api
4.vue2和vue3定义数据变量和方法的改变
在vue2
中定义数据变量是data(){}
,创建的方法要在methods:{}
中。
而在vue3
中直接在setup(){}
中,使用该方法需要引入,在这里面定义的变量和方法因为最终要在模板中使用,所以最后都得 return
。
如:
<script lang="ts">
import { defineComponent, ref } from 'vue';
export default defineComponent({
name: 'App',
setup() {
//使用ref,说明这个数组就是全局在面板中可以使用了
const girls = ref(['美女1','美女2','美女3'])
const selectGirl = ref('2')
//设置一个函数
const selectGirlFun = (index: number) => {
//改变selectGirl的值要加value
//要得到值要加value ,这些都因为使用了ref函数
selectGirl.value = girls.value[index]
}
//在标签中使用的变量要使用return
//为什么要使用return,因为有的不需要在标签中使用的就不用return
return{
girls,
selectGirl,
selectGirlFun
}
},
});
</script>
5.父子传参方式不同
vue2:
父传子:props,
子传父:$emit
vue3:setup()函数特性,vue3还给我们提供了provide和inject,我们可以在父组件中通过provide暴露属性或方法,子组件通过inject接受,并且只要是父组件的后代,都可以通过inject接收到父组件暴露的值
6.vue2和vue3数据双向绑定原理发生改变
vue2:vue2的数据双向绑定原理使用的是es5的数据劫持object.defineProperty配合发布订阅模式来实现
优点:兼容性相对好
vue3:通过proxy的api(Reflect)实现
优点:可以直接监听对象而非属性,可以直接监听数组的变化, 有多达 13 种拦截方法,不限于 apply、ownKeys、deleteProperty、has 等等是Object.defineProperty 不具备的;
7.vue3在单个组件上创建多个v-model 绑定
8.v-if和v-for的优先级
vue2中v-for的优先级比v-if高,每次遍历都要v-if;
vue3中v-if 比v-for高,但尽量避免一起使用。
9.setup语法糖 <script setup>
- 引入组件的时候不需要注册组件
- 定义变量的时候不需要return出去,顶层的绑定会暴露给模板,模板中可以直接使用
- 使用
defineProps
、defineEmits
、defineExpose
等API,它们将自动地在<script setup>
中可用
<script lang="ts" setup>
import {ref} from "vue"
// 只需要引入需要的组件,不需要注册组件
import Test from "./components/Test.vue"
// 定义变量不需要return出去
const count = ref(0)
const Add = () =>{
count.value++
}
</script>
<template>
<div>
<Test></Test>
<h1>{
{count}}</h1>
<button @click="Add">Add</button>
</div>
</template>
<style scoped lang='less'>
</style>
四、computed的计算属性和watch监听的区别
computed :
1.支持缓存,只有依赖数据发生改变,才会重新进行计算
2.不支持异步,当computed内有异步操作时无效,无法监听数据的变化
3.computed变量不在data中定义,而是在computed对象中定义。(可以在data中没有定义,模板中直接使用方法名)
watch:
1.不支持缓存,只要监听的数据变化就会触发相应操作;
2.watch支持异步;
3.监听的函数接收两个参数,第一个参数是最新的值;第二个参数是输入之前的值;
4.watch的数据必须是data中声明过或父组件传递过来的props中的数据,当数据变化时,触发监听器
计算属性:
<div id="app"> {
{total}} </div>
<script>
var vm = new Vue({
el: '#app',
data: {
num: 10,
price: 8.8,
},
computed: {
total: function () {
return this.num * this.price
}
}
})
</script>
侦听器:
<div id="app"> {
{total}} </div>
<script>
var vm = new Vue({
el: '#app',
data: {
num: 10,
price: 8.8,
},
watch: {
num: function (val) {
this.total = val * this.price
},
price: function (val) {
this.total = this.num * val
}
}
})
</script>
五、谈一谈响应式数据
什么是响应式,也即是说,数据发生改变的时候,视图会重新渲染,匹配更新为最新的值。
使用 Object.defineProperty 可以为对象中的每一个属性,设置 get 和 set 方法。
- Vue 是怎么知道数据改变?
- Vue 在 属性的 set 方法中做了手脚,因而当数据改变时,触发属性的set 方法,Vue 就能知道数据有改变
- Vue 在数据改变时,怎么知道通知哪些视图更新?
- 通过Object.defineProperty-get,通知那些存在依赖收集器中的视图
- Vue 在数据改变时,视图怎么知道什么时候更新?
- 触发Object.defineProperty-set,在数据变化触发 set 函数时,通知视图,视图开始更新
六、keep alive的运行机制和实现原理
1.原理
在 created钩子函数调用时将需要缓存的 VNode 节点保存在 this.cache 中/在 render(页面渲染) 时,如果 VNode 的 name 符合缓存条件(可以用 include 以及 exclude 控制),则会从 this.cache 中取出之前缓存的 VNode实例进行渲染。
2. keep-alive是什么?
keep-alive
可以在组件切换时,保存其包裹的组件的状态,使其不被销毁,防止多次渲染。
其拥有两个独立的生命周期钩子函数 actived(在keep-alive 组件激活时调用) 和 deactived(在keep-alive 组件停用时调用),使用keep-alive
包裹的组件在切换时不会被销毁,而是缓存到内存中并执行 deactived 钩子函数,命中缓存渲染后会执行 actived 钩子函数。
应用场景:
用户在某个列表页面选择筛选条件过滤出一份数据列表,由列表页面进入数据详情页面,再返回该列表页面,我们希望:列表页面可以保留用户的筛选(或选中)状态。
3.用法
我们想要缓存某个组件,只要用<keep-alive>组件将其包裹就行。
常用的用法是包裹<component>组件缓存动态组件,或者包裹<router-view>缓存路由页面。
比如常在router.js路由表里定义好哪些页面需要缓存,就可以通过下面这样实现了:
{
path: "/index",
name: 'index',
component: () => import(/* webpackChunkName: "index" */ '@/pages/index'),
meta: {
title: '首页',
keepAlive: true
},
},
<keep-alive>
<router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive && isRouterAlive"></router-view>
<keep-alive>组件可以接收三个属性:
include - 字符串或正则表达式。只有名称匹配的组件会被缓存。
exclude - 字符串或正则表达式。任何名称匹配的组件都不会被缓存。
max - 数字。最多可以缓存多少组件实例。
include 和 exclude 属性允许组件有条件地缓存。二者都可以用逗号分隔字符串、正则表达式或一个数组来表示:
<!-- 逗号分隔字符串 -->
<keep-alive include="a,b">
<component :is="view"></component>
</keep-alive>
<!-- 正则表达式 (使用 `v-bind`) -->
<keep-alive :include="/a|b/">
<component :is="view"></component>
</keep-alive>
<!-- 数组 (使用 `v-bind`) -->
<keep-alive :include="['a', 'b']">
<component :is="view"></component>
</keep-alive>
注意:想要缓存的组件一定要给定name属性,并且要和include,exclude给定的值一致
七、登录token
1. 初次登录的时候,前端调后调的登录接口,发送用户名和密码;
2. 后端收到请求,验证用户名和密码,验证成功,就给前端返回一个 token,和一个用户信息的值;
3. 前端拿到 token,将 token 储存到 Vuex 中,然后从 Vuex 中把 token 的值存入浏览器 Cookies 中;
4. 把用户信息存到 Vuex 然后再存储到 LocalStroage 中,然后跳转到下一个页面;
5. 根据后端接口的要求,只要不登录就不能访问的页面需要在前端每次跳转页面师判断 Cookies 中是否有 token: 没有就跳转到登录页,有就跳转到相应的页面;
6. 我们应该在每次发送 post/get 请求的时候应该加入 token.
常用方法:
(1)在项目 utils/service.js 中添加全局拦截器,将 token 的值放入请求头中。
(2)后端判断请求头中有无 token。有 token,就拿到 token 并验证 token 是否过期,在这里过期会返回无效的 token 然后有个跳回登录页面重新登录并且清除本地用户的信息。
八、用户登录的权限是怎么操作的?
角色权限控制的整个流程中,前端整个流程步骤应是:
1. 首先展示无需登录的默认页面(比如404页面、登录页、注册页),
2. 然后在登录或浏览器刷新时调用后端接口拿到后端给的该账户的权限数据,然后将数据注入到系统中;
3. 整个系统拿到权限数据后就开始对页面的展现内容以及页面导航进行生成(使用addRouter添加路由),最终生成一个只展示当前用户所拥有对应权限的系统。从而达到整个角色权限的控制。
(1)菜单的控制
在登录请求中, 会得到权限数据, 当然, 这个需要后端返回数据的⽀持. 前端根据权限数据, 展示对应的菜单.点击菜单,才能查看相关的界⾯.
(2)界⾯的控制
如果⽤户没有登录,⼿动在地址栏敲⼊管理界⾯的地址, 则需要跳转到登录界⾯
如果⽤户已经登录, 可是⼿动敲⼊⾮权限内的地址, 则需要跳转404界⾯
(3)按钮的控制
在某个菜单的界⾯中, 还得根据权限数据, 展示出可进⾏操作的按钮, ⽐如删除,修改,增加
(4)请求和响应的控制
如果⽤户通过⾮常规操作, ⽐如通过浏览器调试⼯具将某些禁⽤的按钮变成启⽤状态, 此时发的请求, 也应该被前端所拦截
(5)⼩结
前端权限的实现必须要后端提供数据⽀持, 否则⽆法实现.
返回的权限数据的结构,前后端需要沟通协商, 怎样的数据使⽤起来才最⽅便.
九、购物车实现思路
第一步,进入购物车必须先登录;
第二步,利用axios请求数据,数据请求利用代理服务器,数据请求成功后,布局渲染页面,页面渲染完毕后开始写功能。
1.增加数量,减少数量
增加数量: css样式写一个步进器,给加的按钮绑定一个点击事件,获取v-for循环时的index下标,然后在方法中定义点击事件,获取到当前点击的这条数据中的数量,并对数量进行加加的处理。
减少数量:css样式写一个步进器,给加的按钮绑定一个点击事件,获取v-for循环时的index下标,然后在方法中定义点击事件,获取到当前点击的这条数据中的数量,并对数量进行减减的处理。 然后进行判断,判断数量不小于一,如果小于一,则让数量等于一。
2.删除
给删除按钮绑定一个点击事件,获取v-for循环时的index下标,然后在方法中定义点击事件,利用splice进行删除的处理,第一个值为index下标,第二个值为删除的数量。
3.总价的计算
循环所有的数据,利用reduce循环。它有两个参数,total 和 item。
在循环里判断,判断它的状态码为true,也就是判断它们是否为选中状态。
如果是选中状态,total += item的数量 乘 item 的价格,返回计算方法,就可以获取到总价。
4.全选反选
在data里面定义checked为不选中(也就是false),在计算属性里面定义一个方法,有get和set, set是反选,get是全选,在反选input框里面设置v-model="item.checked", 在全选的input框中v-model里面设置方法名,在get里面使用every(所有的数据返回条件才返回true,否则是false),当他每一项单选框的状态为选中时,返回true,在set里面传一个val值,这个val值等于的是get返回的数据,再使用循环遍历,当全部数据的单选框状态等于这个val, 这样就实现了全选反选。
九、promise的理解和async函数,如何实现多个网络请求成功之后,并拿到数据之后再执行其他的异步操作。
1.promise是什么?
它可以去实现一个异步操作,最常见的应该就是去封装成异步请求了。
就是将将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数(解决了回调地狱)。
promise也是一个构造函数。可以帮我们把异步操作队列化,按照顺序执行返回结果。自身上有all、reject、resolve这几个方法,原型上有then、catch等方法。
2,promise的状态
Promise对象代表一个异步操作,对象的状态不受外界影响,
- pending:初始状态,没有成功或失败(进行中),
- fulfilled:操作结束并且请求成功
- rejected:请求失败
3. async与await的使用
async与await是ES6标准中新增的关键字,作为处理异步请求的一种解决方案,是对promise的一个完善。是generator一个语法糖。
1.async 和 await 是一种同步的写法,但还是异步的操作,必须同时去写才会生效。
2. 函数前面多了一个aync关键字,await关键字只能用在aync定义的函数内。
3. async函数会隐式地返回一个promise该promise的reosolve值就是函数return的值。
4. await在数据,await 接收的对象必须还是个 promise 对象。
4.基本使用
下面是 async
与 Promise
异步操作的基本使用。
使用场景:当异步操作需要按顺序执行时可以使用,如按顺序读取多个文件内容。
限制:await
后面表达式 异步出错了 会中断下一步的await
表达式的异步执行;
let asyncFn = async function() {
await Promise.resolve('hello world 1').then(v => {
console.log(v);
});
await Promise.resolve('hello world 2').then(v => {
console.log(v);
});
await Promise.resolve('hello world 3').then(v => {
console.log(v);
});
}
asyncFn(); //hello world 1 hello world 2 hello world 3
但是,如果使用了catch
捕获错误,后面的异步可以继续执行;
let asyncFn = async function() {
await Promise.reject('出错了').catch(e => {
console.log(e);
});
await Promise.resolve('hello world').then(v => {
console.log(v);
});
}
asyncFn(); //出错了 hello world
十、reduce()方法的用法有哪些
1. 数组求和、求乘积
let numbers = [1, 2, 3, 4, 5]
let result1 = numbers.reduce((sum, n) => sum + n, 0)
console.log(result1); // 15
// let result2 = numbers.reduce((sum, n) => sum * n)
let result2 = numbers.reduce((sum, n) => sum * n, 1)
console.log(result2); // 120
2. 累加数组中对象的值
let numberObj = [{n: 1}, {n: 2}, {n: 3}, {n: 4}, {n: 5}]
let result3 = numberObj.reduce((sum, obj) => sum + obj.n, 0)
console.log(result3); // 15
3. 二维数组变一维数组
let twoArray = [[0, 1], [2, 3], [4, 5]]
let oneArray = twoArray.reduce((arr, val) => arr.concat(val), [])
console.log(oneArray); // [0, 1, 2, 3, 4, 5]
4.将多维数组转化为一维
let moreArr = [[0, 1], [2, 3], [4,[5,6,7]]]
const resultArr = function(moreArr){
return moreArr.reduce((pre,cur) => pre.concat(Array.isArray(cur) ? resultArr(cur) : cur), [])
}
console.log(resultArr(moreArr)); // [0, 1, 2, 3, 4, 5, 6, 7]
5.数组去重
let arr = [1, 2, 3, 4, 4, 1]
let newArr = arr.reduce((pre,cur)=>{
if(!pre.includes(cur)){
return pre.concat(cur)
}else{
return pre
}
},[])
console.log(newArr); // [1, 2, 3, 4]
十一、小程序的运行机制和更新机制
1.运行机制
热启动 :假如⽤户已经打开了某个⼩程序,在⼀定时间内再次打开⼩程序的话,这个时候我们就不再需要重新启动了,这需要把我们的后台打开的⼩程序切换到前台来使⽤(挂起状态)。
冷启动:⽤户⾸次打开⼩程序或被微信主动销毁再次打开的情况,此时⼩程序需要重新加载启动。
1.1 小程序的冷启动和热启动
1.2小程序前后台
1.3挂起状态
1.4小程序销毁
2.更新机制
其实微信客户端会有若干个时机取检查本地缓存,如果有新版本,那就进行小程序代码包的更新,但如果恰巧发布新版本后没有经过这些时机就打开小程序,那打开可能还会是旧版本的小程序。
2.1 启动时同步更新
-
定期检查发现新版本
-
用户长时间未使用
2.2 启动时异步更新
十二、小程序的生命周期
1. 请谈谈小程序的生命周期函数(应用 页面的 )5个
onLoad()页面加载时触发,只会调用一次,可获取当前页面路径中的参数
onShow()页面显示/切入前台时候触发,一般用来发送数据请求
onReady()页面初次渲染完成时触发,只会调用一次,代表页面已可和视图层进行交互
onHide()页面隐藏/切入后台时触发,如底部tab切换到其他页面或小程序切入后台等
onUnload()页面卸载时触发,如redirectTO或navigateBack到其他页面时
-------------------------
onPullDownRefresh():下拉刷新的钩子函数
onReachBottom():上翻到底的钩子函数
2. 请谈谈小程序的组件生命周期函数
created():组件实例刚刚被创建好时触发。
attached():在组件完全初始化完毕、进入页面节点树后触发。
detached() 组件离开页面节点树后触发。
十三、小程序的传值
1. 页面跳转或重定向时,使用url带参数传递数据(路由传值)
2. 使用本地存储传递参数
3. 使用全局变量传递数据
4. 给html元素添加data-*属性来传递值,然后通过e.currentTarget.dataset或onload的param参数获取(data- 名称不能有大写字母,不可以存放对象)
5. 设置id 的方法标识来传值,通过e.currentTarget.id获取设置的id值,然后通过设置全局对象的方式来传递数据
6. 在navigator中添加参数数值
十四、小程序的支付是如何实现的
小程序注册,要以公司的身份去注册一个小程序,才有微信支付权限
1.创建订单
请求创建订单的 API 接口:把(订单金额、收货地址、订单中包含的商品信息)发送到服务器
服务器响应的结果:订单编号
2.订单预支付
请求订单预支付的 API 接口:把(订单编号)发送到服务器
服务器响应的结果:订单预支付的参数对象,里面包含了订单支付相关的必要参数
3.发起微信支付
调用 uni.requestPayment() 这个 API,发起微信支付;把步骤 2 得到的 “订单预支付对象” 作为参数传递给 uni.requestPayment() 方法
监听 uni.requestPayment() 这个 API 的 success,fail,complete 回调函数
wx.requestPayment({
'timeStamp': _this.data.order.jsApiParameters.timeStamp, //当前时间戳
'nonceStr' : _this.data.order.jsApiParameters.nonceStr, //随机字符串长度
'package' : _this.data.order.jsApiParameters.package, //统一下单
'signType' : 'MD5', //签名算法,应与后台下单时的值一致
'paySign' : _this.data.order.jsApiParameters.paySign, //签名
'success':function(res){
if(res.errMsg == 'requestPayment:ok'){
wx.navigateTo({
url:'/pages/success/success?order_id='+_this.data.order_id, //跳转页面的路径,可带参数 ?隔开,不同参数用 & 分隔;相对路径,不需要.wxml后缀
})
}else{
wx.navigateTo({
url:'/pages/error/error?order_id='+_this.data.order_id, //跳转页面的路径,可带参数 ?隔开,不同参数用 & 分隔;相对路径,不需要.wxml后缀
})
}
},
'fail':function(res){
wx.showToast({
title: '已取消',
duration: 1000,
});
return false;
}
})
十五、小程序的双向数据绑定和vue的区别
大体相同,但小程序之间this.data的属性是不可以同步到视图的,必须调用this.setData()方法。
十六、小程序实现下拉刷新有哪几种方法
⽅案 ⼀ :onPullDownRefresh函数
1. 通过在 app.json 中, 将 "enablePullDownRefresh": true, 开启全局下拉刷新。
或者通过在 组件 .json , 将 "enablePullDownRefresh": true, 单组件下拉刷新。
2. 在页面中监听页面下拉事件,跟生命周期同级位置声明 onPullDownRefresh 函数
3. 在刷新完成后关闭下拉刷新效果。stopPullDownRefresh()
// 下拉刷新的事件
onPullDownRefresh() {
// 因为刷新后数据都重新渲染, 那我们要确保最新的数据在第一页
this.queryObj.pagenum = 1
this.goodsList(uni.stopPullDownRefresh)
}
⽅案⼆:
scroll-view :使⽤该滚动组件 ⾃定义刷新,通过 bindscrolltoupper 属性, 当滚动到顶部/左边,会触发 scrolltoupper事件,所以我们可以利⽤这个属性,来实现下拉刷新功能。
十七、适配,移动端各种机型的适配是怎么做的
方案一:百分比设置 (不推荐)
方案二:rem适配
1 - 媒体查询
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<title>Document</title>
<style>
/* 利用css的层叠特性 */
@media screen and (min-width: 320px) {
html {
font-size: 16px;
}
}
@media screen and (min-width: 375px) {
html {
font-size: 18px;
}
}
@media screen and (min-width: 414px) {
html {
font-size: 20px;
}
}
@media screen and (min-width: 480px) {
html {
font-size: 22px;
}
}
.box {
width: 5rem;
height: 5rem;
background-color: skyblue;
}
</style>
</head>
<body>
<div class="box"></div>
</body>
</html>
2 - 使用scss的函数或者less的混入来计算
less文件设置
@textColor:#12345678;
.poToRem(@px){
// 375 -> 37.5 根据设计稿来的 设计稿375px 那就 / 37.5
result:1rem * (@px / 37.5)
}
// 使用less
.box{
// 利用混入来设定
width: .poToRem(100)[result];
height: .poToRem(100)[result];
}
p{
font-size: .poToRem(16)[result];
}
3 - 使用postcss-pxtorem插件
webpack的这个工具,在打包时会自动换算
01. 安装
npm install postcss-pxtorem --save-dev
02. 在postcss.config.js中配置
module.exports = {
plugins: [
require('postcss-preset-env'),
// 使用这个插件
require('postcss-pxtorem')({
rootValue: 37.5, // 设计稿宽度的1/10
propList: ['*'], // 需要做转化处理的属性,如`hight`、`width`、`margin`等,`*`表示全部
exclude: /node_modules/i // 忽略的文件
})
]
};
03. 这样在页面上我们还是直接写px即可,打包后后自动更改的
4 - 使用VSCode插件 : px to rem 插件
点击齿轮⚙️ ,选择扩展设置
03. 使用
方案三:flex的弹性布局
十八、防抖节流
1、防抖(debounce):触发高频事件后 n 秒内函数只会执行一次,如果 n 秒内高频事件再次被触发,则重新计算时间
举例:就好像在百度搜索时,每次输入之后都有联想词弹出,这个控制联想词的方法就不可能是输入框内容一改变就触发的,他一定是当你结束输入一段时间之后才会触发。
2.节流(thorttle):高频事件触发,但在 n 秒内只会执行一次,所以节流会稀释函数的执行频率.
比如:王者技能按了之后,3秒内不能再触发。
举例:预定一个函数只有在大于等于执行周期时才执行,周期内调用不执行。就好像你在淘宝抢购某一件限量热卖商品时,你不断点刷新点购买,可是总有一段时间你点上是没有效果,这里就用到了节流,就是怕点的太快导致系统出现bug。
定时器setTimeOut
区别:防抖动是将多次执行变为最后一次执行,
节流是将多次执行变成每隔一段时间执行。
十九. $nextTick是什么?
★nextTick 是在下次 DOM 更新循环结束之后执行延迟回调,在修改数据之后使用 nextTick,获取更新后的 DOM。
Vue.nextTick和Vue.$nextTick的差别:
Vue.nextTick(callback),当数据发生变化,更新后执行回调。
Vue.$nextTick(callback),当dom发生变化,更新后执行的回调。
二十、状态码
200 – 请求成功。一般用于GET与POST请求
3xx (重定向)
301 – 资源(网页等)被永久转移到其它URL
302 Found 临时性重定向。
304 Not Modified 自从上次请求后,请求的网页未修改过。重定向到浏览器缓存
401: Unauthorized请求要求用户的身份认证,请求未授权
403 Forbidden 禁止访问
404 – 请求的资源(网页等)不存在
500 – 内部服务器错误