前端成长仔一枚,最近的一个项目中,遇到了一个bug,虽然不是很大,但是足够灵异。借此记录一下。
项目背景:项目首页使用的el-tree和el-tab-pane,没有使用路由,全部在一个根路由下由v-if控制显示。实习小白也不懂为什么这样,但是入乡随俗,我新增页面、tree结构和tab页的时候也用的这种方式。(事实证明,跟着前辈走方便又快捷。之前不信邪,非得用路由跳转,纠结到心脏病发,熬夜到十二点也解决不了问题)。
问题背景:本来欢快的使用v-if控制页面显示足够,但是产品提出新的需求,在A页面中设置按钮,点击按钮的时候可以新增一个tab展示B页面,并且将参数带过去。
解决办法一:不用路使用eventBus,由于A、B页面毫无关系,建立一个bus.js,用$emit传递要携带的参数,新打开的页面使用$on接收。
新建一个eventBus文件,取名为bus.js用于接收数据。
import Vue from "vue"
export default new Vue()
发送数据的组件在methods方法中新增方法:
import bus from "./bus.js"
methods:{
//发送的是单个数据时:
sendFormData(){
bus.$emit("dataName", dataValue)
}
//发送的是多个数据时:
sendFormData(){
bus.$emit("dataName", dataValue1, dataValue2)
}
}
接收数据的组件在methods方法中新增方法为:
import bus from "./bus"
methods:{
recvFormData(){
//接收单个数据
bus.$on("dataName",msg=>{
console.log(msg)
})
}
//接收多个数据:
在template中的写法为:@recvFormData=recvFormData(arguments)
recvFormData(values){
bus.$on("dataName",values=>{
console.log(values)
})
}
}
然鹅,$emit传递的时候,那边新的页面已经在created周期中了,$on接收不到。看过网友的建议后,可以将$emit写在beforeDestroy阶段,好死不死,该需求就是在关闭 B的tab页面还能回到A的tab页面。该方法不行。
解决办法二:使用路由携带参数跳转。直接在根目录下创建新的children。然而,由于element-ui新增标签页给定的代码中写死了tab的content内容部分且是字符串的形式。如下:
methods: {
addTab(targetName) {
let newTabName = ++this.tabIndex + '';
this.editableTabs.push({
title: 'New Tab',
name: newTabName,
content: 'New Tab content'
});
this.editableTabsValue = newTabName;
},
}
首先,要将content设置为组件的形式,才能将新的页面传递进去。
改写content的方式:
1、引入要展示的组件:
import Admin from "@/components/views/Admin.vue"2、将addTab方法中的content字段的值改为组件名字:
methods: { addTab(targetName) { let newTabName = ++this.tabIndex + ''; this.editableTabs.push({ title: 'New Tab', name: newTabName, content:"Admin" }); this.editableTabsValue = newTabName; }, }完成。
也是因为这种方式,当我们的路由从A页面跳转的时候,会展示Admin组件中的内容。为了避免内容的重复,可以将这个组件设为一个空组件。便可解决问题,这是一个投机取巧得方式,更加优化得方式有待学习。
由于解决办法二过于妖娆(繁琐),所以想到了可以用vuex做传值。
解决办法三:使用vuex,将要携带的参数写在state中。在A组件中点击按钮新增tab页面的同时,使用mutations修改state中的值。在module中新建一个js文件并设置命名空间namespaced:true。
(如果项目不大,可以不建模块。)
const state={
dataName1:"",
dataName2:"",
}
const mutations={
changeData1(state,value){
state.dataName1=value,
},
changeData2(state, value){
state.dataName2=value
}
}
const actions={
//一些异步调用
funtion1(){
return new Promise((resolve,reject)=>{...})
}
}
export default{
namespaced:true,
state,
mutations,
actions
}
在A页面中,引入vuex仓库中的state和mutations,修改state中的值。
import {mapState, mapMutations} form "vuex"
export default{
comoputed(){
...mapState('name',["dataName1", "dataName2"])
}
methods:{
...mapMutations("name",["changeData1", "changeData2"])
//具体的业务逻辑代码(也就是点击事件)
clickFn(){
this.changeData1(value1)
this.changeData2(value2)
}
}
}
在B页面中,如果B页面只被调用这一次,则可以不引入mutations,在本业务逻辑中,其他地方还需使用B页面,并且相应的参数为默认值,因此我的写法为:
import {mapState, mapMutations} from "vuex"
export default{
computed(){
...mapState("name", ["dataName1","dataName2"])
}
mounted(){
this.localData1 = this.dataName1
this.localData2 = this.dataName2
},
/*由于其他页面会调用该页面,因此在这个页面离开时,要将vuex的值设为空,
以免其他情况下的数据受到影响*/
beforeDestroy(){
this.changeData1("")
this.changeData2("")
},
methods:{
...mapMutations("name", ["changeData1", "changeData2"])
}
}
我正在使用i18n从头开始构建一个多语言网络应用程序,虽然我自己可以处理一大堆yml文件,但我说的语言(非常)有限,最终我想寻求外部帮助帮助。我想知道这里是否有人在使用UI插件/gem(与django上的django-rosetta不同)来处理多个翻译器,其中一些翻译器不愿意或无法处理存储库中的100多个文件,处理语言数据。谢谢&问候,安德拉斯(如果您已经在rubyonrails-talk上遇到了这个问题,我们深表歉意) 最佳答案 有一个rails3branchofthetolkgem在github上。您可以通过在Gemfi
exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby中使用两个参数异步运行exe吗?我已经尝试过ruby命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何rubygems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除
我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere
我正在为一个项目制作一个简单的shell,我希望像在Bash中一样解析参数字符串。foobar"helloworld"fooz应该变成:["foo","bar","helloworld","fooz"]等等。到目前为止,我一直在使用CSV::parse_line,将列分隔符设置为""和.compact输出。问题是我现在必须选择是要支持单引号还是双引号。CSV不支持超过一个分隔符。Python有一个名为shlex的模块:>>>shlex.split("Test'helloworld'foo")['Test','helloworld','foo']>>>shlex.split('Test"
我不确定传递给方法的对象的类型是否正确。我可能会将一个字符串传递给一个只能处理整数的函数。某种运行时保证怎么样?我看不到比以下更好的选择:defsomeFixNumMangler(input)raise"wrongtype:integerrequired"unlessinput.class==FixNumother_stuffend有更好的选择吗? 最佳答案 使用Kernel#Integer在使用之前转换输入的方法。当无法以任何合理的方式将输入转换为整数时,它将引发ArgumentError。defmy_method(number)
两者都可以defsetup(options={})options.reverse_merge:size=>25,:velocity=>10end和defsetup(options={}){:size=>25,:velocity=>10}.merge(options)end在方法的参数中分配默认值。问题是:哪个更好?您更愿意使用哪一个?在性能、代码可读性或其他方面有什么不同吗?编辑:我无意中添加了bang(!)...并不是要询问nobang方法与bang方法之间的区别 最佳答案 我倾向于使用reverse_merge方法:option
CSV.open(name,"r").eachdo|row|putsrowend我得到以下错误:CSV::MalformedCSVErrorUnquotedfieldsdonotallow\ror\n文件名是一个.txt制表符分隔文件。我是专门做的。我有一个.csv文件,我转到excel,并将文件保存为.txt制表符分隔的文件。所以它是制表符分隔的。CSV.open不应该能够读取制表符分隔的文件吗? 最佳答案 尝试像这样指定字段分隔符:CSV.open("name","r",{:col_sep=>"\t"}).eachdo|row|
我有一个只接受一个参数的方法:defmy_method(number)end如果使用number调用方法,我该如何引发错误??通常,我如何定义方法参数的条件?比如我想在调用的时候报错:my_method(1) 最佳答案 您可以添加guard在函数的开头,如果参数无效则引发异常。例如:defmy_method(number)failArgumentError,"Inputshouldbegreaterthanorequalto2"ifnumbereputse.messageend#=>Inputshouldbegreaterthano
我没有找到太多关于如何执行此操作的信息,尽管有很多关于如何使用像这样的redirect_to将参数传递给重定向的建议:action=>'something',:controller=>'something'在我的应用程序中,我在路由文件中有以下内容match'profile'=>'User#show'我的表演Action是这样的defshow@user=User.find(params[:user])@title=@user.first_nameend重定向发生在同一个用户Controller中,就像这样defregister@title="Registration"@user=Use
对于作为String#tr参数的单引号字符串文字中反斜杠的转义状态,我觉得有些神秘。你能解释一下下面三个例子之间的对比吗?我特别不明白第二个。为了避免复杂化,我在这里使用了'd',在双引号中转义时不会改变含义("\d"="d")。'\\'.tr('\\','x')#=>"x"'\\'.tr('\\d','x')#=>"\\"'\\'.tr('\\\d','x')#=>"x" 最佳答案 在tr中转义tr的第一个参数非常类似于正则表达式中的括号字符分组。您可以在表达式的开头使用^来否定匹配(替换任何不匹配的内容)并使用例如a-f来匹配一