详解Nuxt.js 实战集锦

读本文前,请先熟读nuxt官方文档,并且具备一定的vue.js相关开发经验

中文文档
英文文档
vue SSR指南

一、CSR和SSR对比

SPA之前的时代,我们传统的Web架构大都是SSR,如:Wordpress(PHP)JSP技术、JavaWeb等这些程序都是传统典型的SSR架构,即:服务端取出数据和模板组合生成 html输出给前端,前端发生请求时,重新向服务端请求html资源。

SPA(CSR):

SPA应用,到了VueReact,单页面应用优秀的用户体验,逐渐成为了主流,页面整体是javaScript渲染出来的,称之为客户端渲染CSRSPA渲染过程。由客户端访问URL发送请求到服务端,返回HTML结构(但是SPA的返回的HTML结构是非常的小的,只有一个基本的结构)。客户端接收到返回结果之后,在客户端开始渲染HTML,渲染时执行对应javaScript,最后渲染template,渲染完成之后,再次向服务端发送数据请求,注意这里时数据请求,服务端返回json格式数据。客户端接收数据,然后完成最终渲染。

CSR原理图

CSR多数是基于webpack构建的项目,编译出来的html文件,资源文件都被打包到js中,这样的页面是不利于搜索引擎优化(SEO, Search Engine Optimization),并且内容到达时间(time-to-content) (或称之为首屏渲染时长)也有很大的优化空间

简单来讲,SPA虽然给服务器减轻了压力,也存在比较明显的两个缺点:

  • 首屏渲染时间比较长:必须等待JavaScript加载完毕,并且执行完毕,才能渲染出首屏。
  • SEO不友好:爬虫只能拿到一个div元素,认为页面是空的,不利于SEO

什么是SEO呢?SEO即通过各种技术(手段)来确保,你的Web内容被搜素引擎最大化收录,最大化提高权重,带来更多流量。大部分的搜索引擎仅能抓取URI直接输出的数据资源,对于 Ajax 类的异步请求的数据无法抓取

因此,对于那些展示宣传型页面,如官网,必须进行服务端渲染

SSR:

为了解决如上两个问题,出现了SSR解决方案,后端渲染出首屏的DOM结构返回,前端拿到内容带上首屏,后续的页面操作,再用单页面路由和渲染,称之为服务端渲染(SSR)

SSR渲染流程是这样的,客户端发送URL请求到服务端,在服务端做出html数据的渲染,渲染完成之后返回html结构,客户端拿到页面的html结构渲染首屏。所以用户在浏览首屏的时候速度会很快,因为客户端不需要再次发送ajax请求。并不是做了SSR我们的页面就不属于SPA应用了,它仍然是一个独立的spa应用。

SSR原理图

SSR是处于CSRSPA应用之间的一个折中的方案,在渲染首屏的时候在服务端做出了渲染,注意仅仅是首屏,其他页面还是需要在客户端渲染的,在服务端接收到请求之后并且渲染出首屏页面,会携带着剩余的路由信息预留给客户端去渲染其他路由的页面。

vueSSR

将本来要放在浏览器执行创建的组件,放到服务端先创建好,然后生成对应的html将它们直接发送到浏览器,最后将这些静态标记"激活"为客户端上完全可交互的应用程序。

在浏览器第一次访问某个URI资源的时候(首屏),Web服务器根据路由拿到对应数据渲染并输出,且输出的数据中包含两部分:

  • 路由页对应的页面及已渲染好的数据
  • 完整的SPA程序代码

在首屏渲染完成之后,此时我们看到的其实已经是一个和之前的SPA相差无几的应用程序了,接下来我们进行的任何操作都只是客户端的应用进行交互,页面/组件由Web端渲染,路由也由浏览器控制,用户只需要和当前浏览器内的应用打交道就可以了。

vueSSR原理图

webpackSource 打包出两个bundle文件:其中 Server Bundle用于服务端渲染,服务端通过渲染器 bundleRendererbundle 生成首屏html片段;而 Client Bundle 用于客户端渲染,首屏外的交互和数据处理还是需要浏览器执行 Client Bundle 来完成

缺点:

  • 开发条件所限。浏览器特定的代码,只能在某些生命周期钩子函数(lifecycle hook)中使用;一些外部扩展库(external library)可能需要特殊处理,才能在服务器渲染应用程序中运行。
  • 更多的服务器端负载。在 Node.js 中渲染完整的应用程序,显然会比仅仅提供静态文件的 server 更加大量占用 CPU 资源,因此如果你预料在高流量环境(high traffic)下使用,请准备相应的服务器负载,并明智地采用缓存策略。

