vue-cli2.x简易版博客系统

282 阅读1分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

一、步骤

项目展示

4.gif

1、脚手架VueCli2

vue-cli脚手架配置项目

image-20220519082756783.png

首先 vue init webpack note-blog

然后 cd note-blog

最后 npm run dev,启动项目。目录结构在下面

image-20220519083227808.png

2、测试组件

2.1

在note-blog\src\components下面创建新组件,注意组件名怎么命名的。

2.2

填写代码。更改template里面div的class名,和组件名相辅相成;script里面name也是一样

<template>
  <div class="add-blog">
    <h1>add-blog</h1>
  </div>
</template>
​
<script>
export default {
  name: "add-blog",
  data() {
    return {};
  },
};
</script>
​
<style scoped>
</style>

2.3

在父组件App.vue里面引入若干子组件

添加下面代码。template里面div的id名,和组件名相辅相成,添加路由组件;script里面name也是一样,另外引入需要的子组件

<template>
  <div id="app">
    <add-blog-vue></add-blog-vue>
  </div>
</template>
​
<script>
import AddBlogVue from "./components/AddBlog.vue";
​
export default {
  name: "App",
  components: {
    AddBlogVue,
  },
};
</script>

运行命令 npm run dev,得到下面的图

image-20220519084651092.png

3、添加博客,post数据

3.1页面

第一个组件

创建组件,美化组件页面内容

3.1.1

先简单实现页面主要组成

1.gif

<template>
  <div class="add-blog">
    <h1>添加博客</h1>
    <form>
      <label for="title">博客标题</label>
      <input type="text" v-model="blog.title" required />
      <label for="content">博客内容</label>
      <textarea v-model="blog.content" cols="30" rows="10"></textarea>
    </form>
      
![1.gif](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c9eae8f9c2f447c58119fc318de6ea54~tplv-k3u1fbpfcp-watermark.image?)
    <hr />
    <div id="preview">
      <h3>博客总览</h3>
      <p>博客标题:{{ blog.title }}</p>
      <p>博客内容:</p>
      <p>{{ blog.content }}</p>
    </div>
  </div>
</template>
​
<script>
export default {
  name: "add-blog",
  data() {
    return {
      blog: {
        title: "",
        content: "",
      },
    };
  },
};
</script>

tips:input标签总和v-model搭配,双向数据绑定

3.1.2

完善。

1、ul>li,select>option标签总和v-for搭配,循环

2、button标签总和v-on:click.prevent="post"事件搭配。prevent防止刷新

3、post请求,需要模块下载 npm install vue-resource --save ,在index.js里面模块,像引入App.vue模块一样

<template>
    <div id="checkboxes">
        <label>Vue.js</label>
        <input type="checkbox" value="Vue.js" v-model="blog.categories" />
        <label>Node.js</label>
        <input type="checkbox" value="Node.js" v-model="blog.categories" />
        <label>React.js</label>
        <input type="checkbox" value="React.js" v-model="blog.categories" />
        <label>Angular.js</label>
        <input type="checkbox" value="Angular.js" v-model="blog.categories" />
        <label for="author">作者:</label>
        <select v-model="blog.author">
          <option v-for="(author, index) in authors" :key="index">
            {{ author }}
          </option>
        </select>
    </div>
    <button v-on:click.prevent="post">添加博客</button>
​
    <hr />
    <div id="preview">
      <h3>博客总览</h3>
      <p>博客标题:{{ blog.title }}</p>
      <p>博客内容:</p>
      <p>{{ blog.content }}</p>
      <p>博客分类:</p>
      <ul>
        <li v-for="(category, index) in blog.categories" :key="index">
          {{ category }}
        </li>
      </ul>
      <p>作者:{{ blog.author }}</p>
    </div>
 </template>
​
    <script>
    methods:{
      post:function(){
        this.$http
        .post("http://jsonplaceholder.typicode.com/posts", {
          title: this.blog.title,
          body: this.blog.content,
          userId: 1,
        })
        .then(function (data) {
          console.log(data);
        });
        }
      }
    </script>

4、最后v-if设置什么情况下显示,什么情况下不显示

image-20220519145644483.png

3.1.3

正式美化

image-20220519151033857.png

4、展示博客组件

4.1

第二个组件

image-20220519145644483.png 步骤和添加博客组件一致

4.2

实现请求 this.$http.get("网址",{}).then((data)=>{console.log(data)})

<template>
  <div id="show-blogs">
    <h1>show-blogs</h1>
    <!-- v-for="(blog, index) in blogs"遍历请求得到的数据 -->
    <div class="single-blog" v-for="(blog, index) in blogs" :key="index">
      <h2>{{ blog.title }}</h2>
      <article>
        {{ blog.body }}
      </article>
    </div>
  </div>
