1.EventBus注册在全局时,路由切换时会重复触发事件,如何解决?
添加Bus.$off
来关闭。
beforeDestroy () {
bus.$off('get', this.myhandle)
},
所以,如果想要用bus 来进行页面组件之间的数据传递,需要注意亮点,组件$emit
事件应在beforeDestory生命周期内。其次,组件B内的$on记得要销毁。
2.怎么修改Vue打包后生成的文件路径?
使用vue-cli生成的项目,打包方式是直接执行package.json里配置的脚本
npm run build
// 这步其实是去执行build下的build.js脚本文件
node build/build.js
只需要修改config文件夹下的生产环境配置文件prod.env.js。
// 我们只需要修改编译后的环境,所以只要修改prod.env.js下的build属性下的assetsPublicPath属性
// 默认值是 "/" 根目录
// 我这里加了一级 "/mywebsite/"
// 最终页面上请求到的静态资源路径,比如css文件的地址就是:
http://www.***.cn/mywebsite/static/css/index****.css
3.Vue和原生app交互的方法?
0.通过url传输数据:(一般是在入口页面传下app的用户信息进来供vue h6使用)
methods: {
// 接收url后的数据
urltext() {
let loc = location.href; 6 let n1 = loc.length;//地址的总长度
let n2 = loc.indexOf(“=”);//取得=号的位置
let outToken = loc.substr(n2 + 1, n1 - n2);//从=号后面的内容
console.log(loc,n1,n2,outToken)
this.outTokenPost(outToken) //传到处理函数
},
}
1.原生APP提供一个接口对象的引用(例如一个扫码的接口,可能还有回调函数以获得扫码结果)
思路就是万物通过window 进行交互
// 将vue组件的要回调的函数暴露出去
mounted:function(){
// 将subscanQRCallBack方法绑定到window下面,提供给外部调用
window['scanQRCallBack'] = (result) => {
this.subscanQRCallBack(result)
}
},
methods:{
scan(){
// alert('开始扫码了')
window.client.startScanQR('OS与js交互',scanQRCallBack) // 通过window调用app提供的client对象
},
subscanQRCallBack(result){
// alert('扫码结果6466:'+result);
this.scanPost(result)
},
}
由交互引发的对vue生命周期的思考
开发时遇到一个经典问题,需要在页面刚载入时与app交互判断是否显示一个弹窗。看似很简单,进入页面调一个交互方法即可,但这个需求的解决经历了几个步骤:
1、created
因为created时,实例就创建完成了,我开始的选择是在此生命周期挂载方法并调用交互,结果:页面闪退,猜测:实例虽有,但模板未编译挂载,app调用方法失败导致闪退
2、mounted
第二次将挂载和调用写在了mounted内,结果:页面闪退,猜测(误):挂载和调用靠的太近,可能方法未挂载完就直接调用,导致闪退
3、created+mounted
created内挂载方法,mounted内调用交互,结果:我的ios12无异常,几乎以为成功时,ios10还是发生了闪退,猜测ios12的webview对此问题进行了优化,考虑兼容性,方案不可行。
4、延时
猜测是window没有加载完便调用了window下的方法,导致闪退,对交互方法加了1s延时,成功!但体验一般,因为硬性的定时容易引发许多不可控的问题,而且弹窗延时的存在导致用户体验低下。
5、window.onload
onload 事件会在页面或图像加载完成后立即发生。mounted钩子里添加代码window.οnlοad=function(){//调用交互},在window加载完成以后触发交互,而且此时间节点在vue的生命周期是不存在的,也是在mounted、created钩子后发生的,这个原生的方法还是很棒的,完美解决~
4.使用Vue做一个tab切换。
思路
1、采用 v-show 指令,设置 隐藏的状态值
2、切换的标题,绑定点击事件 @cilick=handleTabs(index)
,点击标题索引绑定到隐藏状态值。
代码如下:
<template>
<div>
<div v-for="(item,index) in muenlist" :key="index" @click="handleTabs(index)">{{ item }}</div>
<div v-show="tableIndex === 0">页面A的内容 </div>
<div v-show="tableIndex === 1">页面B的内容</div>
<div>
</template>
<script>
export default {
data() {
muenlist: ['页面A', '页面B'],
tableIndex: 0,
},
methods: {
// tab切换
handleTabs(index) {
this.tableIndex = index
},
}
}
</script>
5,Vue里什么是递归组件?举个例子
递归组件 ,顾名思义,就 是 自己的内部实现又调用自己的 组件 。 比如 Vue 官方给的treeView的 例子 ,父目录 下 有子目录,子目录 下 还有子目录,子子孙孙,无穷尽也。
首先为了使用递归组件需要准备一份数据,因为这次是生成一个菜单,所以准备一个菜单书数据,新建一个testdata.js 文件代码如下
var demoData = [
{
'id': '1',
'menuName': '基础管理',
'menuCode': '10',
'children': [
{
'menuName': '用户管理',
'menuCode': '11'
},
{
'menuName': '角色管理',
'menuCode': '12',
'children': [
{
'menuName': '管理员',
'menuCode': '121'
},
{
'menuName': 'CEO',
'menuCode': '122'
},
{
'menuName': 'CFO',
'menuCode': '123'
},
{
'menuName': 'COO',
'menuCode': '124'
},
{
'menuName': '普通人',
'menuCode': '124'
}
]
},
{
'menuName': '权限管理',
'menuCode': '13'
}
]
},
{
'id': '2',
'menuName': '商品管理',
'menuCode': ''
},
{
'id': '3',
'menuName': '订单管理',
'menuCode': '30',
'children': [
{
'menuName': '订单列表',
'menuCode': '31'
},
{
'menuName': '退货列表',
'menuCode': '32',
'children': []
}
]
},
{
'id': '4',
'menuName': '商家管理',
'menuCode': '',
'children': []
}
];
export default demoData;
这是使用时 ES6 语法,导出一个数据,所以这里必须注意 ES6 导出的语法,如果不清楚 ES6 的语法自行了解.
建立树形组件
现在建立树形组件,首先新建一个文件treeMenu,代码如下
<template>
<li>
<span @click="toggle">
<i v-if="hasChild" class="icon" v-bind:class="[open ? 'folder-open': 'folder' ]"></i>
<i v-if="!hasChild" class="icon file-text"></i>
{{model.menuName}}
</span>
<ul v-show="open" v-if="hasChild">
<tree-menu v-for="(item,index) in model.children" v-bind:model="item" v-bind:key="index"></tree-menu>
</ul>
</li>
</template>
<script>
export default {
name: "treeMenu",
props: ['model'],
data(){
return {
open:false
}
},
computed:{
hasChild(){
return this.model.children && this.model.children.length
}
},
methods:{
toggle(){
if(this.hasChild){
this.open = !this.open
}
}
}
}
</script>
<style>
ul {
list-style: none;
margin: 10px 0;
}
li {
padding: 3px 0;
}
li > span {
cursor: pointer;
font-size: 14px;
line-height: 20px;
}
i.icon {
display: inline-block;
width: 20px;
height: 20px;
margin-right: 5px;
background-repeat: no-repeat;
vertical-align: middle;
}
.icon.folder {
background-image: url(/src/assets/folder.png);
}
.icon.folder-open {
background-image: url(/src/assets/folder-open.png);
}
.icon.file-text {
background-image: url(/src/assets/file-text.png);
}
.tree-menu li {
line-height: 1.5;
}
</style>
上述代码中我们需要注意,这个组件必须含有 name 这个属性,因为没有 name 这个属性会造成控件自身不能调用自身,自身调用的时候最好有绑定 key ,因为这个 key 是唯一的标识,对于 vue 更新控件比较好.除非控件非常简单就不用 key.
另外一个需要注意就是递归组件时候,需要有一个条件来终止递归,在这里使用 v-for 隐形条件终止递归. props 这个属性其实主要传递父控件的数据的参数,具体用法可以参详 vue 的官方文档.
sidebar 控件
新建一个 sidebar 控件,代码如下
<template>
<div class="tree-menu">
<ul v-for="menuItem in theModel">
<my-tree :model="menuItem"></my-tree>
</ul>
</div>
</template>
<script>
import testData from './testdata';
import myTree from './treeMenu';
export default {
name: "side-bar",
components: {
myTree
},
data() {
return {
theModel: testData
}
}
}
</script>
在把该 sidebar 组件添加到 HelloWorld.vue 中,成功后如下图:
成功后会出现如下图的