二、nuxt.js介绍

1. nuxt.js是什么?

Nuxt.jsvue官方推荐的一个基于 Vue.js的做Vue SSR的通用应用框架(开箱即用),集成了Vue,Vue-Router,Vuex,Vue-Meta等组件/框架,内置了webpack用于自动化构建,使我们可以更快速地搭建一个具有服务端渲染能力的应用。

2. nuxt.js的优势?

作为框架,Nuxt.js 为 客户端/服务端 这种典型的应用架构模式提供了许多有用的特性,例如异步数据加载、中间件支持、布局支持等。Nuxt.js 有以下比较明显的特性

  • 支持各种样式预编译器SASS,LESS等等
  • 本地开发支持热加载
  • HTML头部标签管理(依赖vue-meta实现)
  • 自动代码分层
  • 强大的路由功能,支持异步数据(路由无需额外配置)
  • 内置 webpack 配置,无需额外配置

3. nuxt.js的使用

npm create nuxt-app <project-name>

4. nuxt.js目录结构

(layouts、pages、static、store、nuxt.config.js、package.json)是Nuxt保留的,不可以更改

5. nuxt.js渲染流程

  • Incoming Request指的是浏览器发出一个请求,服务端接收请求后
  • 要检查当前有没有nuxtServerInit这个配置项,如果有的话就先执行这个函数。具体的作用和使用可参考官方文档nuxtserverinit-方法
  • middleware中间件,中间件允许您定义一个自定义函数运行在一个页面或一组页面渲染之前。也就是可以在 匹配布局(layout 组件)前执行某种操作,也可以在解析完 layout 之后,解析 page 组件前 执行某种操作。可以理解为是路由器的拦截器的作用
  • 验证:validate(),可以配合高级动态路由去做验证。如果校验不通过,Nuxt.js 将自动加载显示 404 错误页面或 500 错误页面,或者进行重定向。
  • 获取数据,asyncData方法获取数据并返回给当前组件,fetch方法修改vuexstore
  • render:最后进行渲染。将渲染后的页面返回给浏览器,用户在页面进行操作,如果再次请求新的页面,此时只会回到生命周期中的 middlerware 中,而非 nuxtServerInit。
  • nuxt-link,如果是发起一个新的路由,那么这个时候要从头开始循环

我们把服务器端创建的 .vue 文件全部理解成组件,在服务器端环境(node)通过 beforeCreatecreated 这俩个生命周期节点后服务器端 vue 组件生命周期结束。返回页面给浏览器,在客户端环境(v8)中这个 vue 组件实例创建后会在客户端再次拥有生命周期,此时生命周期中有 mounted 等钩子函数。

需要特别注意的是 nuxt 中没有 mounted 钩子函数也没有组件实例,只有 beforeCreate/created 钩子与 context 对象。beforeCreated()created()这两个生命周期函数是同时运行在服务端&&客户端,vue的其他钩子则运行在客户端,所以beforeCreated()created()不存在window对象

三、nuxt.js渲染过程部分详解

1、nuxtServerInit

举例:打开网页要立即显示的内容

// SSR方式:
// 1、nuxtServerInit 方法

actions: {
  async nuxtServerInit({commit},{req,app}) {
    let {data: {province, city}} = await axios.get('/aa/bb')
    commit('home/setPosition',{province: '', city: ''})
  }
}

// 2、middleware 属性

middleware: async (ctx) => {
  let {data: {province, city}} = await axios.get('/aa/bb')
}

// NO-SSR
vue 组件 mounted 函数发送请求

2、异步数据 asyncData

asyncData方法会在组件(限于页面组件)每次加载渲染之前,即在服务端或路由更新之前被调用。在 asyncData() 中可以处理请求得来的数据,通过 return 将处理后的数据返回给当前 vue 组件的 data 。再次强调这里不能使用 this ,因为没有组件实例,asyncData() 默认的参数是 ctxcontent 对象。

该方法用来获取数据,在服务器端把异步获取到的数据扔给浏览器,那是如何抛给浏览器的呢?

通过下发一个`script`标签,然后在`window`上挂了一个对象这个对象,第一个是告诉你用的是哪个模板,第二个给你的是数据

