1) v-show与v-if的共同点:
我们都知道在 vue 中 v-show 与 v-if 的作用效果是相同的(不含v-else),都能控制元素在页面是否显示
在用法上也是相同的
<Model v-show="isShow" />
<Model v-if="isShow" />
2)v-show与v-if的区别
控制手段:v-show隐藏则是为该元素添加css–display:none,dom元素依旧还在。v-if显示隐藏是将dom元素整个添加或删除
编译过程:v-if切换有一个局部编译/卸载的过程,切换过程中合适地销毁和重建内部的事件监听和子组件;v-show只是简单的基于css切换
编译条件:v-if是真正的条件渲染,它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。只有渲染条件为假时,并不做操作,直到为真才渲染
v-show 由false变为true的时候不会触发组件的生命周期
v-if由false变为true的时候,触发组件的beforeCreate、create、beforeMount、mounted钩子,由true变为false的时候触发组件的beforeDestory、destoryed方法
性能消耗:v-if有更高的切换消耗;v-show有更高的初始渲染消耗
3)v-show与v-if的使用场景
v-if 与 v-show 都能控制dom元素在页面的显示
v-if 相比 v-show 开销更大的(直接操作dom节点增加与删除)
如果需要非常频繁地切换,则使用 v-show 较好
如果在运行时条件很少改变,则使用 v-if 较好
vue中data必须是函数是为了保证组件的独立性和可复用性,data是一个函数,组件实例化的时候这个函数将会被调用,返回一个对象,计算机会给这个对象分配一个内存地址,你实例化几次,就分配几个内存地址,他们的地址都不一样,所以每个组件中的数据不会相互干扰,改变其中一个组件的状态,其它组件不变。
为了防止多个组件实例对象之间共用一个data,产生数据污染。采用函数的形式,initData时会将其作为工厂函数都会返回全新data对象
1)什么是$nextTick?
$nextTick是vue.js中的一个重要方法,他被称为"异步队列",他的功能是在当前代码执行完毕之后执行回调函数,实现响应式、异步更新。
SnextTick 的具体用法
1、更新 DOM
当 vue 实例中的数据发生变化时,使用SnextTick 可以实现立即更新 DOM。因为 Vue.js 将所有数据变化放入异步更新队列,所以在发生变化之后,如果要立即更新 DOM,就可以采用$nextTick 选项这样就可以实现响应式更新 DOM。
代码示例:
this.name = name
$nextTick(0 =>{
// DOM 更新完成
})
2、异步操作
在 Vue 实例中,如果需要执行一些异步操作,可以使用SnextTick方法,在当前代码执行完成之后执行。一般来说,只有在异步操作之后才能获取到期望的结果,因此在使用SnextTick 方法实现异步操作时,可以将回调函数放入SnextTick 中,以便及时获取期望结果。
代码示例:
$nextTick(0)=>[
axios.get(url).then(res => {
//取请求的结果
).catch(err =>[
//常处理
})
})
3、强制刷新组件
在 Vue.js 中,有时候你想要强制刷新组件,比如在某个接口请求完毕后想要立即刷新页面的组件,这时候就可以使用SnextTick 方法,它可以支持强制更新组件。
代码示例:
$nextTick(0) =>{
this.$forceUpdate()
})
总结
以上就是 Vue.js 中特殊方法$nextTick 及其具体用法的详细分析,它可以用于 Vue 实例中的 DOM 更新、异步操作、强制刷新组件等它可以在数据发生变化之后立即更新 DOM,也可以将回调函数放入SnextTick 中实现异步操作,甚至可以使用SnextTick 来强制刷新组件,从而获得期望的结果
什么是双向绑定?
我们先从单向绑定切入单向绑定非常简单,就是把Model绑定到View,当我们用JavaScript代码更新Model时,View就会自动更新双向绑定就很容易联想到了,在单向绑定的基础上,用户更新了View,Model的数据也自动被更新了
双向绑定的原理是什么?
我们都知道 Vue 是数据双向绑定的框架,双向绑定由三个重要部分构成
数据层(Model):应用的数据及业务逻辑
视图层(View):应用的展示效果,各类UI组件
业务逻辑层(ViewModel):框架封装的核心,它负责将数据与视图关联起来
而上面的这个分层的架构方案,可以用一个专业术语进行称呼:MVVM这里的控制层的核心功能便是 “数据双向绑定” 。自然,我们只需弄懂它是什么,便可以进一步了解数据绑定的原理
实现双向绑定
vue 双向数据绑定是通过 数据劫持 结合 发布订阅模式的方式来实现的,
也就是说数据和视图同步,数据发生变化,视图跟着变化,视图变化,数据也随
之发生改变;
核心:关于 VUE 双向数据绑定,其核心是 Object.defineProperty()方法。
在vue中,永远不要把v-if和v-for同时用在同一个元素上,会带来性能方面的浪费(每次渲染都会先循环再进行条件判断);想要避免出现这种情况,可在外层嵌套template(页面渲染不生成dom节点),在这一层进行v-if判断,然后在内部进行v-for循环。
vue中修饰符分为以下五种:
应用场景:
.stop:阻止事件冒泡
.native:绑定原生事件
.once:事件只执行一次
.self :将事件绑定在自身身上,相当于阻止事件冒泡
.prevent:阻止默认事件
.caption:用于事件捕获
.once:只触发一次
.keyCode:监听特定键盘按下
.right:右键
vue2 和vue3 是不一样的
vue2:
全局自定义指令:vue.directive(’第一个参数是指令名称‘,{第二个参数是一个对象,这个对象有钩子函数})
局部自定义指令通过组件options选项中设置directive属性,是定义在组件内部的,只能在当前组件中使用
自定义指令应用场景:防抖 图片懒加载 一键copy的功能
自定义指令的钩子函数
inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。
componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。
unbind:只调用一次,指令与元素解绑时调用
vue3:
created - 新增!在元素的 attribute 或事件监听器被应用之前调用。
bind 变为 → beforeMount 在元素被插入到 DOM 前调用,通常进行css的操作
inserted 变为→ mounted 可以进行DOM操作
beforeUpdate:新增!在元素本身被更新之前调用,与组件的生命周期钩子十分相似。
update → 移除!该钩子与 updated 有太多相似之处,因此它是多余的。请改用 updated。
componentUpdated → updated
beforeUnmount:新增!与组件的生命周期钩子类似,它将在元素被卸载之前调用。
unbind -> unmounted
1) 什么是插槽?
插槽(Slot)是 Vue 提出来的一个概念,正如名字一样,插槽用于决定将所携带的内容,插入到指定的某个位置,从而使模板分块,具有模块化的特质和更大的重用性。插槽显不显示、怎样显示是由父组件来控制的,而插槽在哪里显示就由子组件来进行控制
2)插槽的分类
插槽有三种:默认插槽、具名插槽、作用域插槽。
背景
使用vue开发时,在vue初始化之前,由于div是不归vue管的,所以我们写的代码在还没有解析的情况下会容易出现花屏现象,看到类似于{{message}}的字样,虽然一般情况下这个时间很短暂,但是我们还是有必要让解决这个问题的。
解决方法
vue指令:v-cloak渲染指令(v-cloak 指令是解决屏幕闪动的好方法)
v-cloak要放在什么位置呢,是不是每个需要渲染数据的标签都要添加这个指令,经过试验发现,v-cloak并不需要添加到每个标签,只要在el挂载的标签上添加就可以,
方法一:
<p class="#app" v-cloak>
<p>{{value.name}}</p>
</p>
而且,在css里面要添加
<style>
[v-cloak] {
display: none;
}
</style>
方法二:(第一种没有彻底解决问题)
在根元素加上
style=“display: none;” :style=“{display: block }”
总结
v-cloak原理是先通过样式隐藏内容,然后在内存中进行值的替换,将替换的内容再反馈给界面,数据渲染完成之后,v-cloak 属性会被自动去除。
由于 JavaScript 的限制,Vue 不能检测以下变动的数组:
当你利用索引直接设置一个项时,例如:vm.items[indexOfItem] = newValue
当你修改数组的长度时,例如:vm.items.length = newLength
VUE给出了方法:vue.set() ,或者写成 this.$set(ARR)
调用方法:Vue.set( target, key, value )
target:要更改的数据源(可以是对象或者数组)
key:要更改的具体数据
value :重新赋的值
现在的代码就可以写成
Vue.set( this.items, 2, {message:"Change Test",id:'1'} )
页面视图也会更新。
还有 变异方法 (mutation method):
变异方法 ,顾名思义,会改变被这些方法调用的原始数组。相比之下,也有非变异 (non-mutating method) 方法,例如:filter(), concat() 和 slice() 。这些不会改变原始数组,但总是返回一个新数组。
1. push()
2. pop()
3. shift()
4. unshift()
5. splice()
6. sort()
7. reverse()
概览Vue3的新特性,如下:
速度更快
vue3相比vue2
1.体积更小
通过webpack的tree-shaking功能,可以将无用模块“剪辑”,仅打包需要的能够tree-shaking,有两大好处:
对开发人员,能够对vue实现更多其他的功能,而不必担忧整体体积过大
对使用者,打包出来的包体积变小了
vue可以开发出更多其他的功能,而不必担忧vue打包出来的整体体积过多
2.更易维护
可与现有的Options API一起使用
灵活的逻辑组合与复用
Vue3模块可以和其他框架搭配使用
2.1 更好的Typescript支持
2.2 编译器重写
3.更接近原生
可以自定义渲染 API
4. 更易使用
响应式 Api 暴露出来
Vue 3 中需要关注的一些新功能包括:
打包大小减少41%
初次渲染快55%, 更新渲染快133%
内存减少54%
…
使用Proxy代替defineProperty实现响应式
重写虚拟DOM的实现和Tree-Shaking
…
我们都知道ref函数和reactive函数都是用来定义响应式数据;
但是reactive更适合定义复杂的数据类型(json/arr)、ref适合定义基本数据类型(可接收基本数据类型和对象)
reactive:
它的响应式是更加‘深层次’的,底层本质是将传入的数据包装成一个Proxy。
参数必须是对象或者数组,如果要让对象的某个元素实现响应式时比较麻烦。需要使用toRefs
ref:
ref(1)->reactive({value:1})
ref函数只能操作浅层次的数据,把基本数据类型当作自己的属性值;
深层次依赖于reactive
Methods
methods 中都是封装好的函数,无论是否有变化只要触发就会执行
适用场景:组件中功能的封装,逻辑处理
Computed
computed: 是 vue 独有的特性计算属性,可以对 data 中的依赖项再重新计算得到一个新值,应用到视图中,和 methods 本质区别是 computed 是可缓存的, 也就是说 computed 中的依赖项没有变化,则 computed 中的值就不会重新计算, 而 methods 中的函数是没有缓存的。
适用场景:假设我们有一个性能开销比较大的计算属性 A,它需要遍历一个巨大的数组并做大量的计算。然后我们可能有其他的计算属性依赖于A 。如果没有缓存,我们将不可避免的多次执行某个函数
Watch
watch 是监听 data 和计算属性中的新旧变化
适用场景:当需要在数据变化时执行“异步”或“开销较大”的操作时,这个方式是最有用的
$ router是用来操作路由,$route是用来获取路由信息
$router是VueRouter的一个实例,他包含了所有的路由,包括路由的跳转方法,钩子函数等,也包含一些子对象(例如history)
$ route是一个跳转的路由对象(路由信息对象),每一个路由都会有一个$route对象,是一个局部的对象。
$ router的用法
//常规方法
this.$router.push("/login");
//使用对象的形式 不带参数
this.$router.push({ path:"/login" });
//使用对象的形式,参数为地址栏上的参数
this.$router.push({ path:"/login",query:{username:"jack"} });
使用对象的形式 ,参数为params 不会显示在地址栏
this.$router.push({ name:'user' , params: {id:123} });
$route的介绍
主要的属性有:
this.$route.path 字符串,等于当前路由对象的路径,会被解析为绝对路径,如/home/ews
this.$route.params 对象,包含路由中的动态片段和全匹配片段的键值对,不会拼接到路由的url后面
this.$route.query 对象,包含路由中查询参数的键值对。会拼接到路由url后面
this.$route.router 路由规则所属的路由器
this.$route.name 当前路由的名字,如果没有使用具体路径,则名字为空
1.基本使用
v-model可以实现表单元素和数据的双向绑定
什么是双向绑定?
例如:< input type=“text” v-model=“message”>
message的数据改变,input输入框中的数据会随之变化
input输入框中的数据变化了,message的数据也会改变
v-model其实是一个语法糖,它背后的本质是两个操作
< input type=“text” :value=“message” @input = “message = $event.target.value”>
和 < input type=“text” v-model=“message”>等价
在vue中v-on是提供的事件绑定机制,它是可以用来监听多个方法的,能够使用@替代v-on,
比如:“< input type=“text” :value=“name” @input=“onInput” @focus=“onFocus” @blur=“onBlur” />”,
而同一个事件就会报错 < a href=“javascript:;” @click=“methodsOne” @click=“methodsTwo”> a>
过滤器(filter)是输送介质管道上不可缺少的一种装置,大白话,就是把一些不必要的东西过滤掉,过滤器实质不改变原始数据,只是对数据进行加工处理后返回过滤后的数据再进行调用处理,我们也可以理解其为一个纯函数。
定义:对要显示的数据进行特定格式化后再显示(适用于一些简单逻辑的处理)。
Vue 允许你自定义过滤器,可被用于一些常见的文本格式化
ps: Vue3中已废弃filter,如果有使用过滤器的场景,可以使用 计算属性
建议在created里注册,在beforeDestory移出
在组件内的beforeRouteLeave中移除事件监听
vuex是一个状态管理工具
1)
2)
state => 基本数据(数据源存放地)
getters => 从基本数据派生出来的数据
mutations => 提交更改数据的方法,同步
actions => 像一个装饰器,包裹mutations,使之可以异步
modules => 模块化vuex
每个Vue组件都有生命周期,过程为创建 -> 挂载 -> 更新 -> 销毁。开发者可以通过钩子函数(如mounted)在组件生命周期中的不同时刻进行操作。
另外还有 keep-alive 独有的生命周期,分别为 activated 和 deactivated 。用 keep-alive 包裹的组件在切换时不会进行销毁,而是缓存到内存中并执行 deactivated 钩子函数,命中缓存渲染后会执行 activated 钩子函数。
1、setup() : 开始创建组件之前,在 beforeCreate 和 created 之前执行,创建的是 data 和 method
2、onBeforeMount() : 组件挂载到节点上之前执行的函数;
3、onMounted() : 组件挂载完成后执行的函数;
4、onBeforeUpdate(): 组件更新之前执行的函数;
5、onUpdated(): 组件更新完成之后执行的函数;
6、onBeforeUnmount(): 组件卸载之前执行的函数;
7、onUnmounted(): 组件卸载完成后执行的函数;
8、onActivated(): 被包含在 中的组件,会多出两个生命周期钩子函数,被激活时执行;
9、onDeactivated(): 比如从 A 组件,切换到 B 组件,A 组件消失时执行;
10、onErrorCaptured(): 当捕获一个来自子孙组件的异常时激活钩子函数。
vue2 -------> vue3
beforeCreate --------> setup(()=>{})
created --------> setup(()=>{})
beforeMount --------> onBeforeMount(()=>{})
mounted --------> onMounted(()=>{})
beforeUpdate --------> onBeforeUpdate(()=>{})
updated --------> onUpdated(()=>{})
beforeDestroy --------> onBeforeUnmount(()=>{})
destroyed --------> onUnmounted(()=>{})
activated --------> onActivated(()=>{})
deactivated --------> onDeactivated(()=>{})
errorCaptured --------> onErrorCaptured(()=>{})
总结: Vue2和Vue3钩子变化不大,删除了beforeCreate 、created 两个钩子使用setup()钩子来替代。
1. 轻量级
Vue作为一款轻量级前端框架,大小只有18–21KB,工程搭建简单,只需要几行命令符。因为Vue使用的主体语言为JS,开发者可以灵活地将其他框架(如React和Angular)的项目迁移到Vue,具有很高的集成能力。Vue提供的router路由可以便捷地搭建一个多界面应用。
2. 高性能
虚拟DOM和响应式避免了不必要的全局重新渲染,提升了用户体验,使用户操作更加流畅。
3. 好上手
与面向对象编程性质类似,组件化更符合人类思维。打个比方,我们在设计网页时,通常会把一个界面分成一块一块的、用于某功能的特定样式模块。Vue的组件化使前端开发更加容易理解,同时MVVM可以更便捷地实现交互,对新手十分友好。
4. 插件化
由于Vue框架的流行性,目前有许多基于Vue的npm扩展包和开发工具(如Vuex)。Vue可以在一个文件下统一管理所有外部插件的全局使用。
5. 便于测试
组件化利于开发者对于单一组件进行测试,很少发生在整个页面下找不到是哪个地方报错的情况。
6.运行速度更快
像比较与react而言,同样都是操作虚拟dom,就性能而言,vue存在很大的优势
7.视图,数据,结构分离
使数据的更改更为简单,不需要进行逻辑代码的修改,只需要操作数据就能完成相关操作
8.虚拟dom
单页面应用(SPA),通俗一点说就是指只有一个主页面的应用,浏览器一开始要加载所有必须的 html, js, css。所有的页面内容都包含在这个所谓的主页面中。但在写的时候,还是会分开写(页面片段),然后在交互的时候由路由程序动态载入,单页面的页面跳转,仅刷新局部资源。多应用于pc端。
多页面(MPA),就是指一个应用中有多个页面,页面跳转时是整页刷新
单页面的优点:
单页面缺点:
多页面应用的优点
//路由参数配置
const router = new VueRouter({
routes: [{
path: '/about/:id',
component: User
}]
})
//声明式导航使用
<router-link to="/about/12">跳转</router-link>
//路由参数配置
const router = new VueRouter({
routes: [{
name: 'user1',
path: '/about/:id',
component: User
}]
})
//声明式导航使用
<router-link :to="{ name: 'user1', params: { id: 123 } }">跳转</router-link>
//路由参数配置
const router = new VueRouter({
routes: [{
name: 'user1',
path: '/about',
component: User
}]
})
//声明式导航使用
<router-link :to="{ name: 'user1', params: { id: 123 } }">跳转</router-link>
//路由参数配置
const router = new VueRouter({
routes: [{
name: 'user1',
path: '/about',
component: User
}]
})
//使用name
<router-link :to="{ name: 'user1', query: { id: 123 }}"></router-link>
//使用path
<router-link :to="{ path: '/about', query: { id: 123 } }"></router-link>
获取参数
this.$route.params.xxx
this.$route.query.xxx
需要注意的点
1、如果使用params传参,且参数是以对象的形式,跳转路径只能使用name形式而不能用path.
2、如果想要params参数想传参也可以不传参需要在占位符后面加?。
//路由参数配置
const router = new VueRouter({
routes: [{
path: '/search/:keyword?',
name: 'search',
component: () => import('@/pages/Search'),
meta: { show: true }
}]
})
//编程式传参
this.$router.push({
name: "search",
params: {},
query: { keyword: this.keyword },
});
3、解决params传值为空字符串路径会出现问题:
this.$router.push({
name: "search",
params: { keyword: "" || undefined },
query: { keyword: this.keyword },
});
vue1.0 升级2.0有很多坑:生命周期;路由中引入静态js,全局组件,全局变量,全局function;v-for循环的key,value值互换了位置,还有track-by;filter过滤器;遍历数组时,key值不能做model;父子通信等等
Vue 组件的封装思路,可以归结为几个步骤:
1、根据功能把需要实现的功能分成多个组件,每个组件间有不同的职责划分;
2、如果有需要,可以对组件进行通用化封装,将公共部分抽离出来,以减少重复代码,提高组件的复用性:
3、组件内部可以使用 props 传递参数,也可以使用events 传递事件,但是要注意不要滥用,以保证组件的职责划分清晰;
4、在 Vue 中,组件可以接收到 data 和 computed属性,这些属性可以定义组件的一些特征,比如颜色、宽度等,也可以使用 methods 来定义组件的交互行为;5、在 Vue 中,可以使用 watch 来监听 props 或者data 的变化,以实现组件内部逻辑的触发:
6、在组件封装的时候,要注意组件的生命周期,以便及时释放或者重新获取资源:
7、在实现组件的时候,要注意 DOM 结构的优化,以减少不必要的渲染次数,以提高组件的性能:
8、在封装组件的时候,需要考虑组件的通用性,可以尽量将组件的实现方式封装的更加灵活,以满足更多的业务场景;
9、在组件封装完成之后,可以进行单元测试,确保组件可以正常工作,并且能够提供可靠的服务;
10、最后,组件封装完成后,可以将组件发布到 NPM上,以便其他开发者可以使用,也可以提供参考和学习,以促进Vue的发展
总结起来,Vue 组件封装思路包括:根据功能把需要实现的功能分成多个组件:如果有需要,可以对组件进行通用化封装;使用 props 传递参数;使用 data 和computed 属性定义组件的特征;使用 watch 监听 props或 data 的变化:注意组件的生命周期:优化 DOM 结构:考虑组件的通用性:进行单元测试;将组件发布到 NPM上。以上这些步骤,是 Vue 组件封装思路的概括
如果请求来的数据是不是要被其他组件公用,仅仅在请求的组件内使用,就不需要放入vuex 的state里。
如果被其他地方复用,这个很大几率上是需要的,如果需要,请将请求放入action里,方便复用,并包装成promise返回,在调用处用async await处理返回的数据。如果不要复用这个请求,那么直接写在vue文件里很方便。
vuex有五个主要的属性,action getters mutations state module。
Action 类似于mutation,不同在于:
Action 提交的是mutation, 而不是直接变更状态;
Action 可以包含任意异步操作;
操作步骤:
(1)actions 里面放我们函数,函数里面的参数context ,可以帮我们提交的mutations。
逻辑梳理:到时候在组件内部,调用actions之后,actions里面又去调用mutations,而mutations又去修改了state。
在vue项目中用vuex来做全局的状态管理, 发现当刷新网页后,保存在vuex实例store里的数据会丢失。
原因:因为 store 里的数据是保存在运行内存中的,当页面刷新时,页面会重新加载vue实例,store里面的数据就会被重新赋值初始化。
我们有两种方法解决该问题:
使用vuex-along
vuex-along 的实质也是将 vuex 中的数据存放到 localStorage 或者 sessionStroage 中,只不过这个存取过程组件会帮我们完成,我们只需要用vuex的读取数据方式操作就可以了,简单介绍一下 vuex-along 的使用方法。
安装 vuex-along:
npm install vuex-along --save
配置 vuex-along: 在 store/index.js 中最后添加以下代码:
import VueXAlong from 'vuex-along' //导入插件
export default new Vuex.Store({
//modules: {
//controler //模块化vuex
//},
plugins: [VueXAlong({
name: 'store', //存放在localStroage或者sessionStroage 中的名字
local: false, //是否存放在local中 false 不存放 如果存放按照下面session的配置
session: { list: [], isFilter: true } //如果值不为false 那么可以传递对象 其中 当isFilter设置为true时, list 数组中的值就会被过滤调,这些值不会存放在seesion或者local中
})]
});
使用 localStorage 或者 sessionStroage
created() {
//在页面加载时读取sessionStorage里的状态信息
if (sessionStorage.getItem("store")) {
this.$store.replaceState(
Object.assign(
{},
this.$store.state,
JSON.parse(sessionStorage.getItem("store"))
)
);
}
//在页面刷新时将vuex里的信息保存到sessionStorage里
window.addEventListener("beforeunload", () => {
sessionStorage.setItem("store", JSON.stringify(this.$store.state));
});
},
1. mapState
import { mapState } from 'vuex'
export default {
// ...
computed:{
...mapState({
// 箭头函数可使代码更简练
count: state => state.count,
// 传字符串参数 'count' 等同于 `state => state.count`
countAlias: 'count',
// 为了能够使用 `this` 获取局部状态,必须使用常规函数
countPlusLocalState (state) {
return state.count + this.localCount
}
})
}
}
定义的属性名与state中的名称相同时,可以传入一个数组:
//定义state
const state={
count:1,
}
//在组件中使用辅助函数
computed:{
...mapState(['count'])
}
2. mapGetters
computed:{
...mapGetters({
// 把 `this.doneCount` 映射为 `this.$store.getters.doneTodosCount`
doneCount: 'doneTodosCount'
})
}
当属性名与getters中定义的相同时,可以传入一个数组
总结:
3. mapMutations
methods:{
...mapMutations({
add: 'increment' // 将 `this.add()` 映射为 `this.$store.commit('increment')`
})
}
当属性名与mapMutatios中定义的相同时,可以传入一个数组
methods:{
...mapMutations([
'increment', // 将 `this.increment()` 映射为 `this.$store.commit('increment')`
// `mapMutations` 也支持载荷:
'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.commit('incrementBy', amount)`
]),
}
** 4. mapActios**
mathods:{
...mapActions({
add: 'increment' // 将 `this.add()` 映射为 `this.$store.dispatch('increment')`
})
}
当属性名与mapActios中定义的相同时,可以传入一个数组
methods:{
...mapActions([
'increment', // 将 `this.increment()` 映射为 `this.$store.dispatch('increment')`
// `mapActions` 也支持载荷:
'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.dispatch('incrementBy', amount)`
]),
}
总结
this.$store.commit('app/addCount')
computed: {
...mapState('some/nested/module', {
a: state => state.a,
b: state => state.b
})
},
methods: {
...mapActions('some/nested/module', [
'foo', // -> this.foo()
'bar' // -> this.bar()
])
}
或者使用 createNamespacedHelpers函数来创建一个基于命名空间的辅助函数
import { createNamespacedHelpers } from 'vuex'
const { mapState, mapActions } = createNamespacedHelpers('some/nested/module') //给定路径
//使用方法与之前相同
export default {
computed: {
// 在 `some/nested/module` 中查找
...mapState({
a: state => state.a,
b: state => state.b
})
},
methods: {
// 在 `some/nested/module` 中查找
...mapActions([
'foo',
'bar'
])
}
}
声明自己对于插槽的理解:其实就是一种父子组件传值的一种方式。
需要明白两点:
匿名插槽
<div id="app">
<div class="father">
<h3>这里是父组件</h3>
<child>
<span>我是插槽插入的内容</span>
</child>
</div>
</div>
<template id="child">
<div class="child">
<h3>这里是子组件</h3>
<slot></slot>
</div>
</template>
<script>
var vm = new Vue({
el: '#app',
data: {},
components: {
child: {
template: '#child'
}
}
});
</script>
上面的代码所展示的效果就是你会发现在
具名插槽
<div id="app">
<div class="father">
<h3>这里是父组件</h3>
<child>
<span slot="demo1">菜单1</span>
<span>菜单2</span>
<span slot="demo3">菜单3</span>
</child>
</div>
</div>
<template id="child">
<div class="child">
<h3>这里是子组件</h3>
<slot></slot>
<slot name="demo3"><slot>
</div>
</template>
<script>
var vm = new Vue({
el: '#app',
data: {},
components: {
child: {
template: '#child'
}
}
});
</script>
具名插槽其实就是在父组件中添加一个 slot=‘自定义名字’ 的属性,然后在子组件中的 里面添加 作用域插槽 页面显示的结果如下: 这里是父组件 这里是子组件 [‘zhangsan’, ‘lisi’, ‘wanwu’, ‘zhaoliu’, ‘tianqi’, ‘xiaoba’] 匿名插槽用法不变 Vue3(其实从2.6开始)中引入了一个新的指令 v-slot,用来表示具名插槽和默认插槽。 Vue2.X和Vue3.X对比 beforeCreate --------> setup(()=>{}) diff整体策略为:深度优先,同层比较 在新老虚拟DOM对比时 在diff中,只对同层的子节点进行比较,放弃跨级的节点比较,使得时间复杂从O(n^3)降低值O(n),也就是说,只有当新旧children都为多个子节点时才需要用核心的Diff算法进行同层级比较。 方式1、 方式2、 vue2 vue3是用过proxy实现数据响应式的,他不会出现这种情况,直接动态添加新属性仍可以实现数据响应式 什么是双向绑定 我们都知道 Vue 是数据双向绑定的框架,双向绑定由三个重要部分构成 理解ViewModel 当然,它还有两个主要部分组成 实现双向绑定(流程) 数据也不通,谁在后面谁优先: setup 和 data 父组件: 子组件: 子组件: 父组件: refs 实现组件间的通信(可跨级)—— defineExpose Options API 存在的问题 Composition API 的优势 shallowReactive:只处理对象最外层属性的响应式(浅响应式)。 provide与inject是Vue中用于跨组件通信的一对API,可以将数据或方法注入到子组件中。 provide用于在父组件中声明要提供给子组件使用的数据或方法,inject用于在子组件中注入父组件提供的数据或方法。 具体使用方法如下: 在父组件中使用provide声明要提供给子组件使用的数据或方法,如: 在子组件中使用inject注入父组件提供的数据或方法,如: 需要注意的是,provide和inject的数据或方法是单向下传递的,即只能由父组件提供给子组件使用,无法在子组件中修改父组件的数据或方法。同时,provide和inject的使用应该谨慎,不要滥用,以免造成代码复杂性和维护困难度的增加。 两者区别:toRaw会将整个对象变成非响应式的,markRaw可以指定哪些属性值可以变化, 在不希望数据被修改,或当数据是从别的地方取过来,不希望影响源数据时,使用readonly()或shallowReadonly()就很有用 hook,本质是一个函数。自定义hook,就是将setup中使用过的组合式函数进行封装,实现代码复用。类似于v2中的mixin 自定义hook的优势: 复用代码, 让setup中的逻辑更清楚易懂。 不一定, 最直观的区别就是在url中,hash带了#,history没有#,它们两个是路由配置mode的两个选项。 前端路由的核心是在改变视图的同时不会向后端发出请求,浏览器提供的这两种支持就是为了达到这一目的。 两种方式的对比 2、history模式: 1.标签名称不同 HTML(div,span,img,a) 2.属性节点不同 HTML : < a href=“#”>超链接< /a> 3.WXML中提供了类似于Vue中的模板语法 WXSS增加了rpx尺寸单位,在不同大小的尺寸屏幕下会进行自动换算 WXSS提供了全局样式(app.wxss)来对设置全局样式,和页面css来设置局部样式 wxss只会支持css的部分选择器(.class/#id/element/并集后代后代选择器/等) 小程序中的数据双向绑定 vue中的数据双向绑定 区别: 大体上区别不大,绑定事件不同,以及获取value值的具体方式不同,以及在小程序中设置data中的数据,需要调用 this.setData方法进行设置 微信小程序项目结构主要有四个文件类型: app.json 必须要有这个文件,此文件用来对微信小程序进行全局配置,决定页面文件的路径、窗口表现、设置网络超时时间、设置tabBar 最少两个。 微信小程序的物种传值方式 bindtap和catchtap都是微信小程序中用来绑定事件的,但是它们有一些区别。 bindtap是绑定点击事件,当用户点击元素时触发。 所以区别就是,bindtap是冒泡事件,catchtap是捕获事件。 wx.navigateTo():保留当前页面,跳转到应用内的某个页面。但是不能跳到 tabbar 页面,使用 wx.navigateBack 可以返回到原页面。小程序中页面栈最多十层。 简单来说,小程序是一种应用,运行的环境是微信(App);H5是一种技术,依附的外壳是是浏览器。 从「前端开发」的视角来看,微信小程序和H5也存在着多方面的不同。概括来说有以下四个方面的区别。 一、运行环境的不同 H5的运行环境是浏览器,包括webview,而微信小程序的运行环境并非完整的浏览器,因为小程序的开发过程中只用到一部分H5技术。 小程序的运行环境是微信开发团队基于浏览器内核完全重构的一个内置解析器,针对性做了优化,配合自己定义的开发语言标准,提升了小程序的性能。 二、开发成本的不同 开发一个微信小程序,由于微信团队提供了开发者工具,并且规范了开发标准,则简单得多。前端常见的HTML、CSS变成了微信自定义的WXML、WXSS,WXML,官方文档中都有明确的使用介绍,开发者按照说明专注写程序就可以了。 需要调用后端接口时,调用发起请求API;需要上传下载时,调用上传下载API;需要数据缓存时,调用本地存储API;引入地图、使用罗盘、调用支付、调用扫码等等功能都可以直接使用;UI库方面,框架带有自家weui库加成。 并且在使用这些API时,不用考虑浏览器兼容性,不用担心出现BUG,显而易见微信小程序的开发成本相对低很多 三、获取系统级权限的不同 微信小程序相对于H5能获得更多的系统权限,比如网络通信状态、数据缓存能力等,这些系统级权限都可以和微信小程序无缝衔接。 而这一点恰巧是H5 被诟病的地方,这也是H5的大多应用场景被定位在业务逻辑简单、功能单一的原因。 四、页面体验不同 H5网页需要在浏览器中渲染,会给人明显的「卡顿」感觉,面对复杂的业务逻辑或者丰富的页面交互时尤为明显。 而微信小程序,它的代码直接在微信上运行,省去了通过浏览器渲染的步骤,因此,在微信中使用小程序,才会比H5流畅很多。 除了首次打开需要几秒的加载时间外,小程序各个页面的切换、跳转等体验已经媲美原生App,有着同样的柔丝般顺滑的效果。 一、生命周期函数不一样: 二、数据请求时间不一样: 三、数据绑定方式不一样: 四、 显示与隐藏元素不一样: 五、事件处理不一样: 六、数据双向绑定不一样: 七、绑定事件传参不一样: 八、父子组件通信不一样: 在vue中需要: 在小程序中需要: 在vue中, 在小程序中, vue会给子组件添加一个 ref属性,通过 this.refs.ref的值便可以获取到该子组件,然后便可以调用子组件中的任意方法。 rpx(responsive pixel): 响应单位,可以根据屏幕宽度进行自适应。 小程序不能使用各种浏览器暴露出来的 DOM API,进行 DOM 选中和操作 原因:在小程序中,渲染层和逻辑层是分开的,分别运行在不同的线程中,逻辑层运行在 JS引擎中,并没有一个完整浏览器对象,因而缺少相关的DOM API和BOM API。 微信小程序现有的在app.json中配置tabbar以及相应的api无法实现tabbar的动态切换,因此需要采用自定义tabbar的方式实现tabbar的动态切换。 二、遇到的问题 自定义tabbar在实现中会出现tabbar切换页面时闪动的情况,该问题在社区反馈较多,官方暂时还没有解决方案。 为tabbar某一项添加右上角文本(badge)。每个tab页下的自定义tabbar实例是不同的,可以在app.globalData中定义全局变量保存所有tab页的自定义tabbar实例,添加文本时循环所有tabbar实例添加badge。 有同步缓存和异步缓存 读取本地数据缓存接口的参数 :视情况选参 key:字符串类型,必填项,本地缓存中指定的key 为了安全,微信小程序只能请求http类型接口,请求其他接口时必须将接口的域名添加到新人列表中。 配置request合法域名 网络数据请求 url,请求的地址,string类型,必填。 发起get请求 发起post请求 页面加载时候就请求数据 跨域和Ajax说明 有两种跳转方式: 小程序跳转注意事项:写路径的时候一定不要忘记加斜杠,理由:你如果不加斜杠的话,它就会在当前页面里面去找这个路径,那肯定找不到呀,因此写绝对路径时千万记得加斜杠。 wx.switchTab(Object object): wx.reLaunch(Object object): wx.redirectTo(Object object): wx.navigateTo(Object object): wx.navigateBack(Object object): 路由传参: 有 应用生命周期 和 页面生命周期 组件(component)的生命周期 App() 必须在 app.js 中调用,必须调用且只能调用一次,app.js中定义了一些应用的生命周期函数 页面生命周期 js文件中定义了一些页面生命周期函数,下面简述下这些生命周期函数的方法作用 组件生命周期 created(重要):组件实例刚刚被创建好时触发 浏览器中,所有 JavaScript 是在运行在同一个作用域下的,定义的参数或者方法可以被后续加载的脚本访问或者改写。和浏览器不同,小程序中可以将任何一个JavaScript 文件作为一个模块,通过module.exports 或者 exports 对外暴露接口。 微信小程序的api一共分为三种: 事件监听API:以on开头,用来监听某一些事件的触发; 同步API:以Sync结尾的api都是同步API。同步API的执行结果可以通过返回值直接获取,如果有错误会直接抛出异常。 异步API:类似与jQUery里面的ajax函数,需要通过返回类型success,fail接受调用的结果。 我自己使用的是一下步骤就可以使用了 这行代码的意思就是 编译插件配置,基本上到这里就可以使用了, 微信小程序事件通道(事件总线)是用于在小程序多个页面或组件之间通过触发事件进行通信的机制。 使用事件通道需要先在 app.js 中初始化事件总线: 在需要发送事件的页面或组件中,通过wx.navigateTo或wx.redirectTo方法跳转到目标页面或组件时,传入events参数,并将它赋值为事件通道对象 在目标页面或组件中,通过onLoad生命周期函数获得事件通道对象,并绑定事件处理函数: 当事件发生时,通过调用触发事件的方法,向事件通道中发送事件: 首先这是 vant weapp的网址 npm init 或者是 npm init -y 初始化之后,你会发现你的目录多出了package.json文件 4.2 安装 miniprogram 安装完毕后,你会发现你的目录中又多些文件。 将 app.json 中的 “style”: “v2” 去除,原因是小程序的新版基础组件强行加上了许多样式,难以覆盖,不关闭将造成部分组件样式混乱。 4.4 修改 project.config.json 开发者工具创建的项目,miniprogramRoot 默认为 miniprogram,package.json 在其外部,npm 构建无法正常工作。需要手动在 project.config.json 内添加如下配置,使开发者工具可以正确索引到 npm 依赖的位置。 4.5 构建 npm 我们点击左上角的工具栏 最后去使用一下组件 父向子组件传递数据 父组件(页面)向子组件传递数据,通过标签属性的方式来传递 (1)在子组件上进行接收 (2)把这个数据当成是data中的数据直接用即可 父传子 在子组件的js文件中,在properties中接收父组件传递的数据,properties里面要填接收的数据的名称,这里的名称是aaa,aaa是个对象,里面写数据的类型和数据的值,数据的值不填就默认是上面的值“a123a",填了数据值,值就是我们写的那个值 子传父 最后:一个共就两个函数注意就好了,子组件中的addInfo 和 父组件的 getAddInfo 生命周期函数 created:在组件实例刚被创建时执行 最重要的生命周期函数有3个,分别是created、attached、detached 组件实例刚被创建好时触发created生命周期函数 在组件初始化完毕,进入页面节点树时触发attched生命周期函数 在组件离开页面节点时,触发detached生命周期函数 在进入小程序的时候要判断是否有授权,如果没有授权,则要先授权之后,才能登陆到小程序的首页。 授权成功,获取用户信息成功之后,将用户信息存储在本地缓存中指定的 userInfo 中,然后跳转到小程序首页 之后不论在哪个页面,如果需要用户信息,从本地缓存中异步获取指定 userInfo 的内容即可 承载网页的容器。会自动铺满整个小程序页面 一、首先,web-view有以下限制: 二、然后看看web-view如何加载html 很简单,一行代码搞定,小程序中的web-view会自动占据整个页面,所以无法在web-view上再覆盖view 三、web-view交互 四、使用注意 点击查看详情
父组件模板的所有东西都会在父级作用域内编译;子组件模板的所有东西都会在子级作用域内编译。不过,我们可以在父组件中使用slot-scope 特性从子组件获取数据,前提是需要在子组件中使用:data=data 先传递data 的数据!<div id="app">
<div class="father">
<h3>这里是父组件</h3>
<child>
<div slot-scope="user">
{{user.data}}
</div>
</child>
</div>
</div>
<script>
Vue.component('child', {
template:'' +
'
这里是子组件
\n' +
' 2、vue3.0中插槽的使用
下面我们来看一下具名插槽的写法!// 子组件
<div class="hello">
我是一个封装的组件
<slot name="num"></slot>
</div>
// 父组件
<HelloWorld v-model="masg" v-slot:num>
<div>我是插槽插入的</div>
</HelloWorld>
// 父组件的另外一个写法
<HelloWorld v-model="masg">
<template v-slot:num>
<div>我是插槽插入的</div>
</template>
</HelloWorld>
在 v2.5 之后屏蔽了 slot-scope,
v-slot引入使其插槽更接近指令化。
作用域插槽的用法// 子组件
<div class="hello">
我是一个封装的组件
<slot :num="num"></slot>
</div>
<script>
import { ref } from 'vue';
export default {
name: 'HelloWorld',
props: {
// msg: String,
modelValue: String
},
setup(prop,context){
const num = ref(10);
return { num }
}
}
</script>
// 父组件
<HelloWorld>
<template v-slot="{num}">
<div>{{num}}</div>
</template>
</HelloWorld>
// 也可以改成下面的写法
<HelloWorld v-slot="{num}">
<div>{{num}}</div>
</HelloWorld>
和 v-bind和v-on相似,缩写只有在存在参数时才生效,这就意味着v-slot没有参数时不能使用#=,对于默认插槽,可以使用#default来代替v-slot
// 上面我们写过具名插槽可以这么写
<HelloWorld v-model="masg">
<template #num>
<div>我是插槽插入的</div>
</template>
</HelloWorld>
// 或者如上面的作用域插槽也可以改成下面的写法
<HelloWorld>
<template #default="{num}">
<div>{{num}}</div>
</template>
</HelloWorld>
32.vue3中如何获取refs,dom对象的方式?
33.vue3中生命周期的和vue2中的区别?
vue2 -------> vue3
created --------> setup(()=>{})
beforeMount --------> onBeforeMount(()=>{})
mounted --------> onMounted(()=>{})
beforeUpdate --------> onBeforeUpdate(()=>{})
updated --------> onUpdated(()=>{})
beforeDestroy --------> onBeforeUnmount(()=>{})
destroyed --------> onUnmounted(()=>{})
activated --------> onActivated(()=>{})
deactivated --------> onDeactivated(()=>{})
errorCaptured --------> onErrorCaptured(()=>{})34.说说vue中的diff算法?
35.说说 Vue 中 CSS scoped 的原理?
36.vue3中怎么设置全局变量?
可以设置一个专用的的全局变量模块文件,模块里面定义一些变量初始状态,用export default 暴露出去,在main.js里面使用Vue.prototype挂载到vue实例上面或者在其它地方需要使用时,引入该模块这样就达到了修改全局变量的目的了。
import api from '@/api'
app.config.globalProperties.$api = api
// ctx.$api 就是全局设置的变量
const {
proxy: { $api },
} = getCurrentInstance();
// ctx.$api 就是全局设置的变量
const { ctx } = getCurrentInstance()
37.Vue 中给对象添加新属性时,界面不刷新怎么办?
38.谈谈对Vue中双向绑定的理解?
就是把Model绑定到View,当我们用JavaScript代码更新Model时,View就会自动更新双向绑定就很容易联想到了,在单向绑定的基础上,用户更新了View,Model的数据也自动被更新了
双向绑定的原理是什么
它的主要职责就是:
5.将来data中数据⼀旦发生变化,会首先找到对应的Dep,通知所有Watcher执行更新函数39.为什么vue2和vue3语法不可以混用?
setup里没有this指向
vue2使用的是webpack形式去构建项目,而vue3使用vite构建项目。vue2中可以使用pototype的形式去进行操作,引入的是构造函数,vue3中需要使用结构的形式进行操作,引入的是工厂函数。40.vue3中setup函数如何进行组件通讯?
1、父传子 ----defineProps
<template>
<children :list="list"></children>
<div>
<input v-model="value" type="text" placeholder="请输入" />
<button @click="handleAdd"> 添加 </button>
</div>
</template>
<script setup>
import { ref } from 'vue'
import Children from '@/views/parentChildCommunicat/parentToChildren/components/children.vue'
const list = ref(['JavaScript', 'HTML', 'CSS'])
const value = ref('')
const handleAdd = () => {
list.value.push(value.value)
value.value = ''
}
</script>
<template>
<ul>
<li v-for="item in props.list" :key="item">{{ item }}</li>
</ul>
</template>
<script setup>
import { defineProps } from 'vue'
const props = defineProps({
list: {
type: Array,
default: () => []
}
})
</script>
2、子传父—defineEmits
<template>
<div>
<input v-model="value" type="text" placeholder="请输入" />
<button @click="handleAdd"> 添加 </button>
</div>
</template>
<script setup>
import { ref, defineEmits } from 'vue'
const value = ref('')
const emits = defineEmits(['add'])
const handleAdd = () => {
emits('add', value.value)
value.value = ''
}
</script>
<template>
<ul>
<li v-for="item in list" :key="item">{{ item }}</li>
</ul>
<son @add="add" />
</template>
<script setup>
import { ref } from 'vue'
import Son from './components/son.vue'
const list = ref(['JavaScript', 'HTML', 'CSS'])
const add = (value) => {
list.value.push(value)
}
</script>
3、跨级组件通信
41.vue3,Composition API 的优势?
1、Composition API就解决了 Options API 存在的问题!
2、功能比较发杂的组件,vue3中还可以自定义 hooks, 将单个功能封装成单个的函数,在集成到组件中去复用! 将功能进行解耦,方便维护、复用、可读性强!
3、想让Composition API 发挥出自己的威力! 需得借助hook函数!
4、hook就是把所有得方法、函数、计算属性、监听属性、数据、生命周期按照功能点进行打包, 打出来的包就是一个 hook函数!
5、更加优雅的组织我们的代码,函数。让相关功能的代码更加有序的组织在一起。42.shallowReactive和shallowRef的区别?
shallowRef:只处理基本数据类型的响应式, 不进行对象的响应式处理。43.provide与inject如何使用?
provide() {
return {
name: 'Vue',
handleClick: this.handleClick
}
},
methods: {
handleClick() {
console.log('Hello Vue!')
}
}
inject: ['name', 'handleClick'],
mounted() {
console.log(this.name) // 输出 'Vue'
this.handleClick() // 输出 'Hello Vue!'
}
44.toRaw 与 markRaw是什么作用?
<template>
<div>
<p>姓名:{{ person.name }}</p>
<p>年龄:{{ person.age }}</p>
<p>爱好:{{ person.like }}</p>
<button @click="changemR">点我markerRaw 标记一个对象,使其永远不会再成为响应式对象</button>
<br>
<button @click="updateToRaw">测试toRaw 将一个由reactive生成的响应式对象 转为普通对象</button>
</div>
</template>
<script setup>
import { reactive, markRaw, toRaw } from 'vue'
const person = reactive({
name: '露丝',
age: 20
})
let likes = ['js', 'css', 'vue']
person.like = markRaw(likes)
const changemR = () => {
person.like[0] = '我爱学习' //变了,但是不是响应式的,打印出来有变化,但是页面没有渲染
console.log(person.like);
}
// toraw
const updateToRaw = () => {
const user = toRaw(person)
user.name = '我是tworaw 之后的名字'
console.log(user, 'user')
}
</script>
45.readonly 与 shallowReadonly谈谈你对他的理解?
readonly与shallowReadonly都是让响应式数据只具备读的能力,后者是浅层次的只读,也就是只对数据对象第一层起作用,深层次的嵌套,当使用shallowReadonly()处理时,深层次数据支持被修改46.自定义hook是什么?
47.虚拟DOM一定更快吗?
原因:虚拟DOM渲染是将真实DOM转为js对象,然后将js对象转换为真实DOM,也就是是说他始终会创建DOM对象。在vue应用初次加载时,需要优先创建所有的虚拟DOM,然后在把虚拟DOM全部转换为真实DOM,消耗的时间一定会比直接渲染真实DOM更多的。48.vue路由中,history和hash两种模式有什么区别?
1、hash模式:
HashHistory.push()会将新的路由添加到浏览器访问的历史的栈顶,而HasHistory.replace()会替换到当前栈顶的路由
49.请谈谈wxml与标准的html的异同?
WXML(2view,text,image,navigator)
WXML :< navigator url=“/pages/home/home”>< /navigator>
WXML可以通过上述模板语法快速实现一些功能50.请谈谈WXSS和CSS的异同?
51.请谈谈微信小程序主要目录和文件的作用?
52.请谈谈小程序的双向绑定和vue的异同?
53.简单描述下微信小程序的相关文件类型?
主要文件{
"pages": [
"pages/index/index",
"pages/logs/logs",
"pages/my/index"
],
"window": {
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#000000",
"navigationBarTitleText": "我是微信小程序", //头部
"navigationBarTextStyle": "white"
},
"tabBar": {
"color": "#333",
"selectedColor": "#FFA500", //选中后的颜色
"list": [
{
"pagePath": "pages/index/index", //路径
"text": "首页", //导航栏标签
"iconPath": "static/baihome.jpg", //未选择的背景图
"selectedIconPath": "static/heihome.jpg" //选中后的背景图
},
{
"pagePath": "pages/logs/logs",
"text": "日志",
"iconPath": "static/rizhiwei.jpg",
"selectedIconPath": "static/rizhidianji.jpg"
},
{
"pagePath": "pages/my/index",
"text": "我的",
"iconPath": "static/mywei.jpg",
"selectedIconPath": "static/mydianji.jpg"
}
]
},
"style": "v2",
"sitemapLocation": "sitemap.json"
}
54.微信小程序有哪些传值(传递数据)方法?
55.bindtap和catchtap的区别?
catchtap是绑定捕获事件,当用户点击元素时触发,但是它会先于冒泡事件被触发,这可以用来阻止冒泡事件的触发。56.简述wx.navigateTo(),wx.redirectTo(),wx.switchTab(),wx.navigateBack(),wx.reLaunch()的区别?
wx.redirectTo():关闭当前页面,跳转到应用内的某个页面。但是不能跳转 tabbar 页面
wx.switchTab():跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面
wx.navigateBack():关闭当前页面,返回上一页面或多级页面。可通过 getCurrentPages() 获取当前的页面栈,决定需要返回几层
wx.reLaunch():关闭所有页面,打开到应用内的某个页面57.微信小程序与H5的区别?
58.小程序和Vue写法的区别?
在页面加载请求数据时,两者钩子的使用有些类似,vue一般会在 created或者 mounted中请求数据,而在小程序,会在 onLoad或者 onShow中请求数据。
vue动态绑定一个变量的值为元素的某个属性的时候,会在变量前面加上冒号。小程序:绑定某个变量的值为元素属性时,会用两个大括号括起来,如果不加括号,为被认为是字符串。
vue中,使用 v-if 和 v-show控制元素的显示和隐藏。小程序中,使用 wx-if和 hidden控制元素的显示和隐藏。
vue:使用 v-on:event绑定事件,或者使用 @event绑定事件;小程序中,全用 bindtap=“”,或者 catchtap=‘’绑定事件,catchtap阻止事件冒泡。
在vue中,只需要在表单元素上加上 v-model,然后再绑定 data中对应的一个值,当表单元素内容发生变化时, data中对应的值也会相应改变。在小程序中,当表单内容发生变化时,会触发表单元素上绑定的方法,然后在该方法中,通过 this.setData({key:value})来将表单上的值赋值给 data中的对应值。
在vue中,绑定事件传参只需要在触发事件的方法中,把需要传递的数据作为形参传入。在小程序中,不能直接在绑定事件的方法中传入参数,需要将参数作为属性值,绑定到元素上的 data-属性上,然后在方法中通过 e.currentTarget.dataset.*的方式获取,从而完成参数的传递。
1、编写子组件;
2、在需要使用的父组件中通过 import引入;
3、在 vue的 components中注册;
4、在模板中使用。
1、编写子组件
2、在子组件的 json文件中,将该文件声明为组件;
3、在需要引入的父组件的 json文件中,在 usingComponents填写引入组件的组件名以及路径;
4、在父组件中,直接引入即可;
父组件向子组件传递数据,只需要在子组件通过 v-bind传入一个值,在子组件中,通过 props接收,即可完成数据的传递,子组件和父组件通信可以通过 this.emit将方法和数据传递给父组件。
父组件直接将值赋值给一个变量,在子组件 properties中,接收传递的值。
小程序是给子组件添加 id或者 class,然后通过 this.selectComponent找到子组件,然后再调用子组件的方法。59.rpx的理解?
60.微信小程序可以进行dom操作吗?
为什么要这样设计?
因为JavaScript是可操纵DOM的,如果JavaScript线程和UI线程同时运行,即在修改这些元素属性同时渲染界面,那么渲染线程前后获得的元素数据就可能不一致,导致传统web开发渲染线程和脚本线程是互斥的。于是当JavaScript引擎执行时GUI线程会被挂起,GUI更新会被保存在一个队列中等到引擎线程空闲时立即被执行。 因此长时间的脚本运行可能会导致页面失去响应。61.微信小程序自定义tabbar的理解?
一、微信小程序自定义tabbar配置
custom-tab-bar/index
62.微信小程序怎么缓存数据?
success:异步接口调用成功的回调函数
fail:异步接口调用失败的回调函数
complete:异步接口调用结束的回调函数,无论成功失败都会执行63.微信小程序怎么进行网络请求?
登录微信小程序管理后台添加链接描述> 开发 -> 开发设置 -> 服务器域名 -> 修改 request 合法域名
注意:
① 域名只支持 https 协议
② 域名不能使用 IP 地址或 localhost
③ 域名必须经过 ICP 备案
④ 服务器域名一个月内最多可申请 5 次修改
微信小程序支持GET,POST等请求。用method可以设置.
微信小程序提供了 wx.request(Object object) 这个API,用于发送网络请求,该API接受一个对象作为参数,该对象包含多个属性,其中常用的有:
data,请求的参数,可以是一个字符串或一个对象,非必填。
method,请求的方法,string类型,默认值是"GET"。
success,请求成功的回调函数,非必填。
fail,请求失败的回调函数,非必填。
调用微信小程序提供的 wx.request() 方法,可以发起 GET 数据请求.getInfo(){
vxwx.request({
url: 'https://www.escook.cn/api/get',
method:'GET',
data:{
name: 'zs',
age:20
},
success:(res) => {
console.log(res.data)
}
})
},
getInfo(){
vxwx.request({
url: 'https://www.escook.cn/api/get',
method:'POST',
data:{
name: 'zs',
age:20
},
success:(res) => {
console.log(res.data)
}
})
}
可以在时间onload中定义fuction,调用get\post网络请求onload: funtion(e){
postInfo();
getInfo()
}
postInfo(){
}
getInfo(){
}
跨域问题只存在于基于浏览器的 Web 开发中。由于小程序的宿主环境不是浏览器,而是微信客户端,所以小
程序中不存在跨域的问题。
Ajax 技术的核心是依赖于浏览器中的 XMLHttpRequest 这个对象,由于小程序的宿主环境是微信客户端,所
以小程序中不能叫做“发起 Ajax 请求”,而是叫做“发起网络数据请求”64.微信小程序路由跳转以及传参如何实现?
跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面,路径后不能带参数。
关闭所有页面,打开到应用内的某个页面。
需要跳转的应用内非 tabBar 的页面的路径 (代码包路径), 路径后可以带参数。参数与路径之间使用 ? 分隔,参数键与参数值用 = 相连,不同参数用 & 分隔。
关闭当前页面,跳转到应用内的某个页面。但是不允许跳转到 tabbar 页面。可传参
保留当前页面,跳转到应用内的某个页面。但是不能跳到 tabbar 页面。使用 wx.navigateBack 可以返回到原页面。小程序中页面栈最多十层。
关闭当前页面,返回上一页面或多级页面。可通过 getCurrentPages 获取当前的页面栈,决定需要返回几层。不可路径传参,其他都可。// 第一种传参方式:字符串拼接 路径 ? 参数1=值 & 参数2=值 & 参数3=值
toShopCar(){
wx.navigateTo({
url:'/pages/pay/pay?username='+this.data.form.username+'&goodsNum='+this.data.form.goodsNum
})
}
// 第二种传参方式:模板字符串 路径 ? 参数1=${值} & 参数2=${值}
toShopCar(){
wx.navigateTo({
url:`/pages/pay/pay?username=${this.data.form.username}&goodsNum=${this.data.form.goodsNum}`
})
}
65.微信小程序生命周期的理解?
应用生命周期
(1)onLaunch: 初始化小程序时触发,全局只触发一次
(2)onShow: 小程序初始化完成或用户从后台切换到前台显示时触发
(3)onHide: 用户从前台切换到后台隐藏时触发
(4)onError: 小程序发生脚本错误,或者 api 调用失败时,会触发 onError 并带上错误信息
后台: 点击左上角关闭,或者按了设备 Home 键离开微信,并没有直接销毁,而是进入后台
前台:再次进入微信或再次打开小程序,相当于从后台进入前台。
(1)onLoad:首次进入页面加载时触发,可以在 onLoad 的参数中获取打开当前页面路径中的参数。
(2)onShow:加载完成后、后台切到前台或重新进入页面时触发
(3)onReady:页面首次渲染完成时触发
(4)onHide:从前台切到后台或进入其他页面触发
(5)onUnload:页面卸载时触发
attached(重要):在组件完全初始化完毕、进入页面节点树后被触发
ready:在组件在视图层布局完成后执行
moved:在组件实例被移动到节点树另一个位置时执行
detached(重要):在组件离开页面节点树后被触发
error:每当组件方法抛出错误时执行66.微信小程序模块化?
67.微信小程序所有api放在哪里,简单介绍几个api?
事件监听API 同步API 异步API
例如:wx.onWindowResize(function callback)用来监听窗口尺寸大小的变化
例如:wx.setStorageSync(‘key’,‘value’)向本地存储中写入内容
例如:wx.request(),发起网络请求,通过success回调函数接受数据。68.微信小程序应用和页面生命周期触发顺序?
69.微信小程序如何使用sass预编译?
"setting": {
...,
"useCompilerPlugins": [
"sass"
],
}
70.微信小程序开发文档界面都有哪些操作,列举几项?
71.微信小程序自定义组件的使用?
72.微信小程序事件通道的使用?
通过事件通道,一个页面或组件可以向事件通道发送一个事件,其他页面或组件可以通过监听该事件来获取消息并进行相应处理。App({
onLaunch() {
this.eventChannel = this.getEventChannelForPage();
},
})
wx.navigateTo({
url: '/pages/targetPage/index',
events: {
someEvent: data => {
// 收到事件,并执行相应操作
}
}
});
onLoad(options) {
const eventChannel = this.getOpenerEventChannel();
eventChannel.on('someEvent', data => {
// 处理事件
});
}
// 触发事件
this.eventChannel.emit('someEvent', data);
73.微信小程序如何使用vant组件库?
大家打开网站后,点击快速上手。上面就有步骤教你如何在小程序中使用vant组件库。
然后给大家介绍一下怎么使用组件库的,(其他的组件库依然可以使用)
npm init 需要验证,一直回车,之后才能初始化
npm init -y 不需要验证,直接初始化
4. 安装依赖 (直接复制安装即可)
4.1 通过 npm 安装vant/weappnpm i @vant/weapp -S --production
npm i miniprogram-sm-crypto --production
4.3 修改 app.json{
...
"setting": {
...
"packNpmManually": flase,
"packNpmRelationList": [
{
"packageJsonPath": "./package.json",
"miniprogramNpmDistDir": "./miniprogram/"
}
]
}
}
构建成功后会出现下面的画面
"usingComponents": {
"vant-button":"@vant/weapp/button/index",
"Tabs":"./components/tabs/tabs"
}
在wxml中:
在页面中的显示
我们就完成了74.微信小程序自定义组件父传子子传父?
因为在前面我们写了自定义组件,所以我们就当他是子组件
子向父传递数据,通过事件的方式传递
<button type="primary" bindtap="addInfo">确定</button>
addInfo(){
let item = {title:'测试',money:8,category:'吃饭'}//要传给父组件的参数
this.triggerEvent('addInfo',item)//通过triggerEvent将参数传给父组件
},
<add-item nowAddDate="{{isShowAdd}}" bind:addInfo="getAddInfo"></add-item>
getAddInfo(e){
console.log(e.detail)//{title:'测试',money:8,category:'吃饭'}
},
75.微信小程序自定义组件生命周期有哪些?
attached:在组件实例进入页面节点树时执行
ready:在组件在视图层布局完成后执行
moved :在组件实例被移动到节点树另一个位置时执行
detached:在组件实例被从页面节点树移除时执行
error:每当组件方法抛出错误时执行
此时不能调用setData,只能添加一些自定义的属性字段
此时,this.data初始化完毕,数据初始化的操作可以在此操作
退出页面时触发,可以做一些清理数据方面的操作76.微信小程序授权登录流程?
刚开始,我把login页当作了小程序的首页,这样导致如果已经授权过,这个页面也会一闪而过。用户体验不好。捋了一下思路之后认为,应该把授权的判断放在app.js中onLaunch生命周期里,首页还是正常的index页面。
若已经授权,获取用户信息,存在全局的data里,若没有授权,跳转到login页,进行授权操作77.web-view
<web-view src="https://www.itlao5.com"></web-view>
Page({
onShareAppMessage(options) {
console.log(options.webViewUrl)
}
})