• Vue开发中常见问题记录


    1、vue-router 中使用 vuex

    首先确保 main.js 中组合了 vuex 和 router

    1. Vue.use(VueRouter)
    2. Vue.use(Vuex)
    3. new Vue({
    4. el: '#app',
    5. router: createVueRouter(VueRouter),
    6. store: createVueStore(Vuex),
    7. render: h => h(App)
    8. })
    9. 复制代码

    router.js 中可以直接使用 router.app.$options.store

    1. let be4Each = function(router) {
    2. router.beforeEach((to, from, next) => {
    3. router.app.$options.store.dispatch('handleDoSomething').then((i) => {
    4. // doSomething
    5. next();
    6. });
    7. });
    8. }
    9. let createVueRouter = function(VueRouter) {
    10. let router = new VueRouter(routerConfig)
    11. be4Each(router)
    12. afterEach(router)
    13. return router
    14. }
    15. export default createVueRouter;
    16. 复制代码

    2、vue组件中js定义的本地图片在页面无法显示

    本地图片直接放到img标签中是可以展示的;但是通过js引入到img标签中,是无法展示的,需要通过require才能展示 assets文件夹下的图片photo.png 本地图片直接在img标签中使用

    1. //图片可以显示
    2. <img  src="@/assets/photo.png"  />
    3. 复制代码

    js中的本地图片需要使用require才能显示

    1. //图片不能显示
    2. <img  :src="pic"  />
    3. //图片可以显示
    4. <img  :src="img"  />
    5. 复制代码
    1. data( ){
    2. return {
    3. pic:'@/assets/photo.png'
    4. img:require('@/assets/photo.png')
    5. }
    6. }
    7. 复制代码

    3、vue build 过程取消 console、debugger 控制台信息输出

    一、前言

    Vue项目开发过程中,会经常需要使用console.log、console.info、alert等测试语句来输出内容,而在生产环境之中,我们不希望控制台同样输出以上信息,特别是用户信息相关。

    打包前,逐一去删除、注释显然费时费力,好在Vue提供了通过配置文件修改配置变量,实现在开发环境打印,而生产环境不打印控制台信息的方法。

    二、配置文件修改

    修改build/webpack.prod.conf.js配置文件,找到UglifyJsPlugin配置,在compress中添加如下代码即可。

    1. new UglifyJsPlugin({
    2. uglifyOptions: {
    3. compress: {
    4. warnings: false,
    5. // 打包的时候移除console、debugger
    6. drop_debugger: true, // 移除debugger
    7. drop_console: true, // 移除console
    8. pure_funcs: ['console.log','console.info']
    9. }
    10. },
    11. sourceMap: config.build.productionSourceMap,
    12. parallel: true
    13. }),
    14. 复制代码

    优化配置方式如下:

    1. new UglifyJsPlugin({
    2. uglifyOptions: {
    3. compress: {
    4. warnings: false,
    5. // 打包的时候移除console、debugger
    6. drop_debugger: process.env.NODE_ENV=== 'production', // 移除debugger
    7. drop_console: process.env.NODE_ENV=== 'production', // 移除console
    8. warnings: process.env.NODE_ENV=== 'production', // 移除告警信息
    9. pure_funcs: ['console.log','console.info']
    10. }
    11. },
    12. sourceMap: config.build.productionSourceMap,
    13. parallel: true
    14. }),
    15. 复制代码

    其中,process.env.NODE_ENV定义在prod.env.js文件中,

    1. module.exports = {
    2. NODE_ENV: "production"
    3. }
    4. 复制代码

    prod.env.js文件在config/index.jsbuild.env配置中引入。

    1. build: {
    2. env: require('./prod.env')
    3. }
    4. 复制代码

    4、vue-cli 脚手架 webpack.base.conf.js 配置文件讲解

    一、前言

    webpack.base.conf.js 文件是vue开发环境和生产环境wepack相关配置文件,主要用来处理各种文件的配置。

    1. // 引入nodejs路径模块
    2. var path = require('path')
    3. // 引入utils工具模块,utils主要用来处理css-loader和vue-style-loader的
    4. var utils = require('./utils')
    5. // 引入config目录下的index.js配置文件,主要用来定义一些开发和生产环境的属性
    6. var config = require('../config')
    7. // vue-loader.conf配置文件是用来解决各种css文件的,定义了诸如css,less,sass之类的和样式有关的loader
    8. var vueLoaderConfig = require('./vue-loader.conf')
    9. // 此函数是用来返回当前目录的平行目录的路径,因为有个'..'
    10. function resolve (dir) {
    11. return path.join(__dirname, '..', dir)
    12. }
    13. module.exports = {
    14. entry: {
    15. // 入口文件是src目录下的main.js
    16. app: './src/main.js'
    17. },
    18. output: {
    19. // 路径是config目录下的index.js中的build配置中的assetsRoot,也就是dist目录
    20. path: config.build.assetsRoot,
    21. // 文件名称这里使用默认的name也就是main
    22. filename: '[name].js',
    23. // 上线地址,也就是真正的文件引用路径,如果是production生产环境,其实这里都是 '/'
    24. publicPath: process.env.NODE_ENV === 'production'
    25. ? config.build.assetsPublicPath
    26. : config.dev.assetsPublicPath
    27. },
    28. resolve: {
    29. // resolve是webpack的内置选项,顾名思义,决定要做的事情,也就是说当使用 import "jquery",该如何去执行这件事
    30. // 情就是resolve配置项要做的,import jQuery from "./additional/dist/js/jquery" 这样会很麻烦,可以起个别名简化操作
    31. extensions: ['.js', '.vue', '.json'], // 省略扩展名,也就是说.js,.vue,.json文件导入可以省略后缀名,这会覆盖默认的配置,所以要省略扩展名在这里一定要写上
    32. alias: {
    33. //后面的$符号指精确匹配,也就是说只能使用 import vuejs from "vue" 这样的方式导入vue.esm.js文件,不能在后面跟上 vue/vue.js
    34. 'vue$': 'vue/dist/vue.esm.js',
    35. // resolve('src') 其实在这里就是项目根目录中的src目录,使用 import somejs from "@/some.js" 就可以导入指定文件,是不是很高大上
    36. '@': resolve('src')
    37. }
    38. },
    39. // module用来解析不同的模块
    40. module: {
    41. rules: [
    42. {
    43. test: /\.(js|vue)$/,
    44. // 也就是说,对.js和.vue文件在编译之前进行检测,检查有没有语法错误
    45. loader: 'eslint-loader',
    46. // 此选项指定enforce: 'pre'选项可以确保,eslint插件能够在编译之前检测,如果不添加此项,就要把这个配置项放到末尾,确保第一个执行
    47. enforce: 'pre',
    48. // include选项指明这些目录下的文件要被eslint-loader检测,还有一个exclude表示排除某些文件夹
    49. include: [resolve('src'), resolve('test')],
    50. // options表示传递给eslint-loader的参数
    51. options: {
    52. // formatter是参数的名称,eslint-friendly-formatter是eslint的一个报告总结插件,也就是说eslint的检测报告非常难看懂,这个插件就是整理这些报告方便查阅的
    53. formatter: require('eslint-friendly-formatter')
    54. }
    55. },
    56. {
    57. test: /\.vue$/,
    58. // 对vue文件使用vue-loader,该loader是vue单文件组件的实现核心,专门用来解析.vue文件的
    59. loader: 'vue-loader',
    60. // 将vueLoaderConfig当做参数传递给vue-loader,就可以解析文件中的css相关文件
    61. options: vueLoaderConfig
    62. },
    63. {
    64. test: /\.js$/,
    65. // 对js文件使用babel-loader转码,该插件是用来解析es6等代码
    66. loader: 'babel-loader',
    67. // 指明src和test目录下的js文件要使用该loader
    68. include: [resolve('src'), resolve('test')]
    69. },
    70. {
    71. test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
    72. // 对图片相关的文件使用 url-loader 插件,这个插件的作用是将一个足够小的文件生成一个64位的DataURL
    73. // 可能有些老铁还不知道 DataURL 是啥,当一个图片足够小,为了避免单独请求可以把图片的二进制代码变成64位的
    74. // DataURL,使用src加载,也就是把图片当成一串代码,避免请求,神不神奇??
    75. loader: 'url-loader',
    76. options: {
    77. // 限制 10000 个字节一下的图片才使用DataURL
    78. limit: 10000,
    79. name: utils.assetsPath('img/[name].[hash:7].[ext]') // 这个函数执行结果是 /img/[name].[hash:7].[ext]
    80. // 不知道吧 name 设置成 /img/[name].[hash:7].[ext] 意欲何为,猜测应该是输出图片的路径或者是解析图片的路径
    81. }
    82. },
    83. {
    84. test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
    85. // 字体文件处理,和上面一样
    86. loader: 'url-loader',
    87. options: {
    88. limit: 10000,
    89. name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
    90. }
    91. }
    92. ]
    93. }
    94. }
    95. 复制代码

    二、注

    对于文件小于10000byte,在生成的代码用中base64来替代; 大于10000byte,按[name].[hash:7].[ext]的命名方式放到static/img下面,方便做cache; 因为项目中会有动态引入而无法提前通过loader加载的图片,用CopyWebpackPlugin放到dist目录下。所以最后build完的图片资源就是两部分:一部分是dev下的整个图片文件夹(被复制了一份),另外就是经过url-loader处理过的dist/img下带hash的图片。

    5、 实现页面缓存

    一、引入场景

    官网解释: 包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。和 相似, 是一个抽象组件:它自身不会渲染一个 DOM 元素,也不会出现在父组件链中。 当组件在 内被切换,它的 activated 和 deactivated 这两个生命周期钩子函数将会被对应执行。 在 2.2.0 及其更高版本中,activated 和 deactivated 将会在 组件内的所有嵌套组件中触发。 主要用于保留组件状态或避免重新渲染

    二、应用场景

    如果未使用keep-alive组件,则在页面回退时仍然会重新渲染页面,触发created钩子,用户体验不好。 在菜单存在多级关系,多见于列表页+详情页的场景,使用keep-alive组件会显著提高用户体验,如:商品列表页点击商品跳转到商品详情,返回后仍显示原有信息,订单列表跳转到订单详情,返回,等等场景。

    三、keep-alive 生命周期

    初次进入时:created > mounted > activated;退出后触发 deactivated;

    再次进入:会触发 activated;事件挂载的方法等,只执行一次的放在 mounted 中;组件每次进去执行的方法放在 activated 中;

    四、项目实践

    1.更改App.vue

    1. <div id="app" class='wrapper'>
    2. <keep-alive>
    3. <!-- 需要缓存的视图组件 -->
    4. <router-view v-if="$route.meta.keepAlive"></router-view>
    5. </keep-alive>
    6. <!-- 不需要缓存的视图组件 -->
    7. <router-view v-if="!$route.meta.keepAlive"></router-view>
    8. </div>
    9. 复制代码

    2.在路由中设置keepAlive

    1. {
    2. path: 'list',
    3. name: 'itemList', // 商品管理
    4. component (resolve) {
    5. require(['@/pages/item/list'], resolve)
    6. },
    7. meta: {
    8. keepAlive: true,
    9. title: '商品管理'
    10. }
    11. }
    12. 复制代码

    3.更改 beforeEach钩子

    这一步是为了清空无用的页面缓存。 假设现在A、B两个页面都开启的缓存:

    若第一次进入A页面后退出,再次进入页面时,页面不会刷新。这和目前的业务逻辑不符。我们想要的结果是A页面前进后返回,页面保持不变,而不是退出后重新进入保持不变。

    在进入过A页面后进入B页面,经过测试后发现,B页面竟然会显示A页面的缓存,尽管url已经改变。

    为了解决这个问题,需要判断页面是在前进还是后退。 在beforeEach钩子添加代码:

    1. let toDepth = to.path.split('/').length
    2. let fromDepth = from.path.split('/').length
    3. if (toDepth < fromDepth) {
    4. // console.log('back...')
    5. from.meta.keepAlive = false
    6. to.meta.keepAlive = true
    7. }
    8. 复制代码

    五、记录页面滚动位置

    keep-alive并不会记录页面滚动位置,如需在跳转时需要记录当前的滚动位置,可在触发activated钩子时重新定位到原有位置。 具体设计思路:

    deactivated钩子中记录当前滚动位置,使用localStorage

    1. deactivated () {
    2. window.localStorage.setItem(this.key, JSON.stringify({
    3. listScrollTop: this.scrollTop
    4. }))
    5. }
    6. 复制代码

    activated钩子中滚动:

    1. this.cacheData = window.localStorage.getItem(this.key) ?JSON.parse(window.localStorage.getItem(this.key)) : null
    2. $('.sidebar-item').scrollTop(this.cacheData.listScrollTop)
    3. 复制代码

    6、ES数组操作:splice() 实现数组删除、替换、增加指定元素

    一、前言

    注:该方法会改变原始数组。

    ES6数组中删除指定元素

    findIndex()方法返回数组中满足提供的测试函数的第一个元素的索引。否则返回-1。

    1. arr.splice(arr.findIndex(item => item.id === data.id), 1)
    2. 复制代码

    二、splice实现删除、替换、新增

    1. splice(index,len,[item])
    2. 复制代码

    splice有3个参数,它也可以用来替换/删除/添加数组内某一个或者几个值。

    index:数组开始下标 len: 替换/删除的长度 item:替换的值,删除操作的话, item为空 如:

    1. arr = ['a','b','c','d']
    2. 复制代码

    删除 ---- item不设置

    1. arr.splice(1,1) //['a','c','d'] //删除起始下标为1,长度为1的一个值,len设置的1,如果为0,则数组不变
    2. arr.splice(1,2) //['a','d'] //删除起始下标为1,长度为2的一个值,len设置的2
    3. 复制代码

    替换 ---- item为替换值

    1. arr.splice(1,1,'ttt') //['a','ttt','c','d'] //替换起始下标为1,长度为1的一个值为'ttt',len设置的1
    2. arr.splice(1,2,'ttt') //['a','ttt','d'] //替换起始下标为1,长度为2的两个值为'ttt',len设置的1
    3. 复制代码

    添加 ---- len设置为0,item为添加值

    1. arr.splice(1,0,'ttt') //['a','ttt','b','c','d'] //表示在下标为1处添加一项'ttt'
    2. 复制代码

    7、vue实战——vue中发送AJAX请求

    一、简介

    1)vue本身不支持发送AJAX请求,需要使用vue-resource、axios等插件实现。

    2) axios是一个基于Promise的HTTP请求客户端,用来发送请求,也是vue2.0官方推荐的,同时不再对vue-resource进行更新和维护。 参考:GitHub上搜索axios,查看API文档

    二、使用axios发送AJAX请求 1、安装axios并引入

    1)npm的方式: $ npm install axios -S

    2)bower的方式:$ bower install axios

    3)cdn的方式:

    2、基本用法 1)axios([options])

    1. <!DOCTYPE html>
    2. <html>
    3. <head lang="en">
    4. <meta charset="UTF-8">
    5. <title>axios发送ajax请求基本用法</title>
    6. <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    7. <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
    8. </head>
    9. <body>
    10. <div id="app">
    11. <button @click="send">发送ajax请求</button>
    12. </div>
    13. <script>
    14. new Vue({
    15. el:"#app",
    16. methods:{
    17. send(){
    18. axios({
    19. method:'get',
    20. url:'user.json'
    21. }).then(function(res){
    22. console.log(res.data.name);
    23. });
    24. }
    25. }
    26. });
    27. </script>
    28. </body>
    29. </html>
    30. 复制代码

    2)axios.get(url[,options]);

    传参方式:
    (1)通过url传参axios(‘url?key=value&key1=val2’).then();
    (2)通过params选项传参 axios(‘url’,{params:{key:value}}).then();\

    3)axios.post(url,data,[options]);

    axios默认发送数据时,数据格式是Request Payload,并非常用的Form Data格式, 所以参数必须要以键值对形式传递,不能以json形式传。

    传参方式:
    (1)自己拼接为键值对 axios.post(‘url’,‘key=value&key1=value1’).then();
    (2)使用transformRequest,在请求发送前将请求数据进行转换

    1. axios.post('url',data,{
    2. transformRequest:[
    3. function(data){
    4. let params = '';
    5. for(let index in data){
    6. params +=index+'='+data[index]+'&';
    7. }
    8. return params;
    9. }
    10. ]
    11. }).then(function(res){
    12. console.log(res.data)
    13. });
    14. 复制代码

    3)如果使用模块化开发,可以使用qs模块进行转换

    axios本身并不支持发送跨域的请求,没有提供相应的API,作者也暂没计划在axios添加支持发送跨域请求, 所以只能使用第三方库

    三、跨域请求(使用vue-resource发送跨域请求) 1、使用vue-resource发送跨域请求步骤

    安装vue-resource并引入:

    1. npm install vue-resource -S
    2. 复制代码

    基本用法:

    使用this.$http.jsonp(url,[ops]) 发送请求

    2、基本使用演示(360搜索)
    1)打开360搜索,然后输入字符’a’会有一些搜索选项自动提示,如图

    2)复制链接
    sug.so.360.cn/suggest?cal…
    3)代码演示

    1. <!DOCTYPE html>
    2. <html>
    3. <head lang="en">
    4. <meta charset="UTF-8">
    5. <title>使用vue-resource发送跨域请求</title>
    6. <!--引入vue、vue-resource文件-->
    7. <script src="vue.min.js"></script>
    8. <script src="vue-resource.min.js"></script>
    9. </head>
    10. <body>
    11. <div id="app">
    12. <button @click="sendJsonp">send</button>
    13. </div>
    14. <script>
    15. var vm = new Vue({
    16. el:"#app",
    17. methods:{
    18. sendJsonp:function(){
    19. this.$http.jsonp('https://sug.so.360.cn/suggest',{
    20. params:{
    21. word:'a'
    22. }
    23. }).then(function(res){
    24. console.log(res.data);
    25. });
    26. }
    27. }
    28. });
    29. </script>
    30. </body>
    31. </html>
    32. 复制代码

    4)结果\

    3、基本例子演示(百度搜索)

    1)要求同360搜索的要求

    2)复制链接 =1526436420943”>sp0.baidu.com/5a1Fazu8AA5…

    3)代码演示

    之前360搜索jsonp回调的参数名是callback,而百度使用的参数名为cb,所以会报错,新增 jsonp:'cb'

    1. <!DOCTYPE html>
    2. <html>
    3. <head lang="en">
    4. <meta charset="UTF-8">
    5. <title>使用vue-resource发送跨域请求</title>
    6. <!--引入vue、vue-resource文件-->
    7. <script src="vue.min.js"></script>
    8. <script src="vue-resource.min.js"></script>
    9. </head>
    10. <body>
    11. <div id="app">
    12. <button @click="sendJsonp">send</button>
    13. </div>
    14. <script>
    15. var vm = new Vue({
    16. el:"#app",
    17. methods:{
    18. sendJsonp:function(){
    19. this.$http.jsonp('https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su',{
    20. params:{
    21. wd:'a'
    22. },
    23. jsonp:'cb'
    24. }).then(function(res){
    25. console.log(res.data);
    26. });
    27. }
    28. }
    29. });
    30. </script>
    31. </body>
    32. </html>
    33. 复制代码

    4)结果

    8、vue cryptoJS AES加密

    1.先在vue项目中安装crypto-js

    1. npm install crypto-js
    2. 复制代码

    2.新建一个secret.js文件

    1. //引用AES源码js
    2. const CryptoJS = require('crypto-js');
    3. const key = CryptoJS.enc.Utf8.parse("1234123412ABCDEF");//十六位十六进制数作为密钥
    4. const iv = CryptoJS.enc.Utf8.parse('ABCDEF1234123412');//十六位十六进制数作为密钥偏移量
    5. //解密方法
    6. function Decrypt(word) {
    7. //先将Base64还原一下,因为加密的时候做了一些字符的替换
    8. const restoreBase64 = word.replace(/\-g/,'+').replace(/_/,'/');
    9. //返回的是解密后的对象
    10. let decrypt = CryptoJS.AES.decrypt(restoreBase64,key,{
    11. iv:iv,
    12. mode:CryptoJS.mode.CBC,
    13. padding:CryptoJS.pad.Pkcs7
    14. });
    15. //将解密对象转换成UTF8的字符串
    16. let decryptedStr = decrypt.toString(CryptoJS.enc.Utf8);
    17. //返回解密结果
    18. return decryptedStr.toString();
    19. }
    20. //加密方法
    21. function Encrypt(word){
    22. console.log('组件里的:',word);
    23. let srcs = CryptoJS.enc.Utf8.parse(word);
    24. //CipherOption,加密的一些选项:
    25. //mode:加密模式,可取值(CBC,CFB,CTR,CTRGladman,OFB,ECB),都在CryptoJS.mode对象下
    26. //padding:填充方式,可取值(Pkcs7,Ansix923,Iso10126,ZeroPadding,NoPadding),都在CryptoJS.pad对象下
    27. //iv:偏移量,mode===ECB时,不需要iv
    28. //返回的是一个加密对象
    29. let encrypted = CryptoJS.AES.encrypt(srcs,key,{
    30. iv:iv,
    31. mode:CryptoJS.mode.CBC,
    32. padding:CryptoJS.pad.Pkcs7
    33. });
    34. //将结果进行base64加密
    35. return encrypted.ciphertext.toString(CryptoJS.enc.Base64);
    36. }
    37. // export {Decrypt,Encrypt}
    38. export {Encrypt}
    39. 复制代码

    3.vue页面内容

    1. import {Encrypt} from "../../utils/secret";
    2. var userName = Encrypt(this.userName)//加密用户名
    3. var userPassword = Encrypt(this.password)//加密用户密码
    4. console.log('加密后:',userName)
    5. console.log('加密后:',userPassword)
    6. 复制代码

    9、vue axios.post请求后端接收不到参数问题

    处理方案一:请求拦截

    1. // post请求后台无法获取传递参数
    2. axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';//配置请求头
    3. axios.defaults.transformRequest = function (data) {
    4. return qs.stringify(data, {arrayFormat: 'brackets'})
    5. }
    6. 复制代码

    处理方案二:

    1. //axios
    2. axios({
    3. method: "post",
    4. url: host + '/xpg/baoxian/getSpbxList',
    5. data: urlstringify({
    6. "fl": title.trim(),
    7. "page": 1,
    8. "size": 10
    9. }),
    10. headers: {
    11. "Content-Type": 'application/x-www-form-urlencoded'
    12. }
    13. })
    14. .then(function (response) {
    15. }
    16. .catch(function (error) {
    17. console.log(error);
    18. });
    19. //转义方法
    20. function urlstringify(obj) {//字符串序列化
    21. var str = '';
    22. for (let key in obj) {
    23. if (Object.prototype.toString.call(obj[key]) === '[object Array]' || obj[key].constructor === Object) {
    24. //数组,对象
    25. for (var arrKey in obj[key]) {
    26. if (Object.prototype.toString.call(obj[key][arrKey]) === '[object Array]' || obj[key][arrKey].constructor === Object) {
    27. //数组,对象
    28. for (var arrarrKey in obj[key][arrKey]) {
    29. str += '&' + key + '[' + arrKey + '][' + arrarrKey + ']=' + obj[key][arrKey][arrarrKey];
    30. }
    31. } else {
    32. //普通
    33. str += '&' + key + '[' + arrKey + ']=' + obj[key][arrKey];
    34. }
    35. }
    36. } else {
    37. //普通
    38. str += '&' + key + '=' + obj[key];
    39. }
    40. }
    41. return str.substring(1);
    42. }
    43. 复制代码

    11、vue中如何实现中英或多语言切换(含element-ui)

    1、首先使用cmd窗口安装 vue-i18n 包

    1. npm install vue-i18n --save-dev
    2. 复制代码

    2、然后在main.js中引入

    1. import VueI18n from 'vue-i18n' //导入包
    2. //导入locales js
    3. import i18n from './common/locales/index.js'
    4. new Vue({
    5. i18n,
    6. el: '#app',
    7. render: h => h(App)
    8. })
    9. 复制代码

    3、index.js en.js内容:

    4、locales js:

    1. import Vue from 'vue' // 引入vue实例
    2. import VueI18n from 'vue-i18n' // 引入vue-i18n多语言包
    3. // element ui国际化
    4. import ElementUI from 'element-ui'
    5. import enLocale from 'element-ui/lib/locale/lang/en'
    6. import twLocale from 'element-ui/lib/locale/lang/zh-tw'
    7. import idLocale from 'element-ui/lib/locale/lang/en'
    8. import jpLocale from 'element-ui/lib/locale/lang/en'
    9. // import idLocale from 'element-ui/lib/locale/lang/id-ID'
    10. import ElementUILocale from 'element-ui/lib/locale'
    11. Vue.use(VueI18n) // vue使用vue-i18n
    12. //element ui国际化
    13. Vue.use(ElementUI,{ElementUILocale})
    14. const DEFAULT_LANG = 'en' // 默认语言为英文
    15. const LOCALE_KEY = 'localeOld_block_chain' // localStorage来存放的key,名字随便定,接下来会用到。
    16. const locales = { // 引入zh.js以及en.js
    17. tw: require('../i18n/zh-tw.js'),
    18. en: require('../i18n/en.js'),
    19. id: require('../i18n/id-ID.js'),
    20. jp: require('../i18n/jp-JP.js')
    21. }
    22. const i18n = new VueI18n({ // 创建带有选项的 VueI18n 实例
    23. locale: DEFAULT_LANG, // 语言标识,在这里默认为en,即为英文
    24. messages: locales // 语言包,上边创建的json文件
    25. })
    26. // element ui国际化
    27. const UIlocales = {
    28. tw: twLocale,
    29. en: enLocale,
    30. id: idLocale,
    31. jp: jpLocale,
    32. }
    33. const setUIlocales = lang => {
    34. switch (lang) {
    35. case 'tw':
    36. return UIlocales.tw
    37. case 'en':
    38. return UIlocales.en
    39. case 'id':
    40. return UIlocales.id
    41. case 'jp':
    42. return UIlocales.jp
    43. }
    44. }
    45. export const setup = lang => { //切换语言的函数,lang为语言标识,en或者tw
    46. // 在此判断lang的值,如果未定义,则让lang默认为DEFAULT_LANG,目的是为了让用户在未选择语言的时候默认为英文。
    47. if (lang == undefined) {
    48. lang = window.localStorage.getItem(LOCALE_KEY)
    49. if (locales[lang] == undefined) {
    50. lang = DEFAULT_LANG
    51. }
    52. } // 若lang有值,那么存入localStorage中,keyLOCALE_KEY,value为lang。
    53. window.localStorage.setItem(LOCALE_KEY, lang)
    54. Object.keys(locales).forEach(item => {
    55. document.body.classList.remove('lang-${item}')
    56. })
    57. document.body.classList.add('lang-${lang}')
    58. document.body.setAttribute('lang', lang)
    59. Vue.config.lang = lang
    60. i18n.locale = lang
    61. // element ui 切换语言
    62. ElementUILocale.use(setUIlocales(lang))
    63. // 挂载需要用到多语言的js文件
    64. const vueInstance = new Vue({ i18n });
    65. if(vueInstance&&vueInstance.$i18n&&vueInstance.$i18n.messages){
    66. // console.log("Vue",vueInstance)
    67. let tipsJs = vueInstance.$i18n.messages[lang];
    68. // console.log("tipsJs",tipsJs.lang.tipsJs)
    69. Vue.prototype.$tipsJs = tipsJs.lang.tipsJs;
    70. }
    71. }
    72. setup()
    73. export default i18n
    74. 复制代码

    5、页面使用多语言 js引入this.$t('') template使用{{i18n.Markets}}

    1. <div class="container_nav">
    2. <p class="tac white fs16">{{i18n.Markets}}</p>
    3. </div>
    4. 复制代码
    1. computed: {
    2. i18n() {
    3. return this.$t('lang.markets')
    4. },
    5. },
    6. 复制代码

    6、自定义js引入i18n

    1. // 引入多语言
    2. import i18n from '../common/locales/index.js';
    3. let envIndex = i18n.t('lang').envIndex;
    4. 复制代码

    13、详解vue 路由跳转四种方式 (带参数)

    1.  router-link

    1. 不带参数
    1. <router-link :to="{name:'home'}">
    2. <router-link :to="{path:'/home'}"> //name,path都行, 建议用name
    3. // 注意:router-link中链接如果是'/'开始就是从根路由开始,如果开始不带'/',则从当前路由开始。
    4. 复制代码

    2.带参数(建议query传参数,不用配置路由)

    1. <router-link :to="{name:'home', params: {id:1}}">
    2. // params传参数 (类似post)
    3. // 路由配置 path: "/home/:id" 或者 path: "/home:id"
    4. // 不配置path ,第一次可请求,刷新页面id会消失
    5. // 配置path,刷新页面id会保留
    6. // html 取参 $route.params.id
    7. // script 取参 this.$route.params.id
    8. <router-link :to="{name:'home', query: {id:1}}">
    9. // query传参数 (类似get,url后面会显示参数)
    10. // 路由可不配置
    11. // html 取参 $route.query.id
    12. // script 取参 this.$route.query.id
    13. 复制代码

    2.  this.$router.push() (函数里面调用)

    1. 1. 不带参数
    2. this.$router.push('/home')
    3. this.$router.push({name:'home'})
    4. this.$router.push({path:'/home'})
    5. 2. query传参
    6. this.$router.push({name:'home',query: {id:'1'}})
    7. this.$router.push({path:'/home',query: {id:'1'}})
    8. // html 取参 $route.query.id
    9. // script 取参 this.$route.query.id
    10. 3. params传参
    11. this.$router.push({name:'home',params: {id:'1'}}) // 只能用 name
    12. // 路由配置 path: "/home/:id" 或者 path: "/home:id" ,
    13. // 不配置path ,第一次可请求,刷新页面id会消失
    14. // 配置path,刷新页面id会保留
    15. // html 取参 $route.params.id
    16. // script 取参 this.$route.params.id
    17. 4. query和params区别
    18. query类似 get, 跳转之后页面 url后面会拼接参数,类似?id=1, 非重要性的可以这样传, 密码之类还是用params刷新页面id还在
    19. params类似 post, 跳转之后页面 url后面不会拼接参数 , 但是刷新页面id 会消失
    20. 复制代码

    3.  this.$router.replace() (用法同上,push)

    4.  this.$router.go(n)

    this.$router.go(n)

    向前或者向后跳转n个页面,n可为正整数或负整数

    ps : 区别

    this.$router.push

    跳转到指定url路径,并想history栈中添加一个记录,点击后退会返回到上一个页面

    this.$router.replace

    跳转到指定url路径,但是history栈中不会有记录,点击返回会跳转到上上个页面 (就是直接替换了当前页面)

    this.$router.go(n)

    向前或者向后跳转n个页面,n可为正整数或负整数

    14、vue前进刷新,后退不刷新and按需刷新

    1.在路由文件router.js中为目标列表页设置meta参数,里面包含keepAlive和ifDoFresh字段

    1. {
    2.     path:'*',
    3.     name:'datalist',
    4.     component: resolve => require(['@/view/datalist'], resolve),
    5.     meta:{
    6.         keepAlive: true,
    7.         ifDoFresh:false
    8.     }
    9. },
    10. 复制代码

    2.在程序主入口main.vue中设置页面根据keepAlive字段判断是否使用keep-alive组件。

    1. <div class="main">
    2. <keep-alive>
    3. <router-view v-if="$route.meta.keepAlive"/>
    4. </keep-alive>
    5. <router-view v-if="!$route.meta.keepAlive"/>
    6. </div>
    7. 复制代码

    3.在目标列表页的beforeRouteEnter方法中判断页面进入方式(详情页,编辑页或其他方式),根据需求将路由参数的ifDoFresh字段设为true/false,

    在页面的activated(开启了 keepAlive: true的页面在第二次进入时是无法触发mounted发法的)方法中根据ifDoFresh字段判断是否刷新页面

    1. beforeRouteEnter (to, from, next) {
    2. if(from.name!='详情页'&&from.name!='编辑页'){
    3. to.meta.ifDoFresh = true;
    4. }
    5. next();
    6. },
    7. activated(){
    8. //开启了keepAlive:true后再次进入,以前的搜索条件和页数都不会变,无论什么情况都调用一下获取数据的接口,这样就能得到当前搜索条件和页数的最新数据
    9. if(this.$route.meta.ifDoFresh){
    10. //重置ifDoFresh
    11. this.$route.meta.ifDoFresh = false;
    12. //获取列表数据方法第一参数为是否重置搜索条件和页数 this.getData(true);
    13. }else{
    14. this.getData();
    15. }
    16. }
    17. 复制代码

    15、vue项目添加发布路径

    项目模板

    我的项目是使用vue init webpack创建的,所以我需要修改3个文件。

    修改文件

    (1)index.html

    head中添加

    (2)路由文件添加base:'/match/'

    1. let router = new Router({
    2. base:'/match/,
    3. routes: [
    4. {
    5. path: '/login',
    6. type: 'login',
    7. component: Login,
    8. meta:{
    9. keepAlive: true,
    10. ifDoFresh:true,
    11. }
    12. },
    13. ]
    14. });
    15. 复制代码

    (3)配置文件/config/index.js 修改assetsPublicPath参数

    1. assetsPublicPath: '/macth/',
    2. 复制代码

    总结:打包修改assetsPublicPath也可满足,后台上传不同地址即可。

    16、 es6新增语法之${}

    1、反单引号怎么打出来?
    将输入法调整为英文输入法,单击键盘上数字键1左边的按键。

    2、用法
    step1: 定义需要拼接进去的字符串变量
    step2: 将字符串变量用${}包起来,再写到需要拼接的地方

    3、示例代码:

    1. let a='Karry Wang';
    2. let str=`I love ${a}, because he is handsome.`;
    3. //注意:这行代码是用返单号引起来的
    4. alert(str);
    5. 复制代码

    一定是用反单引号啊!不要写成单引号了!!

    17、Form 表单重置失败问题解决

    一、前言 在Vue项目开发过程中,应用this.refs[name].resetFields();实现表单搜索元素重置时发现失效。经检查发现是form−item绑定的属性prop与包裹元素el−input绑定值不一致造成的。现梳理有关应用this.refs[name].resetFields();实现表单搜索元素重置时发现失效。经检查发现是form-item绑定的属性prop与包裹元素el-input绑定值不一致造成的。现梳理有关应用this.refs[name].resetFields();实现表单搜索元素重置时发现失效。经检查发现是form−item绑定的属性prop与包裹元素el−input绑定值不一致造成的。现梳理有关应用this.refs[name].resetFields();重置表单注意事项。

    Form必须要有ref属性;
    Form必须绑定:model;

    1. <Form ref="submitUser" :model="submitUser">
    2. 复制代码
    • FormFormItem中必须要有prop属性;
    1. <FormItem prop="realName">
    2. </FormItem>
    3. 复制代码
    • Form包裹的元素绑定值需与FormItemprop属性名称保持一致(可类比Form表单校验规则)
    1. <Form ref="submitUser" :model="submitUser">
    2. <FormItem prop="uname">
    3. <Input type="text" v-model="submitUser.uname" placeholder="用户名"></Input>
    4. </FormItem>
    5. <FormItem prop="passwd">
    6. <Input type="text" v-model="submitUser.passwd" placeholder="密码"></Input>
    7. </FormItem>
    8. <FormItem>
    9. <Button type="info" @click="query">Login</Button>
    10. <Button @click="handleReset('submitUser')" style="margin-left: 8px;" type="info">Reset</Button>
    11. </FormItem>
    12. </Form>
    13. <script>
    14. export default {
    15. data () {
    16. return {
    17. submitUser:{
    18. realName:'',
    19. identityNumber:'',
    20. mobileNumber:'',
    21. telePhoneNumber:''
    22. }
    23. }
    24. },
    25. methods:{
    26. handleReset (name) {
    27. this.$refs[name].resetFields();
    28. }
    29. }
    30. }
    31. </script>
    32. 复制代码

    18、Vue监听数据变化

    监听数据变化,在Vue中是通过侦听器来实现的,时刻监听某个数据的变化

    watch的基本用法

    1. 侦听器的书写位置
      写在export default中与data和methods用,隔开
    1. <script>
    2. export default {
    3. name: "app",
    4. // 数据 key---data value---Function
    5. data: function () {
    6. return {
    7. count: 1
    8. };
    9. },
    10. // 方法 key---methods value---{}
    11. methods: {},
    12. //在export default中添加即可不用管顺序
    13. watch: {
    14. //监听内容
    15. count() {
    16. console.log("count发生了变化");
    17. }
    18. }
    19. };
    20. </script>
    21. 复制代码

    监听器里的方法一定要与被监听的变量名一致

    侦听器的进阶用法

    获取前一次的值

    有的时候需要上一次的数据,再上一个案例中添加一个参数即可获取旧值

    1. watch:{
    2. inputValue(value,oldValue) {
    3. // 第一个参数为新值,第二个参数为旧值,不能调换顺序
    4. console.log(`新值:${value}`);
    5. console.log(`旧值:${oldValue}`);
    6. }
    7. }
    8. 复制代码

    handler方法immediate属性

    immediate: 可以让页面第一次渲染的时候去触发侦听器
    handler: 监听到修改之后这个函数会执行
    侦听器实际上是一个对象,里面包含了handler方法和其他属性:

    1. <script>
    2. export default {
    3. name: "app",
    4. watch: {
    5. firstName: {
    6. handler: function (newName, oldName) {
    7. this.fullName = newName + " " + this.lastName;
    8. },
    9. immediate: true
    10. }
    11. }
    12. };
    13. </script>
    14. 复制代码

    19、vue中页面加载进度条效果

    滚动条效果插件:nprogress

    • 安装:
    1. cnpm install --save nprogress
    2. 复制代码
    • main.js中引入:
    1. //引入nprogressimport NProgress from 'nprogress'import 'nprogress/nprogress.css' //这个样式必须引入
    2. 复制代码
    • main.js中进行一些配置:
    1. NProgress.configure({
    2. easing: 'ease', // 动画方式
    3. speed: 500, // 递增进度条的速度
    4. showSpinner: false, // 是否显示加载ico
    5. trickleSpeed: 200, // 自动递增间隔
    6. minimum: 0.3 // 初始化时的最小百分比
    7. })
    8. 复制代码
    • 接下来,还是在mian.js中,
    1. router.beforeEach((to, from , next) => {
    2. // 每次切换页面时,调用进度条
    3. NProgress.start();
    4. // 这个一定要加,没有next()页面不会跳转的。这部分还不清楚的去翻一下官网就明白了
    5. next();
    6. });
    7. 复制代码
    1. router.afterEach(() => {
    2. // 在即将进入新的页面组件前,关闭掉进度条
    3. NProgress.done()
    4. })
    5. 复制代码

    20、 webpack only one instance of babel-polyfill is allowe

    旧的浏览器不兼容babel-polyfill

    项目是用vue-cli2搭建的,主要引起错误的原因如下图所示:

    用了这种方式后,babel-polyfill与其他的插件造成了冲突,也就是说有两个地方都用到了babel-polyfill

    于是我的解决方案如下所示:

    第一步去掉配置文件的babel-polyfill

    1. entry: {
    2. app: './src/main.js',
    3. }
    4. 复制代码

    第二步,在main.js加上以下代码

    1. if (!global._babelPolyfill) {
    2. require('babel-polyfill');
    3. }
    4. 复制代码

    21、nvm常用命令 切换node

    常用命令:

    1. nvm ls :列出所有已安装的 node 版本
    2. nvm ls-remote :列出所有远程服务器的版本(官方node version list)
    3. nvm list :列出所有已安装的 node 版本
    4. nvm list available :显示所有可下载的版本
    5. nvm install stable :安装最新版 node
    6. nvm install [node版本号] :安装指定版本 node
    7. nvm uninstall [node版本号] :删除已安装的指定版本
    8. nvm use [node版本号] :切换到指定版本 node
    9. nvm current :当前 node 版本
    10. nvm alias [别名] [node版本号] :给不同的版本号添加别名
    11. nvm unalias [别名] :删除已定义的别名
    12. nvm alias default [node版本号] :设置默认版本
    13. 复制代码

    22、前端脚手架并发布到npm

    1. 首先在本地创建一个npm项目。
    2. 在本地新建文件夹。vue-test
    3. 创建好文件夹后,使用cmd进入该创建好的文件夹。
    4. 使用npm init 全部Y 生成一个默认的package.json模板,在package.json 中需要增加一个bin配置,声明这个bin的名称以及对应文件地址。
    1. 在当前文件夹下新建一个文件夹目录bin目录。

    1. 在新建的这个bin目录下新建一个index.js文件。
    2. 编辑这个index.js 文件,在文件中添加 console.log("vue-test")
    3. 并且在当前文件的首开始,添加一行 #!/usr/bin/env node

    1. 将脚手架发布到npm(此处需要大家先行在npm进行注册。) 使用npm login 进行npm登陆。 然后使用 npm publish 发布 (此处报错,建议百度。一般都是名称重复问题)
    2. 推送成功后,在自己电脑本地则可以使用 npm install vue-test -g 进行安装
    3. 安装完成后,则可以使用 vue-test (package.json 中bin配置的那个名称)来进行验证

    23、 vue 刷新不出现白屏的解决办法

    1、路由切换操作

    1. // 如果在这个空间有权限,刷新当前页面
    2. this.$router.push(path).catch(err => err);
    3. 复制代码

    2、在使用router-view 的地方(一般在APP.vue文件)

    1. <template>
    2. <div class="home">
    3. <router-view class="right" v-if="isRouterAlive" />
    4. </div>
    5. </template>
    6. <script>
    7. export default {
    8. provide() {
    9. return {
    10. reload: this.reload
    11. }
    12. },
    13. data() {
    14. return {
    15. isRouterAlive: true
    16. };
    17. },
    18. mounted() {
    19. },
    20. methods: {
    21. reload() {
    22. this.isRouterAlive = false
    23. this.$nextTick(() => {
    24. this.isRouterAlive = true
    25. })
    26. }
    27. }
    28. };
    29. </script>
    30. 复制代码

    3、在被刷新的地方

    方式一:watch监听

    1. export default {
    2. inject: ['reload'],
    3. watch: {
    4. // 监听到路由跳转时,强制刷新
    5. '$route': {
    6. handler() {
    7. this.reload()
    8. }
    9. }
    10. },
    11. }
    12. 复制代码

    方式二,methods方法调用刷新

    1. export default {
    2. inject: ['reload'],
    3. created() {
    4. this.refresh();
    5. },
    6. methods: {
    7. //刷新方法
    8. refresh(){
    9. this.reload()
    10. }
    11. },
    12. }
    13. 复制代码

    24、 vue-resource和axios和vue-axios区别

    vue-resource(已经淘汰)

    目前主流的 Vue 项目,都选择 axios 来完成 ajax 请求,基于 Promise 的 HTTP 请求客户端,可同时在浏览器和 Node.js 中使用。

    vue-axios 是在axios基础上扩展的插件,在Vue.prototype原型上扩展了$http等属性,可以更加方便的使用axios,使用vue-axios更多是为了符合规范,并且方便协作吧。

    总结:

    25、window.open在Safari中不能打开的问题

    1.原因分析:

    原因:大部分现代的浏览器(Chrome/Firefox/IE 10+/Safari)都默认开启了阻止弹出窗口的策略,原因是window.open被广告商滥用,严重影响用户的使用。这个阻止弹出窗口的操作,并不是直接封杀window.open(),而是会根据用户的行为来判断这次window.open()是否属于流氓操作。
    如果是由用户触发的动作所引起的 window.open 就不会被浏览器所阻止,比如写在 onclick 这些事件 handler 里的,但如果是代码自己触发的就会被阻止。
    那么,我们可以知道,在Safari中无法open新窗口,原因是Safari的安全机制将其阻挡。
    并不是所有地方都无法正常使用,在一些ajax或者jquery的getjson等回调代码中只要调用window.open都失效。原因是苹果的安全策略拦截。

    2.解决方案:

    解决办法有4种:

    (1)用window.location.replace()来替代,【或者改变location.href,可以解决,缺点就是不是新开的窗口】

    (2)苹果系统设置,偏好设置->安全性,去掉阻止弹窗的复选框就ok了。 【不建议,会改变用户的设置】

    (3)在回到函数中生成一个链接,让用户再次点击下,因为链接是无论如何不会被拦截的。【不建议,多加了一个动作】

    (4)在回调代码之前打开一个空窗口,例如 var w=window.open(xxx); 然后在回调函数中设置它的location。【推荐】

    例如w.location='juejin.cn/user/229183…'; 具体分析和代码参考:

    1. var openWin = function(){
    2. var winRef = window.open("url","_blank");
    3. $.ajax({
    4. type: '',
    5. url: '',
    6. data: '',
    7. ......
    8. success:function(json){
    9. winRef.location = "新的url";
    10. }
    11. });
    12. };
    13. 复制代码

    26、解决Vuex-在F5刷新页面后数据不见

    1.问题场景

    vuex优势:相比sessionStorage,存储数据更安全,sessionStorage可以在控制台被看到。 vuex劣势:在F5刷新页面后,vuex会重新更新state,所以,存储的数据会丢失。 为了克服这个问题, vuex-persistedstate出现了

    2.原理

    • 将vuex的state存在localStorage或sessionStorage或cookie中一份
    • 刷新页面的一瞬间,vuex数据消失,vuex会去sessionStorage中拿回数据,变相的实现了数据刷新不丢失~

    3.使用方法

    • 安装
    1. npm install vuex-persistedstate --save
    2. 复制代码
    • 在store下的index.js中,引入并配置

      1. import createPersistedState from "vuex-persistedstate"
      2. const store = new Vuex.Store({
      3. // ...
      4. plugins: [createPersistedState()]
      5. })
      6. 复制代码
    • 此时可以选择数据存储的位置,可以是localStorage/sessionStorage/cookie,此处以存储到sessionStorage为例,配置如下:

      1. import createPersistedState from "vuex-persistedstate"
      2. const store = new Vuex.Store({
      3. // ...
      4. plugins: [createPersistedState({
      5. storage: window.sessionStorage
      6. })]
      7. })
      8. 复制代码

    4. 存储指定state:

    vuex-persistedstate默认持久化所有state,指定需要持久化的state,配置如下:

    1. import createPersistedState from "vuex-persistedstate"
    2. const store = new Vuex.Store({
    3. // ...
    4. plugins: [createPersistedState({
    5. storage: window.sessionStorage,
    6. reducer(val) {
    7. return {
    8. // 只储存state中的user
    9. user: val.user
    10. }
    11. }
    12. })]
    13. 复制代码

    5. 如果此刻想配置多个选项,将plugins写成一个一维数组,不然会报错。

    1. import createPersistedState from "vuex-persistedstate"
    2. import createLogger from 'vuex/dist/logger'
    3. // 判断环境 vuex提示生产环境中不使用
    4. const debug = process.env.NODE_ENV !== 'production'
    5. const createPersisted = createPersistedState({
    6. storage: window.sessionStorage
    7. })
    8. export default new Vuex.Store({
    9. // ...
    10. plugins: debug ? [createLogger(), createPersisted] : [createPersisted]
    11. })
    12. 复制代码

    27、vue实现滚动公告栏效果组件

    1. <template>
    2. <div>
    3. <div class="textBox">
    4. <transition name="slide">
    5. <p class="text" :key="text.id">
    6. <el-tag type="warning">{{text.val.tag}}</el-tag>
    7. {{text.val.title}}</p>
    8. </transition>
    9. </div>
    10. </div>
    11. </template>
    12. <script>
    13. export default {
    14. name: 'scroll',
    15. data () {
    16. return {
    17. textArr: [
    18. {tag:'精彩推荐',title:'第1条公告'},
    19. {tag:'热门推荐',title:'第3条公告'},
    20. {tag:'精彩推荐',title:'第3条公告'},
    21. {tag:'公司公告',title:'第4条公告'},
    22. {tag:'热门推荐',title:'第5条公告'},
    23. ],
    24. number: 0
    25. }
    26. },
    27. computed: {
    28. text () {
    29. return {
    30. id: this.number,
    31. val: this.textArr[this.number]
    32. }
    33. }
    34. },
    35. mounted () {
    36. this.startMove()
    37. },
    38. methods: {
    39. startMove () {
    40. // eslint-disable-next-line
    41. let timer = setTimeout(() => {
    42. if (this.number === this.textArr.length) {
    43. this.number = 0;
    44. } else {
    45. this.number += 1;
    46. }
    47. this.startMove();
    48. }, 2500); // 滚动不需要停顿则将2000改成动画持续时间
    49. }
    50. }
    51. }
    52. </script>
    53. <style scoped>
    54. .textBox {
    55. width: 100%;
    56. height: 40px;
    57. margin: 0 auto;
    58. overflow: hidden;
    59. position: relative;
    60. text-align: center;
    61. }
    62. .text {
    63. width: 100%;
    64. position: absolute;
    65. bottom: 0;
    66. }
    67. .slide-enter-active, .slide-leave-active {
    68. transition: all 0.5s linear;
    69. }
    70. .slide-enter{
    71. transform: translateY(20px) scale(1);
    72. opacity: 1;
    73. }
    74. .slide-leave-to {
    75. transform: translateY(-20px) scale(0.8);
    76. opacity: 0;
    77. }
    78. </style>
    79. 复制代码

    28、解决input只能输入金额类型的方案(金额输入框只能输入2位小数)

    1. <input type="digit" v-model="writeMoney" class="payInput" @input="oninput" :maxlength="moneyMaxLeng" />
    2. data() {
    3. return {
    4. writeMoney: "",
    5. moneyMaxLeng: 8//规定最大可输入的长度
    6. }
    7. },
    8. //输入内容验证
    9. oninput(e) {
    10. this.$nextTick(() => {
    11. let val = e.target.value.toString();
    12. val = val.replace(/[^\d.]/g, ""); //清除"数字""."以外的字符
    13. val = val.replace(/.{2,}/g, "."); //只保留第一个. 清除多余的
    14. val = val.replace(/^0+./g, '0.');
    15. val = val.match(/^0+[1-9]+/) ? val = val.replace(/^0+/g, '') : val
    16. val = (val.match(/^\d*(.?\d{0,2})/g)[0]) || ''
    17. if (val.includes(".")) {
    18. let numDian = val.toString().split(".")[1].length;
    19. if (numDian === 2) {
    20. this.moneyMaxLeng = val.length;
    21. }
    22. } else {
    23. this.moneyMaxLeng = 8;
    24. }
    25. this.writeMoney = val;
    26. });
    27. },
    28. 复制代码

    29、Vue中使用transform的translateX来实现下滑线跟随导航。

    1、template中的代码

    1. <ul class="tab" :style="{height: tabheight}">
    2. <li
    3. ref="iWidth"
    4. v-for="(item,index) in tabList"
    5. :key="index"
    6. :class="{'on': checkindex == index}"
    7. @click="checkli(index)"
    8. >{{item}}</li>
    9. <i :style="{transform:`translateX(${iWidths/2+checkindex*iWidths}px) translateX(-50%)`}"></i>
    10. </ul>
    11. 复制代码

    2、css

    1. ul.tab {
    2. height: 1000px;
    3. width: 100%;
    4. border-bottom: 1px solid #eeeeee;
    5. line-height: 1rem;
    6. font-size: 0.32rem;
    7. color: #333333;
    8. display: flex;
    9. position: relative;
    10. overflow: hidden;
    11. transition: all 0.5s;
    12. }
    13. .tab li {
    14. flex: 1;
    15. text-align: center;
    16. transition: all 0.5s;
    17. }
    18. .tab li.on {
    19. color: #da0428;
    20. }
    21. .tab i {
    22. width: 0.6rem;
    23. height: 0.05rem;
    24. border-radius: 0.03rem;
    25. background: #da0428;
    26. bottom: 0;
    27. position: absolute;
    28. transition: all 0.5s;
    29. }
    30. 复制代码

    3、JS代码(实现的主要思路就是通过给元素添加ref属性通过this.$refs.xxx获取此元素的宽度,再配合transform中的translateX属性进行使用。)

  • 相关阅读:
    SSRF漏洞
    Java核心篇,二十三种设计模式(十四),行为型——命令模式
    PTA 7-102 藏头诗
    XSS原理
    cmdline(二):uboot cmdline怎么传?&&cmdline kernel怎么用?
    8. Go实现Gin服务优雅关机与重启
    已解决(pandas读取DataFrame列报错)raise KeyError(key) from err KeyError: (‘name‘, ‘age‘)
    rust angular 自签名证书 wss
    2022-09-16 第二小组 张明旭 Java学习记录
    【Java面试指北】Exception Error Throwable 你分得清么?
  • 原文地址:https://blog.csdn.net/sinat_17775997/article/details/126225993