3、布局

Nuxt.js布局方式如下图所示:

nuxt.js实现了一个新的概念,layout布局,我们可以通过layout布 局方便的实现页面的多个布局之间方便的切换。具体开发的页面中,如果使用默认布局,则不需指定页面的布局,nuxt框架会自动对没有指定布局的页面和default布局进行关联。如果需要指定布局,则在layout字段中对布局进行指定。

<script>
export default {
 layout: 'plusBuy',
 ...
}
</script>

// 如果layout文件中建立了一个单独的文件,则在使用中也要指定
<script>
export default {
 layout: 'plusBuy/plusBuy',
 ...
}
</script>

四、nuxt爬坑

1、localhost访问可以,换成真实的ip地址后访问不了

解决方案:

  1. 确认有没有开代理
  2. package.json里做如下配置
"config": {
  "nuxt": {
    "host": "0.0.0.0",
    "port": 3000
  }
}

2、接口跨域问题

解决方案

  • 安装@nuxtjs/axios@nuxtjs/proxy
  • nuxt.config.js做如下配置
modules: ['@nuxtjs/axios'], // 不需要加入@nuxtjs/proxy

axios: {
  proxy: true
},
proxy: {
  '/wlfrontend': { // 请求到 /wlfrontend 代理到请求 http://10.102.140.38:7001/wlfrontend
    target: 'http://10.102.140.38:7001',
    changeOrigin: true // 如果接口跨域,需要进行这个参数配置
  },
  '/scenery': { // 将'localhost:8080/scenery/xxx'代理到'https://m.ly.com/scenery/xxx'
    target: 'https://m.ly.com', // 代理地址
    changeOrigin: true, // 如果接口跨域,需要进行这个参数配置
    secure: false // 默认情况下,不接受运行在 HTTPS 上,且使用了无效证书的后端服务器。如果你想要接受,只要设置 secure: false
  }
}

3、asyncDate fetch created 因为服务端客户端都会走,如果不想在客户端执行?

async asyncData ({ query, store, req }) {
  if (!process.server) return
}

async fetch({ store, params }){
  if (!process.server) return
}

created(){
  if (!process.server) return
},

4、页面做缓存,也就是返回上一级保持数据不重新请求

解决方案:
在布局页面处理,layout/default.vue或者是自己建立的布局页面

<template>
  <div class="plusBuy">
    <nuxt keep-alive />
  </div>
</template>

5、nuxt是把所有页面的js都引入到主页了?

在生产模式下,Nuxt.js 使用浏览器的预加载策略来预加载目标页面的脚本资源。所以当用户点击某个链接时,会有一种秒开的感觉。预加载策略使得 Nuxt.js 既可以保持代码分离又能保证页面访问体验。
<nuxt-link>则是帮我们扩展了自动预获取代码分割页面。可以使用 no-prefetch属性 禁用
如果想要禁用,在nuxt.config.js做如下配置

router: {
  prefetchLinks: false, // 全局禁用所有链接上的预取
}
render: {
  resourceHints: false, // 添加prefetch和preload,以加快初始化页面加载时间。如果有许多页面和路由,可禁用此项
},

6、切换子路由的head中外部引入脚本载入有延迟,所以在调用时报错

注意:
1、引入脚本不要加async:true,这样的话脚本不会阻塞,在下面代码有用到该脚本中的方式时,脚本可能还没有加载完
2、需要每个小项目自己做个定制化页面layout,layout/我的目录/我的页面.vue 然后在定制化页面中使用head()加入脚本

export default {
  // 方式一:
  head: {
    script: [
      { type: 'text/javascript', src: 'https://js.40017.cn/cn/min/??/touch/hb/c/bridge.2.1.4.js?v=2016053', defer: true }
    ]
  }
  // 方式二:
  head () {
    return {
      script: [
        { type: 'text/javascript', src: 'https://js.40017.cn/cn/min/??/touch/hb/c/bridge.2.1.4.js?v=2016053', defer: true }
      ]
    }
  }
}

7、滚动事件

如果htmlbody设置了100%,那么子页面足够长时滚动的话,滚动事件要绑定在子页面上,因为body的高度不是整个页面的高度

// 1. 在子页面父元素加
<template>
  <div class="plus" ref="mainPage"></div>
</template>

// 2. 样式设置100%滚动
.plus {
  height: 100%;
  overflow-y: scroll;
  -webkit-overflow-scrolling : touch;
}