</template>
​
<script>
export default {
  name: "show-blogs",
  data() {
    return {
      blogs: [],
    };
  },
  created() {
    this.$http.get("http://jsonplaceholder.typicode.com/posts").then((data) => {
      console.log(data);
      this.blogs = data.body.slice(0, 20);
      console.log(this.blogs);
    });
  },
};
</script>
​
<style scoped>
#show-blogs {
  max-width: 800px;
  margin: 0 auto;
}
.single-blog {
  padding: 20px;
  margin: 20px 0;
  box-sizing: border-box;
  background: #eee;
}
</style>

4.3

【tip】请求的本地数据文件,只能放在static文件夹底下

image-20220519160048813.png

5、钩子函数

5.1

自定义指令

5.2

5.2.1属性

Vue.directive('rainbow', {
  bind(el, binding, vnode) {
    el.style.color = "#" + Math.random().toString(16).slice(2, 8)
  }
})

5.2.2方法

Vue.directive('theme', {
  bind(el, binding, vnode) {
    if (binding.value == 'wide') {
      el.style.maxWidth = "1260px"
    } else if (binding.value == 'narrow') {
      el.style.maxWidth = "560px"
    } else if (binding.value == 'middle') {
      el.style.maxWidth = "800px"
    }
  }
})

5.2.3方法的属性

Vue.directive('theme', {
  bind(el, binding, vnode) {
    if (binding.value == 'wide') {
      el.style.maxWidth = "1260px"
    } else if (binding.value == 'narrow') {
      el.style.maxWidth = "560px"
    }
    // ShowBlogs的自定义属性v-theme 的参数column
    if (binding.arg == 'column') {
      el.style.background = "#667cc"
      el.style.padding = '20px'
    }
  }
})

image-20220519155926225.png

6、过滤器方法

6.1

自定义过滤器

<h2 v-rainbow>{{ blog.title | to-uppercase}}</h2>
<article v-rainbow>
    {{ blog.body | snippet }}
</article>

6.2

实现过滤器

// value接收"to-uppercase"的值,并返回toUpperCase()
Vue.filter("to-uppercase", function (value) {
  return value.toUpperCase();
})
Vue.filter("snippet", function (value) {
  return value.slice(0, 100) + "...";
})

6.3

什么时候需要使用过滤器方法?

6.4

实现搜索方法

computed: {
    filteredBlogs: function () {
        return this.blogs.filter((blog) => {
            //   this.blogs.filter过滤的方法返回布尔值,ES6函数match(this.search)
            return blog.title.match(this.search);
        });
    },
},

image-20220519162137674.png

2.gif

7、路由

7.1

2022年2月7日以后,vue-router的默认安装版本为版本4,即vue-router4只能用在vue3中,vue-router3才能用在vue2中

1、下载路由模块 npm i vue-router@3.2.0

2、引入路由模块

image-20220519164913841.png

3、创建路由 router.js

import ShowBlogs from './components/ShowBlogs'
import AddBlog from './components/AddBlog'

export default [
    { path: "/", component: ShowBlogs },
    { path: "/add", component: AddBlog }
]

4、修改路由view

image-20220519165050210.png

8、头部组件

8.1 制作头部

第三个组件

步骤和添加博客组件一致

创建头部组件,App.vue引入头部组件,美化样式

image-20220519171530591.png

<template>
  <nav>
    <ul>
      <li>
        <router-link to="/" exact>博客</router-link>
        <router-link to="/add" exact>写博客</router-link>
      </li>
    </ul>
  </nav>
</template>

<script>
export default {
  name: "blog-header",
};
</script>

<style scoped>
ul {
  list-style-type: none;
  margin: 0;
  text-align: center;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  text-decoration: none;
  color: #fff;
  padding: 12px;
  border-radius: 5px;
}
nav {
  background: crimson;
  padding: 30px 0;
  margin-bottom: 40px;
}
.router-link-active {
  background: rgba(255, 255, 255, 0.8);
  color: #444;
}
</style>

8.2 路由参数

8.2.1 单条博客组件

第四个组件

sp20220519_175727_262.png

<template>
  <div id="single-blog">
    <h1 v-rainbow>{{ blog.title }}</h1>
    <article v-rainbow>{{ blog.body }}</article>
  </div>
</template>

<script>
export default {
  name: "single-blog",
  data() {
    return {
      id: this.$route.params.id,
      // 点击进入成为单条博客
      blog: {},
    };
  },
  created() {
    this.$http
      .get("http://jsonplaceholder.typicode.com/posts/" + this.id)
      .then((data) => {
        // console.log(data);
        this.blog = data.body;
      });
  },
  directives: {
    rainbow: {
      bind(el, binding, vnode) {
        el.style.color = "#" + Math.random().toString(16).slice(2, 8);
      },
    },
  },
};
</script>

<style scoped>
#single-blog {
  max-width: 800px;
  margin: 0 auto;
  padding: 20px;
  background: #eee;
  border: 1px dotted #aaa;
}
</style>