Vue.js能做PC端单页式网站开发吗

JavaScript011

Vue.js能做PC端单页式网站开发吗,第1张

完全可以。

1、另一方面,Vue 完全有能力驱动采用单文件组件和 Vue 生态系统支持的库开发的复杂单页应用,实现PC端单页式的前端开发。

2、PC端网站在不需要优先考虑SEO和首屏渲染时间时,单页式在用户体验和开发体验(开发效率)上是完胜多页式的。

3、vue.js作为主流框架之一,同样支持SSR,vue.js的PC端网站开发时服务端渲染编译比较慢,使用用单页式效率更高。

扩展资料:

主流框架Vue.js与angularjs的开发区别:

一、相同点:

都支持指令:内置指令和自定义指令。

都支持过滤器:内置过滤器和自定义过滤器。

都支持双向数据绑定。

都不支持低端浏览器。

二、不同点:

1、AngularJS的学习成本高,比如增加了Dependency Injection特性,而Vue.js本身提供的API都比较简单、直观。

2、在性能上,AngularJS依赖对数据做脏检查,所以Watcher越多越慢。

3、Vue.js使用基于依赖追踪的观察并且使用异步队列更新。所有的数据都是独立触发的。对于庞大的应用来说,这个优化差异还是比较明显的。

参考资料:vue.js官网-介绍-Vue.js

按照上面我们列出来的功能模块,我们在 Vuex/ 下面建立一个 store.js 文件

import Vue from 'vue'

import Vuex from 'vuex'

Vue.use(Vuex)

// 需要维护的状态

const state = {

notes: [],

activeNote: {},

show: ''

}

const mutations = {

// 初始化 state

INIT_STORE(state, data) {

state.notes = data.notes,

state.show = data.show

state.activeNote = data.activeNote

},

// 新增笔记

NEW_NOTE(state) {

var newNote = {

id: +new Date(),

title: '',

content: '',

favorite: false

}

state.notes.push(newNote)

state.activeNote = newNote

},

// 修改笔记

EDIT_NOTE(state, note) {

state.activeNote = note

// 修改原始数据

for (var i = 0i <state.notes.lengthi++) {

if(state.notes[i].id === note.id){

state.notes[i] = note

break

}

}

},

// 删除笔记

DELETE_NOTE(state) {

state.notes.$remove(state.activeNote)

state.activeNote = state.notes[0] || {}

},

// 切换笔记的收藏与取消收藏

TOGGLE_FAVORITE(state) {

state.activeNote.favorite = !state.activeNote.favorite

},

// 切换显示数据列表类型:全部 or 收藏

SET_SHOW_ALL(state, show){

state.show = show

// 切换数据展示,需要同步更新 activeNote

if(show === 'favorite'){

state.activeNote = state.notes.filter(note =>note.favorite)[0] || {}

}else{

state.activeNote = state.notes[0] || {}

}

},

// 设置当前激活的笔记

SET_ACTIVE_NOTE(state, note) {

state.activeNote = note

}

}

export default new Vuex.Store({

state,

mutations

})

创建 Vuex Actions

在 Vuex/ 下面建立一个 action.js,用来给组件使用的函数

function makeAction(type) {

return ({ dispatch }, ...args) =>dispatch(type, ...args)

}

const initNote = {

id: +new Date(),

title: '我的笔记',

content: '第一篇笔记内容',

favorite: false

}

// 模拟初始化数据

const initData = {

show: 'all',

notes: [initNote],

activeNote: initNote

}

export const initStore = ({ dispatch }) =>{

dispatch('INIT_STORE', initData)

}

// 更新当前activeNote对象

export const updateActiveNote = makeAction('SET_ACTIVE_NOTE')

// 添加一个note对象

export const newNote = makeAction('NEW_NOTE')

// 删除一个note对象

export const deleteNote = makeAction('DELETE_NOTE')

export const toggleFavorite = makeAction('TOGGLE_FAVORITE')

export const editNote = makeAction('EDIT_NOTE')

// 更新列表展示

export const updateShow = makeAction('SET_SHOW_ALL')

创建 Vuex Getters

在 vuex/ 下面建立一个 getter.js 文件,用来从 store 获取数据

// 获取 noteList,这里将会根据 state.show 的状态做数据过滤