// 3. 再添加滚动事件
function scrollEvent() {
  var that = this;
  let dom = this.$refs.mainPage;

  dom.onscroll = function() {
    let wh = dom.scrollTop;
    // 页面上滑,出现
    wh > 100 ? (that.showBackTop = true) : (that.showBackTop = false);
    // 未开通,页面滑动至不出现顶部的立即开通按钮时,底部的立即开通固定展示
    if(that.memberRightsInfo && !that.memberRightsInfo.IsPlusMember){
      if(document.querySelector('.tab') && document.querySelector('.tab').offsetTop){
        let distance = document.querySelector('.tab').offsetTop;
        wh > distance - 50 ? (that.isShowFixedBtn = true) : (that.isShowFixedBtn = false);
      }
    }
  };
}

8、文件下建立了其他文件,比如store/plusBuy/index.js,并没有在store下直接建立index.js,如何使用?

原理:Nuxt把store中的index.js文件中所有的state、mutations、actions、getters都作为其公共属性挂载到了store实例上,然而其他的文件则是使用的是命名空间,其对应的命名空间的名字就是其文件名。

computed: {
  ...mapState('plusBuy', {
    nickName: state => state.nickName
  })
}

...mapMutations('plusBuy', {
  setCityId: 'setCityId' // 将 `this.setCityId()` 映射为 `this.$store.commit('setCityId')`
})

...mapActions('plusBuy', {
  login: 'login' // 将 `this.login()` 映射为 `this.$store.dispatch('login')`
})

9、asyncData不可以调用this,如果有好多个异步或数据进行处理,如何优化asyncData()

// 可以使用类
class A {
  aatest(aa){
    console.log(aa)
  }
}

// 调用方法
async asyncData ({ query, store, req }) {
  var test = new A();
  test.aatest(123);
}

10、如何获取cookie

// 服务端获取cookie
b_getToken(req = {},c_name){
  if (req.headers && req.headers.cookie) {
    var req_Cookies = req.headers.cookie.split("; ")
    let tokens = ''
    req_Cookies.forEach(v => {
      if (v.indexOf(c_name + "=")>=0) {
        tokens = v
      }
    })
    return tokens.split('=')[1]
  } else {
    return ''
  }
}

// 客户端获取cookie
getCookie: function(c_name) {
  if (document.cookie.length > 0) {
    //先查询cookie是否为空,为空就return ""
    let c_start = document.cookie.indexOf(c_name + "=") || ''; //通过String对象的indexOf()来检查这个cookie是否存在,不存在就为 -1
    if (c_start != -1) {
      c_start = c_start + c_name.length + 1; //最后这个+1其实就是表示"="号啦,这样就获取到了cookie值的开始位置
      let c_end = document.cookie.indexOf(";", c_start); // 为了得到值的结束位置。因为需要考虑是否是最后一项,所以通过";"号是否存在来判断
      if (c_end == -1) {
        c_end = document.cookie.length;
      }
      return unescape(document.cookie.substring(c_start, c_end));
    }
  }
  return "";
},

// 调用
let token = '';
if(process.server){
  token = serverUtilsFn.b_getToken(req,'17uCNRefId');
  console.log('server:' + token)
}else {
  token = utilsFn.getCookie('17uCNRefId');
  console.log('client:' + token)
}

11、axios数据处理问题,重复问题

import axios from 'axios';
import requestCheck from './requestCheck';

// 确保使用 axios.create创建实例后再使用。否则多次刷新页面请求服务器,服务端渲染会重复添加拦截器,导致数据处理错误
const myaxios = axios.create()

// axios.defaults.baseURL = "http://localhost:3000/"

myaxios.interceptors.request.use(config => {
  let req = {...config };
  req.url = req.method.toLocaleLowerCase() == 'post' ? requestCheck(req.url, req.data) : requestCheck(req.url, req.params);
  return req;

}, error => {
  return Promise.reject(error)
})

myaxios.interceptors.response.use(response => {
  return response
}, error => {
  return Promise.reject(error)
})

export default myaxios;

12、跳转路由传递参数并且取值

传递参数 -- this.$router.push({name: ' 路由的name ', params: {key: value}})
参数取值 -- this.$route.params.key
注: 使用这种方式,参数不会拼接在路由后面,地址栏上看不到参数
注意: 由于动态路由也是传递params的,所以在 this.$router.push() 方法中 path不能和params一起使用,否则params将无效。需要用name来指定页面。

