一vue.js开发环境搭建、安装stylus,以及一些小技巧,--save和--save-dev的区别,axios发送ajax请求静态数据处理,移动端的配置,旅游网站

vue.js的vue-cli的理解

vue-cli是Vue的脚手架工具,帮我们写好vue.js基础代码的工具,搞定目录结构、本地调试、代码部署、热加载、单元测试等工作。

vue.js开发环境搭建

1、安装node.js下载地址,安装好之后需要配置node.js系统环境变量,这里要保证node.js的版本是4版本以上

2、安装全局vue-cli脚手架,用于帮助搭建所需的模板框架

首先:在cmd里面输入:npm install -g vue-cli,回车

然后:在cmd里面输入vue,出现vue信息说明安装成功,如下图所示

3、创建项目

在cmd里面输入:vue init webpack sell(项目文件夹名),等待一会会出现'git'的项,可按下图操作

 

4、安装依赖(进入相应的盘符路径,在执行下面的操作)

首先,在cmd里面输入:cd sell(项目),回车

然后,在cmd里面输入:npm install,回车。

这时候需要等待一会,安装成功会出现下面的图片信息:

回到项目目录下,会发现多了node_modules文件夹(里面的内容就是之前安装的依赖)

5、测试环境是否搭建成功

首先,在cmd里面输入: npm run dev

然后会出现下面的图,表示成功:

然后,在浏览器地址栏里面输入地址:localhost://8080

出现下面的图,表示环境搭建成功

 

6、vue实现ajax获取后台数据是通过vue-resource这个插件的,那么就需要在这个项目下安装这个插件

1) 在项目中引入该插件:在cmd下进入项目的根目录,然后输入“npm install vue-resource --save”

2)在main.js中引入该插件:import VueResource from 'vue-resoucre ;Vue.use(VueResource)

经过以上两步就可以使用vue-resource插件中的API了

 

新版本的vue在使用vue-cli搭建项目的框架的时候,在build文件夹下已经没有dev-server.js文件,这是因为在新版本的vue下,已经将dev-server.js和webpack.dev.conf.js进行合并了,如果需要写路由相关配置,需要在build文件夹下的webpack.dev.conf.js文件中找到devServer对象对相关属性进行配置。

下面是webpack.dev.conf.js文件的内容:

'use strict'
const utils = require('./utils')
const webpack = require('webpack')
const config = require('../config')
const merge = require('webpack-merge')
const path = require('path')
const baseWebpackConfig = require('./webpack.base.conf')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
const portfinder = require('portfinder')

const HOST = process.env.HOST
const PORT = process.env.PORT && Number(process.env.PORT)

const appData = require('../data.json');
const seller = appData.seller;
const goods = appData.goods;
const ratings = appData.ratings;


const devWebpackConfig = merge(baseWebpackConfig,{
  module: {
    rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap,usePostCSS: true })
  },// cheap-module-eval-source-map is faster for development
  devtool: config.dev.devtool,// these devServer options should be customized in /config/index.js
  devServer: {
    before(app){
      app.get('/api/seller',function (req,res) {  //通过路由获取数据都要通过api这个组件去获取
        res.json({
          errno:0,data:seller
        });
      });

      app.get('/api/goods',function(req,res){
        res.json({
          errno:0,data:goods
        });
      });

      app.get('/api/ratings',data:ratings
        });
      });
    },clientLogLevel: 'warning',historyApiFallback: {
      rewrites: [
        { from: /.*/,to: path.posix.join(config.dev.assetsPublicPath,'index.html') },],},hot: true,contentBase: false,// since we use CopyWebpackPlugin.
    compress: true,host: HOST || config.dev.host,port: PORT || config.dev.port,open: config.dev.autoOpenBrowser,overlay: config.dev.errorOverlay
      ? { warnings: false,errors: true }
      : false,publicPath: config.dev.assetsPublicPath,proxy: config.dev.proxyTable,quiet: true,// necessary for FriendlyErrorsPlugin
    watchOptions: {
      poll: config.dev.poll,}
  },plugins: [
    new webpack.DefinePlugin({
      'process.env': require('../config/dev.env')
    }),new webpack.HotModuleReplacementPlugin(),new webpack.NamedModulesPlugin(),// HMR shows correct file names in console on update.
    new webpack.NoEmitOnErrorsPlugin(),// https://github.com/ampedandwired/html-webpack-plugin
    new HtmlWebpackPlugin({
      filename: 'index.html',template: 'index.html',inject: true
    }),// copy custom static assets
    new CopyWebpackPlugin([
      {
        from: path.resolve(__dirname,'../static'),to: config.dev.assetsSubDirectory,ignore: ['.*']
      }
    ])
  ]
})

