欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 前端技术 > vue >内容正文

vue

步步向前之vue

发布时间:2025/7/25 vue 62 豆豆
生活随笔 收集整理的这篇文章主要介绍了 步步向前之vue 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

疑难杂症

vue改造多页面应用配置注意问题(踩了神坑...)

首先修改webpack配置,文章很多,主要参考这篇链接vue多页面开发
不想移步的童鞋来:

  • 在util.js里面尾部直接加入

    /* 这里是添加的部分 ---------------------------- 开始 */// glob是webpack安装时依赖的一个第三方模块,还模块允许你使用 *等符号, 例如lib/*.js就是获取lib文件夹下的所有js后缀名的文件var glob = require('glob')// 页面模板var HtmlWebpackPlugin = require('html-webpack-plugin')// 取得相应的页面路径,因为之前的配置,所以是src文件夹下的pages文件夹var PAGE_PATH = path.resolve(__dirname, '../src/pages')// 用于做相应的merge处理var merge = require('webpack-merge')//多入口配置// 通过glob模块读取pages文件夹下的所有对应文件夹下的js后缀文件,如果该文件存在// 那么就作为入口处理exports.entries = function () {var entryFiles = glob.sync(PAGE_PATH + '/*/*.js')var map = {}entryFiles.forEach((filePath) => {var filename = filePath.substring(filePath.lastIndexOf('\/') + 1, filePath.lastIndexOf('.'))map[filename] = filePath})return map}//多页面输出配置// 与上面的多页面入口配置相同,读取pages文件夹下的对应的html后缀文件,然后放入数组中exports.htmlPlugin = function () {let entryHtml = glob.sync(PAGE_PATH + '/*/*.html')let arr = []entryHtml.forEach((filePath) => {let filename = filePath.substring(filePath.lastIndexOf('\/') + 1, filePath.lastIndexOf('.'))let conf = {// 模板来源template: filePath,// 文件名称filename: filename + '.html',// 页面模板需要加对应的js脚本,如果不加这行则每个页面都会引入所有的js脚本chunks: ['manifest', 'vendor', filename],inject: true}if (process.env.NODE_ENV === 'production') {conf = merge(conf, {minify: {removeComments: true,collapseWhitespace: true,removeAttributeQuotes: true},chunksSortMode: 'dependency'})}arr.push(new HtmlWebpackPlugin(conf))})return arr}/* 这里是添加的部分 ---------------------------- 结束 */
  • webpack.base.conf.js 文件

    /* 修改部分 ---------------- 开始 */entry: utils.entries(),/* 修改部分 ---------------- 结束 */
  • webpack.dev.conf.js 文件

    /* 注释这个区域的文件 ------------- 开始 */// new HtmlWebpackPlugin({// filename: 'index.html',// template: 'index.html',// inject: true// }),/* 注释这个区域的文件 ------------- 结束 */new FriendlyErrorsPlugin()//**注意我在新版本生成的这里是保存static目录的东西不用在意**new CopyWebpackPlugin([{from: path.resolve(__dirname, '../static'),to: config.dev.assetsSubDirectory,ignore: ['.*']}])/* 添加 .concat(utils.htmlPlugin()) ------------------ */].concat(utils.htmlPlugin())
  • webpack.prod.conf.js 文件

    /* 注释这个区域的内容 ---------------------- 开始 */// new HtmlWebpackPlugin({// filename: config.build.index,// template: 'index.html',// inject: true,// minify: {// removeComments: true,// collapseWhitespace: true,// removeAttributeQuotes: true// // more options:// // https://github.com/kangax/html-minifier#options-quick-reference// },// // necessary to consistently work with multiple chunks via CommonsChunkPlugin// chunksSortMode: 'dependency'// }),/* 注释这个区域的内容 ---------------------- 结束 */// copy custom static assetsnew CopyWebpackPlugin([{from: path.resolve(__dirname, '../static'),to: config.build.assetsSubDirectory,ignore: ['.*']}])/* 该位置添加 .concat(utils.htmlPlugin()) ------------------- */].concat(utils.htmlPlugin())
  • 改造目录

    值得注意的是:这里的js一定要和html名称一样,我因为这个不一样,卡了好久,在别的地方有说必须是App.vue的,这个如图,我没用,测试界面正常显示,但是我把默认main.js直接移动到文件夹里时,index.html一直是空白页,把main.js改为index.js正常,如果有问题我还会探究改正
  • 访问方式

    • http://localhost:8080/login.html
    • http://localhost:8080/index.html
  • 修改config目录下的assetsPublicPath路径的问题

    相信很多人都查过npm run build后空白页的问题然后修改assetsPublicPath的值/为./,然而这里改的话,所有页面都会无法获取,cannot get,此处困扰我三天,一度令我觉得自己不适合这行,适合喝西北风,本来就新手学vue,也没什么资源,这里解决了,但build后的问题呢,未完待续,先调好开发效果,步步为营吧
  • 全局使用axios

    • 结合 vue-axios使用

      import axios from 'axios' import VueAxios from 'vue-axios'Vue.use(VueAxios,axios);getNewsList(){this.axios.get('api/getNewsList').then((response)=>{this.newsList=response.data.data;}).catch((response)=>{console.log(response);}) },
    • axios 改写为 Vue 的原型属性

      首先在主入口文件main.js中引用,之后挂在vue的原型链上

      import axios from 'axios'Vue.prototype.$ajax= axios

      在组件中使用

      this.$ajax.get('api/getNewsList').then((response)=>{this.newsList=response.data.data;}).catch((response)=>{console.log(response);})
    • 结合 Vuex的action

      在vuex的仓库文件store.js中引用,使用action添加方法

      import Vue from 'Vue'import Vuex from 'vuex'import axios from 'axios'Vue.use(Vuex)const store = new Vuex.Store({// 定义状态state: {user: {name: 'xiaoming'}},actions: {// 封装一个 ajax 方法login (context) {axios({method: 'post',url: '/user',data: context.state.user})}}})export default store

      在组件中发送请求的时候,需要使用 this.$store.dispatch

      methods: {submitForm () {this.$store.dispatch('login')}}

    关于新版vue-cli安装json-server在build文件里没生成出dev-server文件

    新版的vue-cli取消了dev-server.js和dev-client.js 改用webpack.dev.conf.js代替,所以 配置本地访问在webpack.dev.conf.js里配置即可

    打开webpack.dev.conf.js,(在build目录下),

    在const portfinder = require(‘portfinder’)后添加以下两行代码

    const appData = require('./db.json')//加载本地数据文件 const seller = appData.seller//获取对应的本地数据,

    添加完以上代码继续在此文件里面向下查找devServer:{ }

    在这个对象里添加配置,(不要删除或覆盖以前默认配置的值)

    before(app) {app.get('/api/seller', (req, res) => {res.json({errno:0,data: seller})}) }, 每更改过webpack.dev.conf.js这个文件或者db.json文件,记得重新 npm run dev

    express启动数据服务模拟post请求

    * `config`目录下的`index.js`,修改`dev`中的`proxyTable`为: proxyTable: {'/api/': 'http://localhost:3000/'} * `build`目录下`webpack.dev.conf.js`文件增加 // express配置servervar express = require('express')var apiServer = express()var bodyParser = require('body-parser')apiServer.use(bodyParser.urlencoded({ extended: true }))apiServer.use(bodyParser.json())var apiRouter = express.Router()var fs = require('fs')//apiName是你请求的方法/数据集合 不要动apiRouter.route('/:apiName') //接口路径 .all(function (req, res) {fs.readFile('./data.json', 'utf8', function (err, data) { //读取接口文件console.log(err)if (err) throw errvar data = JSON.parse(data)if (data[req.params.apiName]) {res.json(data[req.params.apiName])} else {res.send('no such api name')}})})apiServer.use('/api', apiRouter);apiServer.listen(3000, function (err) {if (err) {console.log(err)return}console.log('Listening at http://localhost:' + 3000 + '\n')}) * 修改build目录下webpack.dev.conf.js文件中的devServer,增加:// Invalid Host header问题修复disableHostCheck: true 测试地址:`http://localhost:8080/apiPost/getNewsList` 这里的请求get和post都适用

    Vue中的图片资源的引入

    • css、template中的图片静态路径可正常写入,webpack可正常打包
    • js即放在script中的图片路径必须使用require引入,否则webpack打包时将无法识别这些资源,包括template中v-bind或:绑定的值,例如:

      data () {return {slides: {src: require('../assets/slideShow/pic1.jpg'), //requiretitle: 'xxx1',href: 'detail/analysis'}}}

    设置props默认值报错

    父子组件的值的传递在vue中很常用到,设置props的默认值时会遇到以下错误:

    props: {selections: {type: Array,default: [{label: 'test',value: 0}]}}

    报错: Props with type Object/Array must use a factory function to return the defaut value
    翻译过来就是 对象或数组的属性默认值必须以一个工厂函数返回
    也就是类似组件中data声明一样

    data () {return {} }

    以上属性值应修改为:

    props: {selections: {type: Array,default () {return [{label: 'test',value: 0}]}}}

    使用事件抛出一个值$event

    有的时候用一个事件来抛出一个特定的值是非常有用的。例如我们可能想让 <blog-post> 组件决定它的文本要放大多少。这时可以使用 $emit 的第二个参数来提供这个值:

    <button v-on:click="$emit('enlarge-text', 0.1)">Enlarge text </button>

    然后当在父级组件监听这个事件的时候,我们可以通过 $event 访问到被抛出的这个值:

    <blog-post...v-on:enlarge-text="postFontSize += $event" ></blog-post>

    或者,如果这个事件处理函数是一个方法

    <blog-post...v-on:enlarge-text="onEnlargeText" ></blog-post>

    那么这个值将会作为第一个参数传入这个方法:

    methods: {onEnlargeText: function (enlargeAmount) {this.postFontSize += enlargeAmount} }

    问题来了,当你需要在事件处理函数中既要传入子组件抛出的值,又想再传入其他参数呢?

    <blog-post...v-on:enlarge-text="onEnlargeText(index, $event)"></blog-post>

    vue项目根目录下index.html引入公共样式如reset.css注意事项

    index.html不能引入src里的文件,src里文件的会用webpack打包。webpack在开发时把static的文件复制到电脑内存里,打包时会复制到static目录下,因此建议非要在页面头部引入的话可以放在static目录下,或者可以选择在main.js使用import导入

    例如:

    <link rel="stylesheet" type="text/css" href="./static/reset.css">

    或者

    // main.js import './common/style/reset.css'

    vue项目localhost可以访问,IP地址替换后无法访问的问题

    vue生成的项目启动地址默认在http://localhost:8080/#,但若将开发移动端则需在手机上测试效果,以前总是知道hbulider有本地外置服务器手机扫码可以访问项目,Vue则需修改根目录下/config/index.js:

    host: '0.0.0.0', // can be overwritten by process.env.HOST

    便可支持ip访问地址,手机在同局域网下就可以预览了

    vue各个生命周期该干什么

    • beforecreate : 可以在这加个loading事件
    • created :在这结束loading,还做一些初始化,data已渲染,也可以在这里发送请求获取页面初始数据,实现函数自执行
    • mounted : 在这发起axios请求,拿回数据,配合路由钩子做一些事情
    • beforeDestory: destoryed :当前组件已被删除,清空相关内容

    附生命周期图:

    Vue中使用less给元素添加背景图片出现的问题

    按照less官方文档,url应当如下使用:

    URLs // Variables @images: "../img";// Usage body {color: #444;background: url("@{images}/white-sand.png"); }

    故而有了根据屏幕分辨率设置背景图片代码

    .bg-image(@url) {background-image: url('@{url}@2x.png');@media (-webkit-min-device-pixel-ratio: 3),(min-device-pixel-ratio: 3){background-image: url('@{url}@3x.png');} } // 报错报错 找不到路径的 这里要使用“~”符号来告诉less引号里面的内容不需要编译。

    正确代码:

    .bg-image(@url) {background-image:~"url('@{url}@2x.png')";@media (-webkit-min-device-pixel-ratio: 3), (min-device-pixel-ratio: 3) {background-image: ~"url('@{url}@3x.png')";} }

    如果组件里用使用计时器

    // 在组件销毁时(即切换组件或关闭页面), // 调用destroyed方法清除计时器 destroyed(){clearTimeout(this.timer) }

    向子组件传递props值为Array或Object时的默认值设置

    不能直接设置为[]或{},最好应设置为一个函数,比如:

    {type: Object,default () {return {}}

    vue 侦听器 watch 检查 对象键值的变化

    先来看官方教程对watch的示例应用:

    watch: {firstName: function (val) {this.fullName = val + ' ' + this.lastName},lastName: function (val) {this.fullName = this.firstName + ' ' + val}}

    但是如果监听的是data中的对象类型的值,直接用就不妥了。
    受现代 JavaScript 的限制 (以及废弃 Object.observe),Vue 不能检测到对象属性的添加或删除。由于 Vue 会在初始化实例时对属性执行 getter/setter 转化过程,所以属性必须在 data 对象上存在才能让 Vue 转换它,这样才能让它是响应的。

    sell: { //事件函数名称必须是`handler`!!!handler(val) {if (Number(this.availSymbol)) {this.sellQuanPro = Math.round(val.quantity / this.availSymbol * 100) > 100 ? 100 : Math.round(val.quantity / this.availSymbol * 100);}},deep: true, //深度递归查看对象immediate: true, //开始时便加载一次该函数}, 事件函数名称必须是handler!!!

    这样监听了对象所有键值,性能开销大,解决方案:用字符串

    如下:

    'sell.price': {handler(val) {console.log('TCL: handler -> val', val); //这里`val`是`sell.price`而不是`sell`}}

    未完待续

    总结

    以上是生活随笔为你收集整理的步步向前之vue的全部内容,希望文章能够帮你解决所遇到的问题。

    如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。