13、设置页面动画效果

/* 全局过渡动效设置 - 淡出 (fade) 效果*/

.page-enter-active,
.page-leave-active {
  transition: opacity .5s;
}

.page-enter,
.page-leave-active {
  opacity: 0;
}

/* 局部过渡动效设置 - 淡出 (fade) 效果*/

.test-enter-active,
.test-leave-active {
  transition: opacity .5s;
}

.test-enter,
.test-leave-active {
  opacity: 0;
}

// 在要使用的组件页面中
export default {
  transition: 'test',
}

14、如何使用插件

// 1. 安装插件
yarn add swiper -D

// 2. 引入
<script>
import Swiper from 'swiper'
</script>

// 3. 引入样式
<style lang="less" scoped>
  @import "../../node_modules/swiper/css/swiper.css";
</style>

15、如何在组件中使用异步数据

如果组件不是和路由绑定的页面组件,原则上是不可以使用异步数据的。因为 Nuxt.js 仅仅扩展增强了页面组件的data方法,使得其可以支持异步数据处理。

对于非页面组件,有两种方式可以实现数据的异步获取:

  1. 在组件的mounted方法里面实现异步获取数据的逻辑,之后设置组件的数据,限制是:不支持服务端渲染。
  2. 在页面组件的asyncDatafetch方法中进行API调用,并将数据作为props传递给子组件。服务器渲染工作正常。缺点:asyncData或页面提取可能不太可读,因为它正在加载其他组件的数据。

