Vue

vue nuxt组建注册

月盾

Nuxt.js 2.13+可以扫描并自动导入您的组件,不再需要在该script部分中手动导入它们!

nuxt.config配置:

export default {
  components: true
}

设置为true或使用对象时,它将包含nuxt / components依赖项,并且~/components在模板中使用它们时会自动导入您的组件。

组件目录:

components/
  ComponentFoo.vue
  ComponentBar.vue

使用

<template>
  <ComponentFoo />
  <component-bar />
</template>

注意:如果使用nuxt 2.10…2.13,则还必须手动安装并添加@nuxt/components到buildModulesinside nuxt.config。

vue子组件修改父组件的数据

月盾

vue在子组件中直接修改父组件传递下来的数据会报错: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "json"

原因是vue子组件不能直接修改父组件的数据,可以使用this.$emit发送通知,让父组件来修改。 示例代码:

子组件:

this.$emit("changeData", "要修改的数据");

父组件:

<mycomponent :json="JsonData" @changeData="changeData"></mycomponent>

data(){
    return {
		JsonData:{}
	}
}
methods:{
    changeData(newData){
	    this.JsonData = newData;
	}
}

子组件发送changeData事件, 父组件绑定changeData事件并接受数据,赋值给父组件的JsonData属性,子组件的值也会改变。从而实现子组件修改父组件的属性值。

你是拿锤子的前端开发吗?

月盾

前言

接上篇《说道说道前后端分离》今天再次对前端现状作一次分析(吐槽)。

再次引用一句《穷查理宝典》中的理论:

在手里拿着锤子的人看来,所有的东西都会是钉子。

因为有锤子的关系,遇到任何问题,都会先想如何用锤子解决。久而久之,陷入了一种思维定式。任何工具带来便利的同时,也带来了局限性。而这往往是用锤子的人很难看到的。

事出有因

这种现状在开发圈内决不少见,不仅限于前端。本文只说说前端的现状,原因是笔者最近在工作中遇到一个棘手的问题:性能优化。

最近接手了多个现有的前端项目,是公司比较核心的移动端官网,作为门户网站访问量和用户量都比较大,但是随着项目的迭代出现了性能问题,页面加载速度在WiFi网络下达到3s,3G网络15s以上,更差的网络40s+。加载的资源小则3M,大则6M。如果一切往好处想,假设所有用户使用最好的网络,用户和公司都不在乎流量费,两三秒的加载速度也还挺快的,每次打开页面费个3M流量也不是个事。但如果考虑这些问题的话就会发现这不是小问题。

对以上问题分析得出结论之一:资源过大,有兴趣的可以打开淘宝网看下首屏资源做下对比,可以看到资源不超过3M,时间不超过2s。

而我们一个移动端网站的资源居然能超过3M,究其原因:

  • 图片大
  • js大
  • css大

图片大是因为图片基本没任何大小控制,都是使用了最高标准原图。js和css大基本是属于架构问题,一个项目中包含的上百的页面每个页面600多k的js是绕不过去的(vendor.js,app.js等打包资源,不包含其他引入资源)。

看到vendor.js,app.js这两个名称很多人应该想到了,这是vue(react)框架开发的网站。 是的,就是用vue开发的移动端网站,使用vue开发网站本身也不是什么大问题,毕竟有实力的公司不需要SEO,直接竞价排名就行。而我要说的问题是,不是什么网站都可以用vue来开发,不信请继续往下看。

问题分析

我司的移动端网站作用并不仅仅是用来展示公司形象的,更重要的是用户转化的,就是让用户注册的。而且是要和很多第三方机构合作投放引流,经常需要分析页面UI的不同对转化率的影响,所以需要的页面不是几个,而是几十上百个,还在不停增加,每周都有三五个页面增加。 由于vue主要是以开发单页SPA应用为主的,在开发人员不考虑真实需求的情况下自然会使用流行的技术,最终把网站开发成一个单页应用。单页应用的特点就是单页,就是把不同的页面做成一个页面一次加载,加载完成后页面之间的切换就会很快,一般无需再加载资源,用户体验也会好很多,可以套用一句话:“一次等待,处处快速”。

这个特点在管理后台项目中很合适,但是在只需要展示一次的项目中也合适吗?不合适。

我们的网站项目是用来做很多落地页的,各个落地页之间没有关联性,不会A页面跳到B页面,从B页面跳到C页面,A页面中不需要B页面的资源,B页面也不需要C页面的资源。然而vue项目打包的时候会把每个页面独有的一些资源都融合在一起,形成公共资源。结果就显而易见了,一个页面总要加载一堆无关资源,不仅资源大,还有很长的白屏时间,用户体验下降。

还有一点不该使用单页应用的原因是我们的页面是纯展示的页面,不需要很多数据交互,vue能起到什么作用?操作数据?驱动UI?模块化?通通不需要。现代html可以不借助第三方库和框架的情况下完全能实现。

结论

JavaScript 的最大优势之一是它不需要编译,所以可以在浏览器中直接运行。这样你就可以立刻获得编码的反馈。入门门槛很低;你只需一个文本编辑器和一个浏览器就能编写软件了。 不幸的是,这种简单性和可访问性已被称为过度工具链的风气破坏了。这种风气已经将 JavaScript 的开发工作变成了一场噩梦。我甚至看过一整套关于配置 Webpack 的课程。这种乱象需要有个尽头——生命苦短啊。

