vue init webpack project
复制代码
npm install
复制代码
npm run dev
复制代码
vue create project
复制代码
选择配置,看我的项目需求javascript
TypeScript 支持使用 TypeScript 书写源码
Progressive Web App (PWA) Support PWA 支持。
Router 支持 vue-router 。
Vuex 支持 vuex 。
CSS Pre-processors 支持 CSS 预处理器。
Linter / Formatter 支持代码风格检查和格式化。
Unit Testing 支持单元测试。
E2E Testing 支持 E2E 测试。
复制代码
进入到项目根目录css
cd project
复制代码
启动项目html
npm run serve
复制代码
npm i element-ui -S
复制代码
import Element from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(Element)
复制代码
首先,安装 babel-plugin-componentvue
npm install babel-plugin-component -D
复制代码
而后,将 .babelrc 修改成:java
{
"presets": [
["es2015", {
"modules": false
}]
],
"plugins": [
[
"component",
{
"libraryName": "element-ui",
"styleLibraryName": "theme-chalk"
}
]
]
}
复制代码
接下来,若是你只但愿引入部分组件,好比 Button 和 Select,那么须要在 main.js 中写入如下内容:node
import Vue from 'vue';
import { Button, Select } from 'element-ui';
import App from './App.vue';
Vue.component(Button.name, Button); Vue.component(Select.name, Select); 复制代码
或写为webpack
- Vue.use(Button)
- Vue.use(Select)
复制代码
npm i vuex -s
复制代码
import Vue from 'vue'
import Vuex from 'vuex'
//挂载 Vuex Vue.use(Vuex) //建立 VueX 对象 const store = new Vuex.Store({ state:{name: 'helloVueX', }, mutations:{}, actions:{}, modules:{} }) export default store 复制代码
将 store 挂载到当前项目的 Vue 实例当中去ios
import Vue from 'vue'
import App from './App'
import router from './router'
import store from './store'
Vue.config.productionTip = false new Vue({ el: '#app', router, store, //store:store 和 router 同样,将咱们建立的 Vuex 实例挂载到这个 vue 实例中 render: h => h(App) }) 复制代码
<template>
<div id='app'>
name:
<h1>{{ $store.state.name }}</h1>
</div>
</template>
methods:{ add(){ console.log(this.\$store.state.name) } }, 复制代码
更具体的学习文档参考个人网站: 学习文档git
npm install node-sass sass-loader --save-dev
复制代码
{
test: /\.scss\$/,
loaders: ['style', 'css', 'sass']
}
复制代码
github
<style lang='scss'>
复制代码</style> 复制代码
npm install sass-resources-loader --save-dev
复制代码
将scss: generateLoaders('sass')
scss: generateLoaders('sass').concat({
loader: 'sass-resources-loader',
options: {
//你本身的 scss 全局文件的路径
resources: path.resolve(\_\ _dirname, '../src/style/common.scss')
}
})
复制代码
若是上面的不能正常编译
//配置 sass 编译路径
function generateSassResourceLoader() { let loaders = [ cssLoader, 'sass-loader', { loader: 'sass-resources-loader', options: { // 多个文件时用数组的形式传入,单个文件时能够直接使用 path.resolve(__dirname, '../static/style/common.scss' resources: path.resolve(__dirname, '../src/style/common.scss') } } ]; if (options.extract) { return ExtractTextPlugin.extract({ use: loaders, fallback: 'vue-style-loader' }); } else { return ['vue-style-loader'].concat(loaders); } } 复制代码
sass:generateSassResourceLoader(),//新加的
scss:generateSassResourceLoader(),//新加的
复制代码
npm install --s node-sass sass-loader
复制代码
1.首先你须要
npm install --s sass-resources-loader
复制代码
2.在 build 目录下找到 utils.js 文件
Module build failed: TypeError: this.getResolve is not a function at Object.loader 复制代码
安装 node-sass 运行报错 vue 安装 node-sass 编译报错 安装node-scss报错 安装 node-scss 报错
在搭建 vue 脚手架 或者是在 vue 项目中,想使用 sass 的功能,
npm install node-sass --save-dev //安装 node-sass
npm install sass-loader --save-dev //安装 sass-loader
npm install style-loader --save-dev //安装 style-loader
复制代码
这是由于当前 sass 的版本过高,webpack 编译时出现了错误,这个时候只须要换成低版本的就行,下面说一下修改方法,很简单,以下,找到 package.json 文件,里面的 "sass-loader"的版本更换掉 就好了。
将 "sass-loader": "^8.0.0",更换成了 "sass-loader": "^7.3.1",
复制代码
也能够先卸载当前版本,而后安装指定的版本
npm uninstall sass-loader
复制代码
npm install sass-loader@7.3.1 --save-dev
复制代码
npm install less less-loader --save
复制代码
修改 webpack.base.config.js 文件,配置 loader 加载依赖,让其支持外部的 less,在原来的代码上添加
// 此种方法在控制台中标签样式显示的是style标签样式
{
test: /\.less$/,
loader: "style-loader!css-loader!less-loader",
}
复制代码
// 能够在控制台中看到当前标签样式来自于哪一个less文件
{
test: /\.less$/,
loader: "style-loader!css-loader!less-loader",
options: {
sourceMap: true
}
}
复制代码
在 vue 文件中的 style 标签中添加 lang="less"便可在标签中使用 less,或者外部引入 less
npm install font-awesome --save
复制代码
而后在 main.js 引入 font-awesome/css/font-awesome.min.css 便可。
<link rel="shortcut icon" href="./favicon.ico" type="image/x-icon" />
复制代码
webpack.dev.conf.js
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'index.html',
favicon: 'favicon.ico', // 新增
inject: true
}),
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', favicon: 'favicon.ico' // 新增 }), 复制代码
在 router/index.js 里面引入公共样式
import 'bootstrap/dist/css/bootstrap.css' //引入 bootstrap
import 'bootstrap-vue/dist/bootstrap-vue.css'
import '@/common/common.css'
import '@/common/index.css'
复制代码
const port = () => import('@/pages/port') //入口页面、
复制代码
const router = new Router({
// mode: 'history',
routes: [
{
path: '/',
name: 'port',
component: resolve => require.ensure([], () => resolve(require('@/pages/port')), 'port'),
}]
})
复制代码
Vue.prototype.isMobile = function() {
let flag = navigator.userAgent.match(
/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i
)
return flag;
}
复制代码
mounted: function() {
this.isMobile();
}
复制代码
// 接口暴露在全局
import { server } from './config/api'
Vue.prototype.\$server = server;
复制代码
//api.js
export const server = { getContentMenu: (paramObj)=>fetch('/content/menu',paramObj),//内容详情查询 getContentListPort: (paramObj)=>fetch('/content/list/'+paramObj),//入口页面接口 getContentList:(paramObj)=>fetch('/content/list/'+paramObj),//内容详情查询 getPageviews:(paramObj)=>fetch('/webpage/1/view',paramObj)//流量统计接口 } 组件里面使用: ```js methods: { getPageviews() { var that = this; let params = { pageId: that.pageId, pageUrl: that.pageUrl, }; that.\$server.getPageviews(params).then(response => {}) } } 复制代码
import axios from 'axios';
axios.defaults.timeout = 5000; axios.defaults.baseURL =''; //填写域名 //http request 拦截器 axios.interceptors.request.use( config => { config.data = JSON.stringify(config.data); config.headers = { 'Content-Type':'application/x-www-form-urlencoded' } return config; }, error => { return Promise.reject(err); } ); //响应拦截器即异常处理 axios.interceptors.response.use(response => { return response }, err => { if (err && err.response) { switch (err.response.status) { case 400: console.log('错误请求') break; case 401: console.log('未受权,请从新登陆') break; case 403: console.log('拒绝访问') break; case 404: console.log('请求错误,未找到该资源') break; case 405: console.log('请求方法未容许') break; case 408: console.log('请求超时') break; case 500: console.log('服务器端出错') break; case 501: console.log('网络未实现') break; case 502: console.log('网络错误') break; case 503: console.log('服务不可用') break; case 504: console.log('网络超时') break; case 505: console.log('http版本不支持该请求') break; default: console.log(`链接错误${err.response.status}`) } } else { console.log('链接到服务器失败') } return Promise.resolve(err.response) }) /** * 封装get方法 * @param url * @param data * @returns {Promise} */ export function fetch(url,params={}){ return new Promise((resolve,reject) => { axios.get(url,{ params:params }) .then(response => { resolve(response.data); }) .catch(err => { reject(err) }) }) } /** * 封装post请求 * @param url * @param data * @returns {Promise} */ export function post(url,data = {}){ return new Promise((resolve,reject) => { axios.post(url,data) .then(response => { resolve(response.data); },err => { reject(err) }) }) } /** * 官网接口请求封装 * @param url * @param data * @returns {Promise} */ export const server = { getContentMenu: (paramObj)=>fetch('/content/menu',paramObj),//内容详情查询 getContentListPort: (paramObj)=>fetch('/content/list/'+paramObj),//入口页面接口 getContentList:(paramObj)=>fetch('/content/list/'+paramObj),//内容详情查询 getPageviews:(paramObj)=>fetch('/webpage/1/view',paramObj)//流量统计接口 } 复制代码
原理:此方法使用的是 v-if 来控制 router-view 的显示或隐藏,v-if 从 false 变为 true 时,vue 会从新渲染 router-view 区域,因此当参数变化时,只需让 v-if 从 true => false => true,就能实现页面刷新。
//App.vue
<template> <div id="app"> <router-view v-if="isRouterAlive"/> </div> </template> <script> export default { name: 'App', provide() { return { reload: this.reload//调用reload方法 } }, data() { return { isRouterAlive: true//一开始router-view为true } }, <span class="hljs-attr" style="line-height: 26px;">methods</span>: {
reload() {
<span class="hljs-keyword" style="color: #333; font-weight: bold; line-height: 26px;">this</span>.isRouterAlive = <span class="hljs-literal" style="color: #008080; line-height: 26px;">false</span>
<span class="hljs-comment" style="color: #998; font-style: italic; line-height: 26px;">//在修改数据以后使用 $nextTick,则能够在回调中获取更新后的 DOM</span>
<span class="hljs-keyword" style="color: #333; font-weight: bold; line-height: 26px;">this</span>.$nextTick(<span class="hljs-function" style="line-height: 26px;"><span class="hljs-params" style="line-height: 26px;">()</span> =></span> {
<span class="hljs-keyword" style="color: #333; font-weight: bold; line-height: 26px;">this</span>.isRouterAlive = <span class="hljs-literal" style="color: #008080; line-height: 26px;">true</span>
})
}
}
}
复制代码
复制代码<span class="hljs-attr" style="line-height: 26px;">methods</span>: {
reload() {
<span class="hljs-keyword" style="color: #333; font-weight: bold; line-height: 26px;">this</span>.isRouterAlive = <span class="hljs-literal" style="color: #008080; line-height: 26px;">false</span>
<span class="hljs-comment" style="color: #998; font-style: italic; line-height: 26px;">//在修改数据以后使用 $nextTick,则能够在回调中获取更新后的 DOM</span>
<span class="hljs-keyword" style="color: #333; font-weight: bold; line-height: 26px;">this</span>.$nextTick(<span class="hljs-function" style="line-height: 26px;"><span class="hljs-params" style="line-height: 26px;">()</span> =></span> {
<span class="hljs-keyword" style="color: #333; font-weight: bold; line-height: 26px;">this</span>.isRouterAlive = <span class="hljs-literal" style="color: #008080; line-height: 26px;">true</span>
})
}
}
}
复制代码</script> 复制代码
export default {
name: 'newproduct',
inject:['reload'],//在export default下面加上这一段
method:{
//调用App.vue下的this.reload()方法,来改变v-if的状态
clickDiv(){//刷新按钮调用的方法
this.reload()
}
}
复制代码
参考文档:如何实现 vue 中不跳转不闪动页面刷新?provide /inject 完美解决方案
:class="{ 'active': isActive }"
复制代码
:class="{'active':isActive==-1}"
或者
:class="{'active':isActive==index}"
复制代码
:class="{ 'active': isActive, 'sort': isSort }"
复制代码
:class="classObject"
data() {
return {
classObject: {
active: true,
sort: false
}
}
}
复制代码
:class="classObject"
data() {
return {
isActive: true,
isSort: false
}
},
computed: {
classObject: function() {
return {
active: this.isActive,
sort: this.isSort
}
}
}
复制代码
:class="[isActive,isSort]"
复制代码
data() {
return {
isActive: 'active',
isSort: 'sort'
}
}
复制代码
数组与三元运算符结合判断选择须要的class 三元运算符后面的“:”两边的class须要加上单引号
:class="[isActive?'active':'']"
复制代码
或者
:class="[isActive==1?'active':'']"
复制代码
或者
:class="[isActive==index?'active':'']"
复制代码
或者
:class="[isActive==index?'active':'otherActiveClass']"
复制代码
//前面这个 active 在对象里面能够不加单引号,后面这个 sort 要加单引号
:class="[{ active: isActive }, 'sort']"
复制代码
或者
:class="[{ active: isActive==1 }, 'sort']"
复制代码
或者
:class="[{ active: isActive==index }, 'sort']"
复制代码
应用于组件 若是直接在自定义组件中使用 class 或 :class,那么样式规则就会直接应在这个组件的根元素上。
<div id="app">
<text-component :class="{'isStrong':isStrong}"></text-component>
</div>
复制代码
<script>
Vue.component('text-component', {
template: '<p class="content">不懂基因测序的学霸不是好的人工智能公司 CEO</p>'
});
var app = new Vue({
el: '#app',
data: {
isStrong: true
}
});
</script>
复制代码
<span v-bind:style="{'display':config.isHaveSearch ? 'block':'none'}" >动态绑定样式</span> 复制代码
也可使用 v-bind:style 或 :style 直接给 HTML 元素绑定样式,它也有对应的对象语法与数组语法。
<div id="app">
<div :style="border"></div>
</div>
复制代码
<script>
var app = new Vue({
el: '#app',
data: {
border:{
border:'1px solid #00F',
textShadow:'0 0 .3em gray'
}
}
});
</script>
复制代码
由于 JS 属性不支持短横分隔命名,因此咱们这里使用 CSS 也支持的驼峰命名法。
<div id="app">
<p>原始字符串: {{ message }}</p>
<p>计算后反转字符串: {{ reversedMessage }}</p>
</div>
复制代码
<script>
var vm = new Vue({
el: '#app',
data: {
message: 'Runoob!'
},
computed: {
// 计算属性的 getter
reversedMessage: function () {
// `this` 指向 vm 实例
return this.message.split('').reverse().join('')
}
}
})
</script> 复制代码
咱们可使用 methods 来替代 computed,效果上两个都是同样的,可是 computed 是基于它的依赖缓存,只有相关依赖发生改变时才会从新取值。而使用 methods ,在从新渲染的时候,函数总会从新调用执行。。换句话说,computed 是局部渲染,而 methods 是所有渲染 区别:
computed 属性默认只有 getter ,不过在须要时你也能够提供一个 setter :
var vm = new Vue({
el: '#app',
data: {
name: 'Google',
url: 'http://www.google.com'
},
computed: {
site: {
// getter
get: function() {
return this.name + ' ' + this.url
},
// setter
set: function(newValue) {
var names = newValue.split(' ')
this.name = names[0]
this.url = names[names.length - 1]
}
}
}
})
复制代码
// 调用 setter, vm.name 和 vm.url 也会被对应更新
vm.site = 'http://www.runoob.com';
document.write('name: ' + vm.name);
document.write('<br>');
document.write('url: ' + vm.url);
复制代码
从实例运行结果看在运行 vm.site = 'http://www.runoob.com'; 时,setter 会被调用, vm.name 和 vm.url 也会被对应更新。
class 与 style 是 HTML 元素的属性,用于设置元素的样式,咱们能够用 v-bind 来设置样式属性。 Vue.js v-bind 在处理 class 和 style 时, 专门加强了它。表达式的结果类型除了字符串以外,还能够是对象或数组。
咱们能够为 v-bind:class 设置一个对象,从而动态的切换 class:
<style>
.active {
width: 100px;
height: 100px;
background: green;
}
</style>
复制代码
<div id="app">
<div v-bind:class="{ active: isActive }"></div>
</div>
复制代码
<script>
new Vue({
el: '#app',
data: {
isActive: true
}
})
</script> 复制代码
例:text-danger 类背景颜色覆盖了 active 类的背景色:
<style>
.active {
width: 100px;
height: 100px;
background: green;
}
.text-danger {
background: red;
}
</style>
复制代码
<div id="app">
<div class="static" v-bind:class="{ active: isActive, 'text-danger': hasError }">
</div>
</div>
复制代码
<script>
new Vue({
el: '#app',
data: {
isActive: true,
hasError: true
}
})
</script> 复制代码
<style>
.active {
width: 100px;
height: 100px;
background: green;
}
.text-danger {
background: red;
}
</style>
复制代码
<div id="app">
<div v-bind:class="classObject"></div>
</div>
复制代码
<script>
new Vue({
el: '#app',
data: {
classObject: {
active: true,
'text-danger': true
}
}
})
</script> 复制代码
<style>
.active {
width: 100px;
height: 100px;
background: green;
}
.text-danger {
background: red;
}
</style>
复制代码
<div id="app">
<div v-bind:class="classObject"></div>
</div>
复制代码
<script>
new Vue({
el: '#app',
data: {
isActive: true,
error: null
},
computed: {
classObject: function () {
return {
active: this.isActive && !this.error,
'text-danger': this.error && this.error.type === 'fatal',
}
}
}
})
</script> 复制代码
<style>
.active {
width: 100px;
height: 100px;
background: green;
}
.text-danger {
background: red;
}
</style>
复制代码
<div id="app">
<div v-bind:class="[activeClass, errorClass]"></div>
</div>
复制代码
<script>
new Vue({
el: '#app',
data: {
activeClass: 'active',
errorClass: 'text-danger'
}
})
</script> 复制代码
还可使用三元表达式来切换列表中的 class : errorClass 是始终存在的,isActive 为 true 时添加 activeClass 类:
<style>
.text-danger {
width: 100px;
height: 100px;
background: red;
}
.active {
width: 100px;
height: 100px;
background: green;
}
</style>
复制代码
<div id="app">
<div v-bind:class="[errorClass ,isActive ? activeClass : '']"></div>
</div>
复制代码
<script>
new Vue({
el: '#app',
data: {
isActive: true,
activeClass: 'active',
errorClass: 'text-danger'
}
})
</script> 复制代码
v-bind:style直接设置样式:
<div id="app">
<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }">菜鸟教程</div>
</div>
复制代码
<script>
new Vue({
el: '#app',
data: {
activeColor: 'green',
fontSize: 30
}
})
</script> 复制代码
也能够直接绑定到一个样式对象:
<div id="app">
<div v-bind:style="styleObject">菜鸟教程</div>
</div>
复制代码
<script>
new Vue({
el: '#app',
data: {
styleObject: {
color: 'green',
fontSize: '30px'
}
}
})
</script> 复制代码
v-bind:style 可使用数组将多个样式对象应用到一个元素上:
<div id="app">
<div v-bind:style="[baseStyles, overridingStyles]">菜鸟教程</div>
</div>
复制代码
<script>
new Vue({
el: '#app',
data: {
baseStyles: {
color: 'green',
fontSize: '30px'
},
overridingStyles: {
'font-weight': 'bold'
}
}
})
</script> 复制代码
Vue 组件间通讯包括:父子组件间通讯,兄弟组件间通讯以及模块之间通讯等。Vue 是数据驱动视图更新的框架, 因此对于 Vue 来讲组件间的数据通讯很是重要。Vue 实现组件间通讯有不少方式,今天我来给你们讲解一下父子组件间通讯:props 和$emit。
<template>
<div class="childA-wrapper"> 子组件A </div>
</template>
<script> export default { data() { return { childA: '我是组件A传过来的值' } }, created: function() {}, mounted() { this.sendDataParent() }, methods: { sendDataParent() { // getChildDataA是在父组件on监听的方法 // 第二个参数this.childA是须要传的值 this.$emit('getChildDataA', this.childA) } } } </script>
复制代码
<template>
<div class="childB-wrapper"> 子组件B </div>
</template>
<script> export default { data() { return { childB:'我是组件B传过来的值' } }, created:function() { }, mounted(){ this.sendDataParent() }, methods: { sendDataParent() { // getChildDataB是在父组件on监听的方法 // 第二个参数this.childB是须要传的值 this.$emit('getChildDataB', this.childB) } } } </script> 复制代码
<template>
<div> <v-childA v-on:getChildDataA="getChildDataA"></v-childA> <v-childB v-on:getChildDataB="getChildDataB"></v-childB> <div>获取组件A传过来的值:{{childAValue}}</div> <div>获取组件B传过来的值:{{childBValue}}</div> </div>
</template>
<script> import childA from '@/components/childA.vue' import childB from '@/components/childB.vue' export default { data() { return { childAValue:'', childBValue:'', } }, methods: { getChildDataA(childA){ console.log(childA) this.childAValue=childA }, getChildDataB(childB){ console.log(childB) this.childBValue=childB } }, components: { 'v-childA': childA, 'v-childB': childB} } </script> 复制代码
<template>
<div> <v-childA></v-childA> <v-childB :sendBData="sendB"></v-childB> </div>
</template>
<script> import childA from '@/components/childA.vue' import childB from '@/components/childB.vue' export default { data() { return { sendB:'父组件向B组件传递的参数' } }, methods: { }, components: { 'v-childA': childA, 'v-childB': childB} } </script> 复制代码
<template>
<div class="childB-wrapper"> 子组件B:{{sendBData}} </div>
</template>
<script> export default { data() { return {} }, created: function() {}, mounted() {}, methods: {}, props: { sendBData: String, required: true } } </script> 复制代码
import Vue from 'vue'
export default new Vue()
复制代码
<template>
<div class="childB-wrapper"> </div>
</template>
<script> import Bus from '@/common/bus.js' export default { data() { return { childB: '我是组件B的内容' } }, created: function() {}, mounted() { this.elementByValue() }, methods: { elementByValue: function () { Bus.$emit('val', this.childB) } } } </script> 复制代码
##### 组件 childA:
<template> <div class="childA-wrapper"> A组件:<span>{{childB}}</span> </div> </template> <script> import Bus from '@/common/bus.js' export default { data() { return { childB: '' } }, created: function() {}, mounted() { var that = this // 用 $on事件来接收参数 Bus.$on('val', (data) => { console.log(data) that.childB = data }) } } </script> 复制代码
更多请查看:你不知道的vue组件传值方式
用到插件:cnpm install prerender-spa-plugin --save 脚手架 2.0:(本身的是 2.0)
const PrerenderSPAPlugin = require('prerender-spa-plugin')
const Renderer = PrerenderSPAPlugin.PuppeteerRenderer
const webpackConfig = merge(baseWebpackConfig, {
plugins: [
// vue-cli 生成的配置就有了
new HtmlWebpackPlugin({
filename: config.build.index,
template: 'index.html',
inject: true,
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
},
chunksSortMode: 'dependency'
}),
// 配置 PrerenderSPAPlugin
new PrerenderSPAPlugin({
// 生成文件的路径,也能够与 webpakc 打包的一致。
staticDir: path.join(\_\ _dirname, '../dist'),
// 对应本身的全部路由文件,好比 index 有参数,就须要写成 /index/param1。这个其实不须要;千万不要加'/'这个 嵌套路由得 commonquestion 直接写便可 routes: ['index', '...', '/commonQuestion', '/commonQuestion/questionList', '/commonQuestion/questionDetailInfo'], // ; renderer: new Renderer({ inject: { // 可选;最好仍是用 foo: 'bar' }, headless: false, // 可选;最好用 renderAfterTime: 5000, // 经过实践是必选 官网说可选有误 必定要必选 renderAfterDocumentEvent: 'render-event' // 可选;最好用 }) }), ] }) 复制代码
mode:‘history’,
复制代码
修改config/index.js 中的build的 assetsPublicPath: ‘/’ ;否则会致使刷新页面路径错乱致使样式或者js丢失;
修改main.js new Vue({ el: '#app', router, store, // 若是须要了切记引入啊 切记须要挂载的所有挂载上去 render: h => h(App), mounted () { document.dispatchEvent(new Event('render-event')) } }) 复制代码
const PrerenderSPAPlugin = require('prerender-spa-plugin');
const Renderer = PrerenderSPAPlugin.PuppeteerRenderer;
const path = require('path');
module.exports = {
configureWebpack: config => {
if (process.env.NODE_ENV !== 'production') return;
return {
plugins: [
new PrerenderSPAPlugin({
// 生成文件的路径,也能够与 webpakc 打包的一致。
// 下面这句话很是重要!!!
// 这个目录只能有一级,若是目录层次大于一级,在生成的时候不会有任何错误提示,在预渲染的时候只会卡着不动。
staticDir: path.join(\_\ _dirname, 'dist'),
// 对应本身的路由文件,好比 a 有参数,就须要写成 /a/param1。
routes: ['/', '/product', '/about'],
// 这个很重要,若是没有配置这段,也不会进行预编译
renderer: new Renderer({
inject: {
foo: 'bar'
},
headless: false,
renderAfterTime: 5000, // 必选哈
// 在 main.js 中 document.dispatchEvent(new Event('render-event')),二者的事件名称要对应上。
renderAfterDocumentEvent: 'render-event'
})
}),
],
};
}
}
复制代码
new Vue({
router,
store,
render: h => h(App),
mounted() {
document.dispatchEvent(new Event('render-event'))
}
}).\$mount('#app')
复制代码
其余修改同 2.0;
vue-meta-info
复制代码
官方地址: monkeyWangs/vue-meta-info
npm install vue-meta-info --save
复制代码
import Vue from 'vue'
import MetaInfo from 'vue-meta-info'
Vue.use(MetaInfo) 复制代码
<template>
...
</template> 复制代码
<script>
export default {
metaInfo: {
title: 'My Example App', // set a title
meta: [{ // set meta
name: 'keyWords',
content: 'My Example App'
}]
link: [{ // set link
rel: 'asstes',
href: 'https://assets-cdn.github.com/'
}]
}
}
</script> 复制代码
<template>
...
</template> 复制代码
<script>
export default {
name: 'async',
metaInfo () {
return {
title: this.pageName
}
},
data () {
return {
pageName: 'loading'
}
},
mounted () {
setTimeout(() => {
this.pageName = 'async'
}, 2000)
}
}
</script> 复制代码
<meta name="参数" content="具体的描述">
复制代码
<meta name="参数" content="具体的描述">
复制代码
其中 name 属性共有如下几种参数。(A-C 为经常使用属性)
说明:用于告诉搜索引擎,你网页的关键字。
<meta name="keywords" content="XX网,汽车,车主,评选">
复制代码
说明:用于告诉搜索引擎,你网站的主要内容。
复制代码
<meta name="description" content="汽车评选,XX网,评选,汽车">
复制代码
说明:这个属性经常使用于设计移动端网页。
举例
<meta name="viewport" content="width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
复制代码
说明:robots 用来告诉爬虫哪些页面须要索引,哪些页面不须要索引。
content 的参数有 all,none,index,noindex,follow,nofollow。默认是 all。
复制代码
举例:
<meta name="robots" content="none">
复制代码
具体参数以下:
1.none : 搜索引擎将忽略此网页,等价于 noindex,nofollow。
2.noindex : 搜索引擎不索引此网页。
3.nofollow: 搜索引擎不继续经过此网页的连接索引搜索其它的网页。
4.all : 搜索引擎将索引此网页与继续经过此网页的连接索引,等价于 index,follow。
5.index : 搜索引擎索引此网页。
6.follow : 搜索引擎继续经过此网页的连接索引搜索其它的网页。
复制代码
说明:用于标注网页做者 举例:
<meta name="author" content="Lxxyx,841380530@qq.com">
复制代码
说明:用于标明网页是什么软件作的 举例: (不知道能不能这样写):
<meta name="generator" content="Sublime Text3">
复制代码
说明:用于标注版权信息 举例:
<meta name="copyright" content="Lxxyx"> //表明该网站为Lxxyx我的版权全部。
复制代码
说明:若是页面不是常常更新,为了减轻搜索引擎爬虫对服务器带来的压力,能够设置一个爬虫的重访时间。若是重访时间太短,爬虫将按它们定义的默认时间来访问。 举例:
<meta name="revisit-after" content="7 days" >
复制代码
说明:renderer 是为双核浏览器准备的,用于指定双核浏览器默认以何种方式渲染页面。好比说 360 浏览器。 举例:
<meta name="renderer" content="webkit"> //默认webkit内核
<meta name="renderer" content="ie-comp"> //默认IE兼容模式
<meta name="renderer" content="ie-stand"> //默认IE标准模式
复制代码
http-equiv 至关于 HTTP 的做用,好比说定义些 HTTP 参数啥的。 meta 标签中 http-equiv 属性语法格式是:
<meta http-equiv="参数" content="具体的描述">
复制代码
其中 http-equiv 属性主要有如下几种参数:
说明:用于设定网页字符集,便于浏览器解析与渲染页面 举例:
<meta http-equiv="content-Type" content="text/html;charset=utf-8"> //旧的HTML,不推荐
<meta charset="utf-8"> //HTML5设定网页字符集的方式,推荐使用UTF-8 复制代码
说明:用于告知浏览器以何种版原本渲染页面。(通常都设置为最新模式,在各大框架中这个设置也很常见。) 举例:
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/> //指定IE和Chrome使用最新版本渲染当前页面
复制代码
用法 1.
说明:指导浏览器如何缓存某个响应以及缓存多长时间。这一段内容我在网上找了好久,但都没有找到满意的。 最后终于在 Google Developers 中发现了我想要的答案。
举例:
<meta http-equiv="cache-control" content="no-cache">
复制代码
共有如下几种用法:
说明:用于禁止当前页面在移动端浏览时,被百度自动转码。虽然百度的本意是好的,可是转码效果不少时候却不尽人意。因此能够在 head 中加入例子中的那句话,就能够避免百度自动转码了。 举例:
<meta http-equiv="Cache-Control" content="no-siteapp" />
复制代码
说明:用于设定网页的到期时间,过时后网页必须到服务器上从新传输。 举例:
<meta http-equiv="expires" content="Sunday 26 October 2016 01:00 GMT" />
复制代码
说明:网页将在设定的时间内,自动刷新并调向设定的网址。 举例:
<meta http-equiv="refresh" content="2;URL=http://www.lxxyx.win/"> //意思是2秒后跳转向个人博客
复制代码
说明:若是网页过时。那么这个网页存在本地的 cookies 也会被自动删除。
<meta http-equiv="Set-Cookie" content="name, date"> //格式
<meta http-equiv="Set-Cookie" content="User=Lxxyx; path=/; expires=Sunday, 10-Jan-16 10:00:00 GMT"> //具体范例
复制代码