总之,使用哪种方法取决于你的应用是否需要支持子组件的服务端渲染。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Nuxt.js实战和配置详解

    前段时间刚好公司有项目使用了Nuxt.js来搭建,而刚好在公司内部做了个分享,稍微再整理一下发出来.本文比较适合初用Nuxt.js的同学,主要讲下搭建过程中做的一些配置.建议初次使用Nuxt.js的同学先过一遍官方文档,再回头看下我这篇文章. 一.为什么要用Nuxt.js 原因其实不用多说,就是利用Nuxt.js的服务端渲染能力来解决Vue项目的SEO问题. 二.Nuxt.js和纯Vue项目的简单对比  1. build后目标产物不同 vue: dist nuxt: .nuxt 2. 网页渲染流

  • Nuxt.js实战详解

    一.为什么选择Nuxt.js 多数是基于webpack构建的项目,编译出来的html文件,资源文件都被打包到js中,以下图404页面代码为例.从代码中可以看出,这样的页面是不利于 搜索引擎优化(SEO, Search Engine Optimization) ,并且 内容到达时间(time-to-content) (或称之为首屏渲染时长)也有很大的优化空间.为了解决以上问题,引入了 Nuxt.js 框架. vue官网对于Nuxt.js也是很推荐的,除此之外,Nuxt.js的开发者积极活跃,版本迭

  • 详解Nuxt.js 实战集锦

    读本文前,请先熟读nuxt官方文档,并且具备一定的vue.js相关开发经验 中文文档 英文文档 vue SSR指南 一.CSR和SSR对比 在SPA之前的时代,我们传统的Web架构大都是SSR,如:Wordpress(PHP).JSP技术.JavaWeb等这些程序都是传统典型的SSR架构,即:服务端取出数据和模板组合生成 html输出给前端,前端发生请求时,重新向服务端请求html资源. SPA(CSR): SPA应用,到了Vue.React,单页面应用优秀的用户体验,逐渐成为了主流,页面整体是

  • 详解Nuxt.js Vue服务端渲染摸索

    本文采用nuxt进行服务端渲染https://zh.nuxtjs.org/ Nuxt.js 十分简单易用.一个简单的项目只需将 nuxt 添加为依赖组件即可. Vue因其简单易懂的API.高效的数据绑定和灵活的组件系统,受到很多前端开发人员的青睐.国内很多公司都在使用vue进行项目开发,我们正在使用的简书,便是基于Vue来构建的. 我们知道,SPA前端渲染存在两大痛点:(1)SEO.搜索引擎爬虫难以抓取客户端渲染的页面meta信息和其他SEO相关信息,使网站无法在搜索引擎中被用户搜索到.(2)用

  • 详解Nuxt.js中使用Element-UI填坑

    Nuxt.js是Vue进行SSR的一个优选开源项目,可免去繁琐的Webpack.nodejs后台服务配置等操作,方便的搭建一个支持SSR的VUE项目.Element-UI则是一个机遇Vue2.0+开发的一套UI框架,实现了常用的组件,可帮助开发者快速搭建一个如CMS系统.后台管理系统等基于Vue的系统. 由于Element-UI目前在SSR支持方面还是不够完善,且Nuxt.js在文档方面也有欠缺,所以在Nuxt.js中使用Element-UI也是一段坑路,需要去将查看Nuxt源码与Element

  • 详解Nuxt.js部署及踩过的坑

    Nuxt.js 提供了两种发布部署应用的方式:服务端渲染应用部署 和 静态应用部署. 静态应用部署就不说了,主要说说服务端渲染应用部署. 官方推荐部署方式 关于服务端渲染应用部署,官方文档是这么写的: 部署 Nuxt.js 服务端渲染的应用不能直接使用 nuxt 命令,而应该先进行编译构建,然后再启动 Nuxt 服务,可通过以下两个命令来完成: nuxt build nuxt start 推荐的 package.json 配置如下: { "name": "my-app&quo

  • 详解Nuxt内导航栏的两种实现方式

    方式一 | 通过嵌套路由实现 在pages页面根据nuxt的路由规则,建立页面 1. 创建文件目录及文件 根据规则,如果要创建子路由,子路由的文件夹名字,必须和父路由名字相同 所以,我们的文件夹也为index,index文件夹需要一个默认的页面不然nuxt的路由规则就不能正确匹配页面 一级路由是根路由 二级路由是index,user,默认进入index路由 下面是router页面自动生成的路由 { path: "/", component: _93624e48, children: [

  • 详解JavaScript面向对象实战之封装拖拽对象

    目录 概述 1.如何让一个DOM元素动起来 2.如何获取当前浏览器支持的transform兼容写法 3.如何获取元素的初始位置 5.我们需要用到哪些事件? 6.拖拽的原理 7. 我又来推荐思维导图辅助写代码了 8.代码实现 part1.准备工作 part2.功能函数 part3.声明三个事件的回调函数 9.封装拖拽对象 概述 为了能够帮助大家了解更多的方式与进行对比,我会使用三种不同的方式来实现拖拽. 不封装对象直接实现: 利用原生JavaScript封装拖拽对象: 通过扩展jQuery来实现拖

  • 详解 vue.js用法和特性

    前  言 最近用Vue.js做了一个数据查询平台,还做了一个拼图游戏,突然深深的感到了vue的强大. Vue.js是一套构建用户界面(user interface)的渐进式框架.与其他重量级框架不同的是,Vue 从根本上采用最小成本.渐进增量(incrementally adoptable)的设计.Vue 的核心库只专注于视图层,并且很容易与其他第三方库或现有项目集成.另一方面,当与单文件组件和 Vue 生态系统支持的库结合使用时,Vue 也完全能够为复杂的单页应用程序提供有力驱动. Vue.j

  • 实例详解Spring Boot实战之Redis缓存登录验证码

    本章简单介绍redis的配置及使用方法,本文示例代码在前面代码的基础上进行修改添加,实现了使用redis进行缓存验证码,以及校验验证码的过程. 1.添加依赖库(添加redis库,以及第三方的验证码库) <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-redis</artifactId> </dependency&

  • 详解node.js中的npm和webpack配置方法

    概述 Node.js用c++语言编写而成的,是一个基于chrome V8引擎的javascript运行环境,让javaScript的运行脱离浏览器服务端,可以使用javaScript语言书写服务器端代码 1.使用node来实现一个http服务器 下面创建了一个端口为8787的服务器.他与php,java等不同,像php本地还要基于阿帕奇服务器,node.js能用代码快速搭建一个服务器. // 引入http模块 var http = require("http"); // 调用http的

  • 详解Vue.js中.native修饰符

    修饰符(Modifiers)是以半角句号 . 指明的特殊后缀,用于指出一个指令应该以特殊方式绑定.这篇文章给大家介绍Vue.js中.native修饰符,感兴趣的朋友一起看看吧. .native修饰符 官方对.native修饰符的解释为: 有时候,你可能想在某个组件的根元素上监听一个原生事件.可以使用 v-on 的修饰符 .native .例如: <my-component v-on:click.native="doTheThing"></my-component>

随机推荐