export const filteredNotes = (state) =>{

if(state.show === 'all'){

return state.notes || {}

}else if(state.show === 'favorite'){

return state.notes.filter(note =>note.favorite) || {}

}

}

// 获取列表展示状态 : all or favorite

export const show = (state) =>{

return state.show

}

// 获取当前激活 note

export const activeNote = (state) =>{

return state.activeNote

}

以上就是我们 Vuex 的所有逻辑了,在定下了我们需要完成的功能之后,接下来就是只需要在组件中去调用 action 来实现对应的功能了。

路由配置

在这里我们将使用 vue-router 来做路由,引用 bootstrap 样式。

index.html

<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8">

<title>vuex-notes-app</title>

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">

</head>

<body>

<div id="app"></div>

<!-- built files will be auto injected -->

</body>

</html>

所有的入口逻辑我们都将在 main.js 中编写

main.js

import Vue from 'vue'

import App from './App'

import VueRouter from 'vue-router'

import VueResource from 'vue-resource'

// 路由模块和HTTP模块

Vue.use(VueResource)

Vue.use(VueRouter)

const router = new VueRouter()

router.map({

'/index': {

component: App

}

})

router.redirect({

'*': '/index'

})

router.start(App, '#app')

根组件 App.vue

<template>

<div id="app" class="app">

<toolbar></toolbar>

<notes-list></notes-list>

<editor></editor>

</div>

</template>

<style>

html, #app {

height: 100%

}

body {

margin: 0

padding: 0

border: 0

height: 100%

max-height: 100%

position: relative

}

</style>

<script>

import Toolbar from './components/Toolbar'

import NotesList from './components/NotesList'

import Editor from './components/Editor'

import store from './vuex/store'

import { initStore } from './vuex/actions'

export default {

components: {

Toolbar,

NotesList,

Editor

},

store,

vuex: {

actions: {

initStore

}

},

ready() {

this.initStore()

}

}

</script>

在根组件中引用了三个子组件:Toolbar.vue, NotesList.vue, Editor.vue。

注意:我们在配置里面加入了 vuex 这么一个选项,这里用来将我们 action 里面定义的方法给暴露出来,我们在根组件中只做了一件事情,那就是初始化模拟数据,因此我们在组件生命周期的 ready 阶段调用了 actions 里面的 initStore 来初始化我们的 store 里面的 state

Toolbar.vue

<template>

<div id="toolbar">

<i class="glyphicon logo"><img src="../assets/logo.png" width="30" height="30"></i>

<i @click="newNote" class="glyphicon glyphicon-plus"></i>

<i @click="toggleFavorite" class="glyphicon glyphicon-star" :class="{starred: activeNote.favorite}"></i>

<i @click="deleteNote" class="glyphicon glyphicon-remove"></i>

</div>

</template>

<script>

import { newNote, deleteNote, toggleFavorite } from '../vuex/actions'

import { activeNote } from '../vuex/getters'

export default {

vuex: {

getters: {

activeNote

},

actions: {

newNote,

deleteNote,

toggleFavorite

}

}

}

</script>

<style lang="scss" scoped>

#toolbar{

float: left

width: 80px

height: 100%

background-color: #30414D

color: #767676

padding: 35px 25px 25px 25px

.starred {

color: #F7AE4F

}

i{

font-size: 30px

margin-bottom: 35px

cursor: pointer

opacity: 0.8

transition: opacity 0.5s ease

&:hover{

opacity: 1

}

}

}

</style>

在这里,我们用到了 Vuex 的一个案例就是我们需要知道当前的激活的笔记是否是收藏类别的,如果是,我们需要高亮收藏按钮,那么如何知道呢?那就是通过 vuex 里面的 getters 获取当前激活的笔记对象,判断它的 favorite 是否为 true。

始终牢记一个概念,vuex 中数据是单向的,只能从 store 获取,而我们这个例子中的 activeNote 也是始终都在 store.js 中维护的,这样子就可以给其他组件公用了

// 需要维护的状态

const state = {

notes: [],

activeNote: {},

show: ''

}

NotesList.vue

<template>

<div id="notes-list">

<div id="list-header">

<h2>Notes | heavenru.com</h2>

<div class="btn-group btn-group-justified" role="group">

<!-- all -->

<div class="btn-group" role="group">

<button type="button" class="btn btn-default"