module.exports = new Promise((resolve,reject) => {
  portfinder.basePort = process.env.PORT || config.dev.port
  portfinder.getPort((err,port) => {
    if (err) {
      reject(err)
    } else {
      // publish the new Port,necessary for e2e tests
      process.env.PORT = port
      // add port to devServer config
      devWebpackConfig.devServer.port = port

      // Add FriendlyErrorsPlugin
      devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({
        compilationSuccessInfo: {
          messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`],onErrors: config.dev.notifyOnErrors
        ? utils.createNotifierCallback()
        : undefined
      }))

      resolve(devWebpackConfig)
    }
  })
})

利用vue的脚手架vue-cli将项目配置好之后,如果做的 是移动端项目,需要在项目的根目录下的index.html的<heada>标签添加如下配置

<meta name="viewport" content="width=device-width,inittial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">

页面宽度为移动端视口宽度,最小最大的页面大小为视口的大小,不能缩放

 

不同浏览器的默认css不一样,需要reset.css设置同样的css

1)在src/assets文件夹下新建文件夹styles,在建一个reset.css文件

2)将 https://meyerweb.com/eric/tools/css/reset/index.html 该内容粘贴在reset.css中

3)将reset.css引进项目中:在src/main.js文件的头部添加如下代码

import './assets/styles.reset.css'

当页面中的样式有所改变的时候,证明该文件引入成功

移动端用1px问

 

 

在vue中使用css预处理器stylus:

cnpm install --save  stylus
cnpm install --save  stylus-loader

在vue的组件中使用stylus语法书写css

 

//scoped使得当前组件的样式只对该组件生效,不会影响到别的组件
<style scoped lang='stylus'>
</style>

移动端的布局,一般使用rem,rem的计算是相对于根元素html中设置的font-size的大小进行计算的

html{
  font-size:50px
}

如果p的width是43px,那么有
p{
  width:.86rem
}

(43 * 2)/(50*2)=0.86rem,这就是设置html的font-size为50px的原因,便于计算

在组件中使用icon-font

1)在https://www.iconfont.cn官网上将要下载的图标添加进购物车,然后添加进项目,然后下载到本地,将字体库和.css文件复制到项目中的文件中,在main.js中将.css文件引进来

2)在组件中,直接使用该类,内容为其16进制代码

 

在webpack.base.conf.js中设置解析规则,使得引进变量的路径变得简短些

如下面:

<style lang="stylus" scoped>
  @import '@/assets/styles/varibles.styl'
</style>

可以将路径写成:
 @import '~styles/varibles.styl'

使用stylus中的变量-----背景色在很多页面共用同一个值,设置变量,便于管理项目,如果项目风格改变,易于管理,只需要改变一个地方即可

1)首先,在src/assets/styles下创建文件varibles.styl

2)在上述文件中添加内容,如上图所示

3)在组件中使用该变量

<style lang="stylus" scoped>
	@import '~styles/varibles.styl'
	.header
		display:flex
		background-color:$bgColor
</style>

这样就可以了

在实际的项目当中,每添加一个新的功能就会创建一个新的分支,当代码完成之后会将代码合并到主分支上

 

安装时--save和--save-dev的区别

在package.json中有两个属性,dependencies和devDependencies

dependencies-表示运行时、发布到生产环境时还需要依赖的插件,--save表示下载的模块会安装到dependencies

devDependencies表示开发、打包时需要的插件,--save-dev下载的模块会安装到devDependencies

npm install '模块名'-----将模块下载到node_modules中

详解     https://blog.csdn.net/cc18868876837/article/details/81109664

 

在vue 中创建轮播图,使用插件vue-awesome-swiper

1)在项目中安装Vue-awesome-swiper,由于最新版有问题,可以在安装的时候指定版本安装

cnpm  install  vue-awesome-swiper@2.6.7  --save

2)在main.js中将vue-awsome-swiper引进来,并通过Vue.use(VueAwesomeSwiper)使用该插件,如下图所示

3)在组件中使用轮播图

 

在使用轮播图时,存在抖动问题,解决方法:链接   https://blog.csdn.net/tangxiujiang/article/details/88872444

4)设置轮播图中的分页符:设置属性swiperOption中的pagination

修改分页符的背景色---->>>样式穿透,样式不受scoped的限制

 

修改轮播图组件中的样式:使用>>>来改变

 

页面图标的拖动,即轮播图,每页显示8个,当多于9-16个之后显示在第二页,以此类推

1)如下所示,是在同一张slider中显示,超过8个图标的部分会被隐藏掉,2)中会利用计算属性设置两页显示的效果

2)利用computed计算分页页数,实现两页显示----将数据分别用不同的数组存储在计算属性pages中

3)在<swiper-slide>中使用for循环,根据不同的页数,获取到数据----key值最好不要用index,不利于diff算法的性能优化

 

使用stylus中mixins功能------对于一些css样式,可能会多处用到,此时可以在src/assets/styles文件夹下建立一个mixins.styl文件

1)内容如下:

2)在组件的<style>中头部引入该文件

@import '~styles/mixins.styl'

3)在相应的位置使用该函数

.icon
    ellipsis()
    position:absolute

 

在 vue中使用axios发送ajax请求

1、首先安装

cnpm  install --save  axios

2、在static文件夹下创建静态数据,如static/mock/index.json

3、在.gitignore文件添加如下内容,使得代码提交的时候mock中的内容不被提交

4、在组件中的mounted调用axios发送ajax请求

import axios from 'axios'
export default {
  name:'Home',components: {
    HomeHeader,HomeSwiper,HomeIcons
  },methods:{
    getHomeInfo(){
      axios.get('/static/mock/index.json')
      .then(this.getHomeInfoSucc)
    },getHomeInfoSucc(res){
      console.log(res)
    }
  },mounted(){
    this.getHomeInfo()
  }
}

注意:axios.get('/static/mock/index.json')这里的路径是静态的,当提交到线上的时候是需要修改成'api/index.json',一般不建议上线前修改该路径,容易出错,存在风险

解决方法:如果生产环境使用'api/index.json',而开发环境使用'/static/mock/index.json',vue中提供了proxy的代理功能,通过该功能就可以实现上面的构想

A)在config/index.js文件中,对象属性dev中的proxyTable属性添加如下内容:当在开发环境下遇到以/api开头,则替换为‘/static/mock’

B)则axios请求的路径可以直接写成线上的路径了

 

 getHomeInfo(){
      axios.get('/api/index.json')
      .then(this.getHomeInfoSucc)
 }

 

用ajax获取到动态数据,渲染下图中的内容,左边是一个组件,右边字母是一个组件,实现页面布局

1)数据格式如下所示:数据在属性cities对象中,每个属性的值是一个数组

在v-for中如果数据cities是数组,使用形式为v-for="(item,index) of  cities"

如果cities是对象,使用形式为v-for="(item,key) of cities"-------区别一个是index一个是key

2)左边内容对应的是List.vue组件部分内容如下----有嵌套的v-for,只要同层的key不一样就可以

cities是属性,所以外层for用key,item是数组,所以内层for用index

3)右边对应的是Alphabet.vue组件,cities是对象,其key就是A   B   C等

 

为上面的组件添加逻辑------兄弟组件间联动

父子组件进行传递数据:使用$emit()

兄弟组件间联动

可以使用的方法有:

1)Vuex-----不同页面之间共享数据可以使用这种方法

2)子组件通过$emit()传给父组件,父组件在传给另外一个子组件,另外一个子组件通过props接收------同一个页面的不同组件可以使用这种方法----兄弟组件进行传递数值使用这种方法比较方便、简单(这里用这种方式

3)eventBus事件总线

 

点击右边的字母,跳到左边相应的字母中

1)在组件Alphabet.vue给<li>添加点击事件

当点击右边字母的时候,获取到e对象,通过e.target.innerText获取到该字母内容,然后通过$emit()将数据传递给父组件

2)在父组件City.vue中监听子组件Alphabet.vue中change事件

 

3)在父组件City.vue的data中定义letter属性默认值为空,然后在methods中定义handleLetterChange事件,当触发change事件时,就把获取到的数据赋值给this.letter,然后在子组件List.vue实例上绑定属性传递给子组件List.vue

data(){
	return {
		letter:''
	}
},methods:{
	handleLetterChange(letter){
		this.letter = letter
	}
}

4)在子组件List.vue中接受父组件传递过来的数据letter

5)此时子组件List.vue就接收到父组件City.vue传递过来的数据了,这时候需要通过watch对letter做一个监听,当其值发生变化的时候,就需要将点击右边的列表项中的字母与左边列表中的字母对应项显示出来

在DOM中绑定属性:ref="key",因为cities是对象,key的值对应的就算A   B   C,

然后js通过watch监听父组件City.vue传过来的letter,当letter有变化的时候,通过element = this.$refs[this.letter][0]获取到字母对应的DOM元素,然后调用better-scroll中的函数this.scroll.scrollToElement(element),将页面滚动到该元素位置

注意:由于DOM中是用v-for来书写DOM,所以通过this.$refs[this.letter]获取到的是一个只有一个元素的数组,所以写成this.$refs[this.letter][0]

这样就实现,点击左边字母,右边跳转到相应的字母的地方

 

功能-----拖动右边的字母表的时候,左边的字母也能跟着一起滚动

1)需要对右边字母表做滚动事件监听,子组件Alphabet.vue中的li绑定事件touchstart    touchmove   touchend

2)希望在touchstart之后再触发touchmove之后的内容,在data中定义标志类touchStatus,默认为false,在手指触摸开始之后修改其值为true,在结束touch之后,修改其值为false,只有在touchStatus为true时,才做一些move的处理

 

 

在右边字母上下滑动的时候,要获得现在处于第几个字母

思路:获得右边第一个字母距离页面顶部的距离,滑动的时候获得手指距离顶部的高度,两者做一个差值获得当前手指与第一个字母的距离,然后除以每一个字母的高度,就可以获得当前第几个字母了,获得该字母之后,触发change事件,将数据传递给外部

1)在 子组件Alphabet.vue定义计算属性数组letters,因为cities是对象,其属性key就是A   B  C.....,需要将key作为计算属性数组letters的值

2)可以将DOM 中的v-for数据改为用letters,每一个li用一个ref,用于在JS中获取到该元素

3)当处于滑动的时候,通过 startY = this.$refs['A'][0].offsetTop获取到字母A距离绿色底部的距离(因为li用v-for书写的,所以this.$refs['A'])是一个只有一个元素的数组

通过  e.touches[0].clientY 获取到手指距离 页面顶部的距离,touchY = e.touches[0].clientY - 绿色部分的高度,就是手指距离绿色底部的距离

每个字母高度是20,将index=Math.floor((touchY-startY)/20),就是手指指向数组letters里面对应的字母,然后通过this.$emit('change',this.letters[index])将当前字母传递给父组件

                                                               图一

4)在父组件已经定义change事件了,就可以实现滚动了,点击右边的字母,跳到左边相应的字母中---有写跳转的功能

 

列表切换性能优化

1)如图一所示的handleTouchMove(e)中的代码

问题:由于这个值是固定的,而每次执行这个方法的时候,都会运算一次,所以性能比较低

解决方法:在data中定义变量startY=0,在updated中更新该值this.startY=this.$refs['A'][0].offsetTop,当页面数据更新完成和页面渲染完成之后updated才执行,所以性能得到提升

图一的handleTouchMove(e)改写为:

2)代码性能:函数节流----当拖动右边的字母的时候,该函数handleTouchMove的执行频率是非常高的,通过函数节流,限制函数执行的频率---即将函数延迟一会在执行,如果在这次滑动还没有结束,又有一个滑动,那么就会清除上次滑动,触发当前滑动

在data中定义timer=null,然后改写handleTouchMove,当this.timer存在时则清除掉,否则创建timer,就执行代码放在定时器setTimeout()里面

 

实现搜索功能-----点击搜索框,输入城市名或者拼音的时候,能把搜索到的结果显示出来

1)Search.vue中DOM的内容

.search-content的布局如下:search-content用来显示搜索的结果

2)在input中对数据做一个绑定,data中定义keyword='',在 input中通过v-model和keyword做一个双向绑定

3)Search.vue中接受Search.vue实例传过来的数据,在父组件City.vue中定义cities

4)在子组件Search.vue中的props接收父组件City.vue传递过来的cities,并在data里面定义空数组list=[]用于存放和关键词一样的结果项,timer=null(函数节流用的)

5)在watch里面对keyword做一个监听,并且做一个函数节流的优化,数据结构如下

关键词和spell或者name匹配上,就放进result数组中

6)获取到列表项this.list,就可以在DOM中做v-for循环

到此,在搜索框输入关键词就可以在页面上显示出匹配的搜索内容了

对.search-item的css如下:

问题一:搜索出来的匹配项过多,一页显示不完全,可以使用better-scroll

DOM修改内容如下:

在mounted()中生成better-scroll实例对象

此时,多出的部分,通过滚动就可以显示出来了

问题二:当清空搜索框的关键词时,搜索结果还显示出来----实际上应该被清空

在对keyword做watch时,做一个判断,this.keyword为空时,将list=[],然后return掉

问题三:当没有匹配项的时候,页面没有任何提示

在ul中添加一个li,内容为没有找到匹配数据

问题四:这样书写,当有或者无数据的时候,这个li一直有显示

可以定义一个计算属性来控制其显示与否

DOM内容改成下面的形式:

问题五:这样书写,没有找到匹配数据的li一直显示,将城市选择一直覆盖掉

用keyword控制content-search的显示,当keyword有值的时候则显示search-content的内容,无则不显示

 

 

 

在路由中使用ajax获取数据---使用url中的查询参数

mounted(){
  this.getDetailInfo()
},methods:{
  getDetailInfo(){
    // 将解析到的参数值放到id里面
    axios.get('/api/detail.json',{
      params:{
        id:this.$route.params.id
      }
    }).then(this.handleGetDataSucc)
  },handleGetDataSucc(res){
    res= res.data
    console.log(res)
  }
}

 

使用vuex实现非兄弟组件之间的数据共享

功能-----点击City.vue中的城市之后,在首页的顶部显示对应的地点---也就是城市选择的数据由传递给首页

1)先安装Vuex在本地项目上,然后在src下创建store文件夹,在store下创建index.js,内容如下,有一一个公用数据city,默认值是北京

2)在src/main.js中将store引进来

3)在组件中使用引进来的store,在Header.vue中的DOM内容,通过{{this.$store.state.city}}获取到公用数据

4)City.vue中的当前城市,应该也是store中state.city的值

List.vue中的内容如下

 

5)当点击热门城市的时候,当前城市和首页右上角的城市会跟着变化

a)在List.vue中给每一个热门城市绑定点击事件---在组件中派发事件this.$store.dispatch(action,data)

b)在store/index.js中创建changeCity-----action用于commit   mutation的

c)在store中创建mutations,用于修改state

 

问题:当选择好了热门城市,比如‘三亚‘’,当刷新页面,又变成默认值了,而不是‘三亚’

解决方法:使用localStorage----在Vue中直接使用该localStorage对象

在mutations中的changeCity修改state的时候,将city存储为localStorage

而city的默认值分两种情况:当localStorage对象中有city时使用localStorage.city的值,否则为上海

 

问题:如果使用localStorage最好使用try...catch,以防出现页面报错的情况

将上面的代码修改为

 

将src/store/index.js中的代码进行拆分

1)在src/store下新建state.js,内容如下

2)在src/store/index.js中将state引进来

import state from './state.js'

3)在src/store/mutations.js文件中内容如下

4)在src/store/index.js中将mutations引进来

import mutations from './mutations.js'

 

代码的优化---在DOM中直接使用this.$store.state.city获取到数据,而是在computed中使用...mapState()来获取到数据

在methods中通过...mapMutations()将store中的action映射成component的methods

 

使用keep-alive优化网页 性能

问题:当前代码存在的一个问题就是,每次路由切换的时候,都会发送一次ajax请求(因为每次进入一个页面的时候,mounted都会被重新执行一次,ajax就会被执行),造成性能很低

1)在App.vue中给<router-view>添加<keep-alive>,路由的内容被加载一次之后,就把路由中的内容放到内存中,下一次进入路由中不需要重新渲染这个组件

2)在首页中,选择'桂林'时,页面显示的是桂林的内容,‘北京’时显示的是北京的内容,,,即当地点发生变化的时候,需要重新发送一次ajax请求

a)在Home.vue中发送ajax请求的时候,路由中的路径带一个参数city,即

b)在Home.vue中data定义一个lastCity数据

c)在挂载的时候,对lastCity赋值

d)当页面被重新激活的时候,在activated中书写逻辑功能,在Home.vue中的生命周期函数activated做一些处理------当前页面的城市和上一次页面显示的城市是否相同,不相同发一次ajax请求,并对lastCity进行更新

 

对全局事件解绑---本意是在其中一个固定的组件中,响应某一个特定的事件,结果在别的组件中也响应该事件,因为该事件绑定在全局中,并不是在某一个特定的组件中绑定

activated(){
  // 这个是全局事件
  window.addEventListener('scroll',this.handleScroll)
},methods:{
  handleScroll(){
    const top = document.documentElement.scrollTop
    if(top>60){
      let opacity = top/140
      opacity =opacity>1?1"opacity"
      this.opacityStyle = {opacity}
      this.showAbs = false
    }else{
      this.showAbs = true
    }
  }
}

在组件中添加声明周期函数deactivated,在里面对事件进行解绑

activated(){
  // 这个是全局事件
  window.addEventListener('scroll',deactivated(){
  // 当页面切换到别的页面时候,解绑该事件
  window.removeEventListener('scroll',methods:{
  handleScroll(){
    const top = document.documentElement.scrollTop
    if(top>60){
      let opacity = top/140
      opacity =opacity>1?1"opacity"
      this.opacityStyle = {opacity}
      this.showAbs = false
    }else{
      this.showAbs = true
    }
  }
}

递归组件------在组件的自身里面调用组价自身,name属性的作用,通过使用自己的名字来使用自己

数据形式,一般会有一个children属性

// 数据形式,一般包含children属性
{
  list: [{
    title:'成人票',
    children: [{
      title:'成人三馆联票'
    ]}
  },{
    title:'学生票',
  }]
}

调用形式

<template>
  <div>
    <div
      class="item"
      v-for="(item,index) of list"
      :key = "index"
    >
      <div class="item-title border-bottom">
        <span class="item-title-icon"></span>
        {{item.title}}
      </div>
      <div v-if="item.children">
        // 自身调用自身,这就是name属性的作用
        <detail-list :list="item.children"></detail-list>
      </div>
    </div>
  </div>
</template>

<script>
  export default{
    name:'DetailList'
  }
</script>

 

vue项目中的接口联调(即页面中请求的地址是线上的地址)

1)联调的时候,将项目根目录下的static/mock文件夹删掉,访问的是服务器中的文件,需要开启一个后台php服务器

2)在config/index.js中将proxyTable中的内容改成下面的形式

module.exports = {
  dev:{
    assetsSubDirectory:'static',assetsPublicPath:'/',proxyTable:{
      '/api':{
        // 内网的地址,或者域名
        // 不需要使用fiddler  charles
        target:'http://localhost:80'
      }
    }
  }
}

vue项目真机测试(可以在手机上输入ip地址进行页面的访问)

1)获取当前计算机的ip地址:

ipconfig

问题:在地址栏中输入:ip:8080页面显示拒绝访问,而localhost:8080却能显示,如果将端口换成80那么:ip:80,页面可以显示

地址栏输入ip:8080页面显示拒绝访问的原因:项目是通过webpack-dev-ser启动的,webpack-dev-server默认不通过ip的形式进行页面的访问,所以需要对默认配置进行修改

2)解决方法:在项目根目录下,打开package.json文件,在scripts属性中的dev添加内容

--host 0.0.0.0

3)重启项目:在地址栏中通过ip地址进行访问:ip:8080就可以访问到页面中的内容了

这时候可以用手机通过内网,通过ip地址访问网页

4)滚动字母表的时候,整个页面跟着滚动:这时候可以在touchstart中添加修饰符prevent

@touchstart.prevent="handleTouchStart"

5)在低版本的android中,可能存在页面白屏的现象(10-2)

 

 

 

vue项目的打包上线

1)在cmd中进入项目的目录

2)执行:npm run build------对src下的代码进行打包和编译,生成一个压缩后的能被浏览器识别的代码

3)打包完成之后,在项目根目录下会多出dist(index.html + static文件夹)文件夹,而dist目录中的内容就是要上线的内容

4)将dist目录中的代码放到后端服务器上的根目录下

5)此时在地址栏中输入localhost就可以直接输出网页的内容了

以上就是简单的项目打包上线过程

 

如果将打包出来的文件(index.html + static文件夹)放在后端服务器的根目录project文件夹中,然后在地址栏中输入localhost/project访问页面,需要在后端文件config/index.js文件进行配置

原文件内容如下

1)将assetsPublicPath中的内容改成如下所示:修改文件路径

assetsPublicPath:'project'

2)在cmd中重新打包:npm  run  build

3)将dist中的内容复制到服务器根目录下的project文件夹里面,就可以了

 

 

 

 

 

 

 

 

 

 

原文地址:https://blog.csdn.net/tangxiujiang

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


https://segmentfault.com/a/1190000022018995 https://www.jianshu.com/p/8c3599dda094 vuex教程中,有这样一句话和这样一段代码: 实践中,我们会经常用到 ES2015 的参数解构来简化代码(特别是我们需要调用commi
ES6 (ECMAScript 6)中的模块是一个包含 JavaScript 代码的文件,在这个模块中所有的变量都对其他模块是不可见的,除非我们导出它。 ES6的模块系统大致分为导出(export)和导入(import)两个模块。 1、模块导出(export) 可以 导出 所有的最外层 函数 、 类
from https://mp.weixin.qq.com/s/-rc1lYYlsfx-wR4mQmIIQQ Vue知识点汇总(含Vue3) 一、Vue 基础 1. Vue的基本原理 当一个Vue实例创建时,Vue会遍历data中的属性,用 Object.defineProperty(vue3.0使
D:\Temp&gt;npm init vite@latest vue3study --template vuenpm ERR! code ETIMEDOUTnpm ERR! errno ETIMEDOUTnpm ERR! network request to https://registry.np
文章浏览阅读1.2k次。最近自己从零撸起的甘特图组件需要子组件的滚动条同步滚动这就涉及到子组件之间的互相通信,通过 消息总线可以达到我们的需求 ,首先建立一个标志位,拖动左边滚动条的时候,右边的滚动条事件不处理,反之拖动右边滚动条时,左边的滚动条事件不做处理,建立一个公共的变量用于两者的互斥store.jsimport Vue from 'vue'export let store = Vue.observable({ scrollFlag: true})export let mutations =.._vue 能不能同时有两个滚动事件
文章浏览阅读3.3k次,点赞3次,收藏16次。静默打印是什么?简单来说就是不需要用户点击"打印",自动去打印,但是使用浏览器web打印不可避免的要弹出以下画面面对这种问题也只能用"富客户端"技术来解决,在浏览器的沙盒安全模型中无法做到,那么只能使用插件的技术,这个我们就不自己花力气去做了,我找来了 lodop 这个免费的打印组件,功能还是挺强大的,下载下图的发行包解压后安装下图两个exe如果你的系统是64位的,可以安装install_lodop64.exe上图的LodopFuncs.js 是客户端要使用的核心库文件..._this.$getlodop().then((lodop) =>{
文章浏览阅读1.7k次。个人觉得大屏展示其实很简单,噱头多过技术含量,下面使用了 DataV (不是阿里的那个DataV哈,具体链接在这里)开发了一个大屏展示,使用了css flex弹性布局,使用了DataV的一些比较酷炫的边框(SVG写的),基本上功能没有全部完成,但是模子已经刻出来了,只是后端推送的内容没有全部写出来前端<template> <dv-full-screen-container class="screen-container"> <div class="ti_用signalr做一个简单的实时大屏显示
文章浏览阅读3.4k次,点赞3次,收藏10次。【说明】导入的Excel 字体颜色和背景色只能识别【标准色】,别的如"主题颜色",exceljs 解析出来不是颜色值。导入的样式包括字体,字号,列宽,合并单元格,【部分能识别】的背景色,文字颜色。导入到 x-data-spreadsheet 如下图。原Excel样式如下。_x-data-spreadsheet
文章浏览阅读1.7k次。之前参考某文章把 router-view 放在 el-tab-pane 外面都不起作用,问题根本不是出在 el-tab-pane,而是v-for 里面有多个route-view , keep-alive 时 tab 并未销毁掉,而是缓存隐藏了起来。需要把 router-view 的 name 与路由的 index.js 名称对应起来。之前参照很多文章修改试图修正这个问题,结果都徒劳,终于让我找到。我做了如下修改,主页面 main.vue。_el-tab-pane 后面接router-view
文章浏览阅读533次。今天在一台虚拟机上面运行老项目,报各种类型上图的错误提示,一开始还以为是less的问题,结果一个个装完还是报错,后面又说webpack, webpack cli有问题,头有点大了,google 一下,发现一个命令。讨论这个命令的文章,可以了解一下。运行以后终于出现了期待已久的。_npm install 忽略依赖
文章浏览阅读8k次,点赞3次,收藏12次。从这篇文章得到启发先定义一个组件从外部接收Template,然后在组件里调用<template > <div ref="markedContent"></div></template><script>import Vue from 'vue/dist/vue.esm.js'export default { name: 'wf-marked-content', props: ['content'], mounte.._vue components 动态传入模板
文章浏览阅读5.4k次。参考上一篇知识开发的一个功能,制作一个打印模板的管理模块,如下(就是保存froala编辑后的html文本,其中包括Vue的Template,这样我们可以利用Vue的模板的优势来动态绑定一些数据源进行HTML的打印,基本上跟过去水晶报表做一个模板再绑定数据源的方法异曲同工)在 main.js 里引用 froala 组件// Import and use Vue Froala lib.import VueFroala from 'vue-froala-wysiwyg'// 引入 Fr.._vue设计网页打印模板
文章浏览阅读992次。计划是这样,公司的项目一直在持续改动,安装包总是需要频繁生成新的,由此我想到了"持续集成"!有自动化工具不用,岂不可惜?这周的主要时间就用来学习CruiseControl.Net全面实现持续集成_怎么在vue的 script部分使用 eldigloa
文章浏览阅读1.2k次。其实Element UI 只用了文字提示的 el-tooltip 组件,不喜欢可以去掉,不记得是从哪拿到的原始代码,我给加了高亮渐变显示,图标,和拖拽时只能拖拽图标的位置,效果如上图,可以水平方向拖动,也可以垂直方向拖动。样式是less写的,css写嵌套样式太繁琐了。拿来主义,改造有理!下面贴代码<template> <div ref="splitPane" class="split-pane" :class="direction" :"{ fl..._element ui拉条样式
文章浏览阅读953次,点赞2次,收藏2次。接上一篇,这次加入的是从x-speadsheet导出Excel,并且带有x-speadsheet中的样式,重点关注 exportExcel 这个方法,我加入了 tinycolor 这个库用来翻译颜色值,值得注意的是, exceljs的颜色值是 argb 不是 rgba,一定不要弄混了a 是代表的透明度放在最前面_x-data-spreadsheet 导出
文章浏览阅读5.5k次,点赞2次,收藏21次。尝试了两个连线库 jsplumb 和 leadline ,其实两个库都很强大,但是基于个人使用的习惯,决定还是用 leadline ,在Vue 下我使用它的一个包装库 leader-line-vue 下面是上图的连接线示例代码,连接线很轻松的就实现了一个渐变效果..._vue 连线
文章浏览阅读4.2k次,点赞2次,收藏5次。首先官网推荐的安装方法没有生成dist文件,导致样式表等这些文件并没有生成npm install element-plus --save以上方法是有问题的,如果不幸执行了上面的命令,那么先执行卸载npm uninstall element-plus删除 main.js文件对element ui的引用,输入以下命令vue add element-plus..._elementui3.0
文章浏览阅读3.1k次。如上图,下面贴代码<template> <div> <el-date-picker size="large" style ="width:120px" v-model="selectYear" format="yyyy 年" value-format="yyyy" type="year" :clearable = "false" placeholder="选择年">.._vue多选周
文章浏览阅读1.8k次,点赞6次,收藏6次。经过 2021年的一个春节,从年前到现在,大致撸出一个 甘特图,进度条是用SVG画的,使用了几个工具库 (interactjs 用来处理拖拽和修改尺寸,snap.svg 用来处理 svg 的dom 操作,moment.js用来处理时间的操作),其他没有依赖任何的UI组件,目前初见雏形,还比较粗糙,后面会不断更新源码地址点击期间也摸索了怎么把vs code的项目上传到 GitHub 上面进行源代码的管理,基本上是参考的这篇文章做的..._vue gantt demo
文章浏览阅读2.1k次。接上两篇vue 下使用 exceljs + x-spreadsheet 带样式导入Excelvue 下使用 exceljs + x-spreadsheet 带样式导出Excel下面封装好一个组件调用组件的页面效果如图,目前“导出Json”还没有做_x-spreadsheet导入导出