VUE,React这类框架用于构建应用方面很合适,但不太适合构建网站。应用是需要有较多的UI和数据方面的交互,而网站则更多的是信息展示,你可能根本不需要JavaScript(框架)。

追求新技术可以让我们获得新奇感,成就感,解决老问题,而不是带来新问题。复杂性才是造成软件问题的根本原因。——试问:离开框架的你还会开发网站吗?

webpack构建vue项目警告

月盾
bundle.js:935 [Vue warn]: You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build.

(found in <Root>)

解决方案:与entry属性平级添加

resolve: {
        alias: {
            'vue$': 'vue/dist/vue.esm.js'
			//该路径为node_modules下的vue目录
        }
    }
// 需要编译器
new Vue({
  template: '<div>{{ hi }}</div>'
})

// 不需要编译器
new Vue({
  render (h) {
    return h('div', this.hi)
  }
})

出现警告的原因是使用了template属性。 文文点到为止,详情请直接访问中文官方文档https://cn.vuejs.org/v2/guide/installation.html#对不同构建版本的解释

vue.js做的应用中点击搜索功能会改变URI

月盾

用vue.js做的后台管理系统,有一个列表搜索功能,正常登陆进去,直接点击搜索功能,页面就会刷新一遍,原因是url地址变化了

原本地址是:
http://www.mydomain/#!/index
点击搜索以后就变成了
http://www.mydomain/?#!/index

在#!前面自动加了?,导致页面刷新一遍,这样第一次搜索就没意义了.

经过初步排查后发现点击其他按钮不会改变URL地址,对比后发现搜索按钮的type=“submit”,可能是提交表单导致跳转了,那么将type改为button或者直接去掉试试,结果还是不行,干脆也改为标签(加了bootstrap按钮样式),结果好了。为什么将button type改为button不行呢,原因是在标签内标签type会被默认当做submit,(IE浏览器默认type=button)

vue.js click点击事件获取当前元素对象

月盾

Vue.js可以传递$event对象

<body id="app">
  <ul>
	<li v-on:click="say('hello!', $event)">点击当前行文本</li>
	<li>li2</li>
	<li>li3</li>
  </ul>
  <script>
   new Vue({
	   el: '#app',
	   data: {
		message: 'Hello Vue.js!'
	   },
	   methods: {
		say: function(msg, event) {
		   //获取点击对象
		   var el = event.currentTarget;
		   alert("当前对象的内容:"+el.innerHTML);
		}
	}
   })
  </script>
 </body>

函数调用处传递$event

v-on:click="say('hello!', $event)"

函数中获取到的event.currentTarget对象就是当前元素

在线示例

请查看HTML页面示例源码

vue.js对表单值初始化

月盾

新建表单有些input输入框需要默认值,比如性别需要一个男或女默认值。再比如一个日期选择框需要默认今天。如果按照HTML的方式设置不会起作用

<input type="radio" name="gender" value="0" checked="checked" v-model="gender">男
<input type="radio" name="gender" value="1" v-model="gender">女
<input type="date" value="2016-01-06" v-model="date">

在vue.js页面中上面这种设置方式是不会起作用的,性别不会选中,日期也不会有值。解决办法是对v-model属性设值,在初始化时给gender=0,那么默认会选中性别男,给date=“2016-01-06"日期控件也有值。

vue.js中使用focus,blur事件

月盾

在线示例

使用focus,blur可对表单进行验证,除了这两个事件,还有一个watch属性可监听data属性值得变化,具体可打开浏览器控制台看属性值得变化情况,代码可直接在浏览器中查看源码

vue.js开发gulp监听文件变化自动编译

月盾

直接看代码:

var gulp = require('gulp')
var webpack = require("gulp-webpack");
var webpackConfig = require("./webpack.config.js");
// gulp.task("webpack", function(callback) {
//   var myConfig = Object.create(webpackConfig);
//   webpack(myConfig, function(err, stats) {
//           console.log(">>>>>err:"+JSON.stringify(err))
//           console.log(">>>>>stats:"+stats)
//         if(err) throw new Error("webpack", err);
//         callback();
//     });
// });

/**
 * 编译时有错误提示
 */
gulp.task("webpack", function(){
    return gulp.src("./app.js")
    .pipe(webpack(Object.create(webpackConfig)))
    .pipe(gulp.dest("./dist/"))
});

gulp.watch('./views/*', ['webpack']);

webpack.config.js配置

var webpack = require("webpack");
module.exports = {
    entry: //"./app.js",
        {
            app:"./app.js"
            // vendor: ["./javascripts/test"]
        },
    output: {
        path: __dirname + "/dist/",
        filename: "bundle.js"
    },
    module: {
        loaders: [
            {
                test: /\.scss$/,
                loaders: ['style', 'css', 'sass']
            },
            //{ test: /\.css$/, loader: "style!css" },
            { test: /\.vue$/, loader: 'vue-loader'},
            { test: /\.(jpg|png|gif)$/, loader: "file-loader?name=images/[hash].[ext]"}
        ]
    },
    // devtool: '#source-map',
    // plugins:[
    //     new webpack.optimize.CommonsChunkPlugin({
    //         name: "vendor",//和上面配置的入口对应
    //         filename: "common.js"//导出的文件的名称
    //     })
    // ]
};

不得不承认自己还是有很多不知道的配置,刚发表完本文就得知一种更高效的方式:直接用webpack自带的监听参数:>webpack -w即可实现,并且编译速度更快,从几秒降到了毫秒。