@click="toggleShow('all')"

:class="{active: show === 'all'}">All Notes</button>

</div>

<!-- favorites -->

<div class="btn-group" role="group">

<button type="button" class="btn btn-default"

@click="toggleShow('favorite')"

:class="{active: show === 'favorite'}">Favorites</button>

</div>

</div>

</div>

<!-- 渲染笔记列表 -->

<div class="container">

<div class="list-group">

<a v-for="note in filteredNotes"

class="list-group-item" href="#"

:class="{active: activeNote === note}"

@click="updateActiveNote(note)">

<h4 class="list-group-item-heading">

{{note.title.trim().substring(0,30)}}

</h4>

</a>

</div>

</div>

</div>

</template>

<script>

import { updateActiveNote, updateShow } from '../vuex/actions'

import { show, filteredNotes, activeNote } from '../vuex/getters'

export default {

vuex: {

getters: {

show,

filteredNotes,

activeNote

},

actions: {

updateActiveNote,

updateShow

}

},

methods: {

toggleShow(show) {

this.updateShow(show)

}

}

}

</script>

笔记列表组件,主要有三个操作

渲染笔记

切换渲染笔记

点击列表 title,切换 activeNote

我们通过 getters 中的 filteredNotes 方法获取笔记列表

// 获取 noteList,这里将会根据 state.show 的状态做数据过滤

export const filteredNotes = (state) =>{

if(state.show === 'all'){

return state.notes || {}

}else if(state.show === 'favorite'){

return state.notes.filter(note =>note.favorite) || {}

}

}

可以看到,我们获取的列表是依赖于 state.show 这个状态的。而我们的切换列表操作恰好就是调用 actions 里面的方法来更新 state.show ,这样一来,实现了数据列表的动态刷新,而且我们对树的操作都是通过调用 actions 的方法来实现的。

我们再看,在切换列表的时候,我们还需要动态的更新 activeNote 。 看看我们在 store.js 中是如何做的:

// 切换显示数据列表类型:全部 or 收藏

SET_SHOW_ALL(state, show){

state.show = show

// 切换数据展示,需要同步更新 activeNote

if(show === 'favorite'){

state.activeNote = state.notes.filter(note =>note.favorite)[0] || {}

}else{

state.activeNote = state.notes[0] || {}

}

}

触发这些操作的是我们给两个按钮分别绑定了我们自定义的函数,通过给函数传入不同的参数,然后调用 actions 里面的方法,来实现对数据的过滤,更新。

Editor.vue

<template>

<div id="note-editor">

<div class="form-group">

<input type="text" name="title"

class="title form-control"

placeholder="请输入标题"

@input="updateNote"

v-model="currentNote.title">

<textarea

v-model="currentNote.content" name="content"

class="form-control" row="3" placeholder="请输入正文"

@input="updateNote"></textarea>

</div>

</div>

</template>

<script>

import { editNote } from '../vuex/actions'

import { activeNote } from '../vuex/getters'

export default {

vuex: {

getters: {

activeNote

},

actions: {

editNote

}

},

computed: {

// 通过计算属性得到的一个对象,这样子我们就能愉快的使用 v-model 了

currentNote: activeNote

},

methods: {

// 为什么这么做? 因为在严格模式中不允许直接在模板层面去修改 state 中的值

updateNote() {

this.editNote(this.currentNote)

}

}

}

</script>

在 Editor.vue 组件中,我们需要能够实时的更新当前的 activeNote 组件和列表中对应的我们正在修改的笔记对象的内容。

由于我们前面提到过,在组件中是不允许直接修改 store.js在里面的状态值的,所以在这里的时候,我们通过一个计算属性,将 store 里面的状态值赋值给一个对象,然后在自定义的 updateNotes() 方法中,去调用 action,同时传入 currentNote 对象。

在 store.js 中,我们是这么做的,找到对应的 id 的对象,重新赋值,因为前面提到过,我们的数据是响应式的,在这里进行了改变,对应的视图也将刷新改变,这样一来就实现了实时编辑,实时渲染的功能了。

// 修改笔记

EDIT_NOTE(state, note) {

state.activeNote = note

// 修改原始数据

for (var i = 0i <state.notes.lengthi++) {

if(state.notes[i].id === note.id){

state.notes[i] = note

break

}

}

},