如何制作卡片链接

550 阅读2分钟

卡片链接

  1. 卡片链接

卡片链接往往比单纯的放一个链接,视觉效果更加的友好。更能够吸引读者去点击阅读,增加点击量和阅读量。

  1. 简单实现一个卡片链接

  1. 使用nodejs作为后台解析。
  2. 使用模块: cheerio,爬取网页链接基本信息。
  3. 爬虫函数的实现

3.1 爬虫函数

const request = async url => {

  const request = axios.create();

  request.interceptors.request.use(config => {

    config.headers['User-Agent'] = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36'

    // config.headers['Referer'] = url

    // config.headers['Origin'] = rootUrl(url)

    return config

  })

  return request.get(url).then(result => {

    let body = result.data;

    // 加载数据

    const $ = cheerio.load(body);

    const title = findTitle($);  // 获取链接标题

    const description = findDescription($); // 获取链接简要描述内容

    const icon = findLinkIcon($, url); // 获取链接icon

    const image = findImage($) // 获取图片

    return {

      title,

      url,

      description,

      icon,

      image

    };

  })

};

3.2 获取链接标题

const findTitle = $ => {

  const title = $('title').text().trim();

  const metaList = $('meta[property]');

  if (title === '') {

    for (const meta of metaList) {

      if (get(meta, 'attribs.property', '').indexOf('title') !== -1) {

        return get(meta, 'attribs.content', '');

      }

    }

  }

  return title;

};

3.3获取链接描述内容

const findDescription = $ => {

  const match_description = $('meta[name=description]')['0'];

  if (match_description) {

    return get(match_description, 'attribs.content', '');

  }

  const metaList = $('meta');

  for (const meta of metaList) {

    if (get(meta, 'attribs.name', '').indexOf('description') !== -1) {

      return get(meta, 'attribs.content', '');

    }

  }

  return '';

};

3.4 获取链接描述内容

const findLinkIcon = ( $ , url) => {

  const handle_link = link => {

    if (link.startsWith('//')) {

      return 'http://' + link.slice(2);

    }

    if (link.startsWith('/')) {

      return rootUrl(url) + link;

    }

    return link;

  };



  const icon = $('link[rel=icon]')['0'];

  if (icon) {

    return handle_link(get(icon, 'attribs.href', ''));

  }

  const linkList = $('link[rel]');

  for (const link of linkList) {

    if (get(link, 'attribs.rel', '').indexOf('icon') !== -1) {

      return handle_link(get(link, 'attribs.href', ''));

    }

  }

  return '';

};

3.5 获取链接描述内容

const findImage = $ => {

  const metaList = $('meta[property]');

  for (const meta of metaList) {

    if (get(meta, 'attribs.property', '').indexOf('og:image') !== -1) {

      return get(meta, 'attribs.content', '');

    }

  }

  return ''

}
  1. 前端实现

前端就比较好实现了,根据服务器返回来的title,icon,description,image,进行布局就好。

4.1 LinkCard.tsx

export default function LinkCard(props: any): React.ReactElement {



  let {

    link

  } = props



  // let link = {

  //   title: 'lodash的get方法 - SegmentFault 思否',

  //   url: 'https://segmentfault.com/a/1190000015605531',

  //   description:

  //     'get这个方法,在lodash中是出场率很高的方法,初识起来有些疑惑,看了demo,又很直观。 get方法源码链接 下边是它的使用说明 {代码...} 根据object对象的path路径获取值。如果解析值是undefined,就返回一个默认的值(defaultValue) {代码...} 暂时不考虑第第三个参数,只考虑第二个参数,该参数的含义就是路径。 指向obj...',

  //   icon: 'https://cdn.segmentfault.com/r-fd1f02aa/favicon.ico',

  // };



  const [innerLink,setInnerLink] = useState(link);



  useEffect(() => {

    // console.log(innerLink)

    if (!innerLink.isSpider) {

      updateLinkInfo({

        link_id: innerLink.id,

        url: innerLink.url

      }).then(res => {

        // console.log(res.data.data)

        setInnerLink(res.data.data)

      })

    }

  }, [])





  return (

    <Link href={link.url} target="_blank" >

      <div className={styles.container}>

        <div className={cls(styles.left,{

          [styles.hideLeft]: innerLink.image

        })}>

          <div>

          {innerLink.title && (

            <div className={styles.title}>

              <span>{innerLink.title}</span>

            </div>

          )}

          {innerLink.description && (

              <div className={styles.content}>

                <span> {innerLink.description}</span>

              </div>

          )}

          </div>

          <div className={styles.link}>

            {innerLink.icon && <img src={innerLink.icon} alt="" />}

            <span>{innerLink.url}</span>

          </div>

        </div>

        {

          innerLink.image && <div className={styles.right}>

            <img className={styles.coverimage} src={innerLink.image} alt="" />

        </div>

        }

      </div>

    </Link>

  );

}

4.2 index.less

css这里就添一个比较重要的内容。卡片需要显示几行描述文字。

 .content {

  font-size: 12px;

  font-family: 'mono';

  color: #333;

  margin-bottom: 5px;

  max-height: 120px;

  width: 100%;

  display: -webkit-box;/** 对象作为伸缩盒子模型显示 **/

  word-break: break-all;

  text-overflow: ellipsis;

  -webkit-box-orient: vertical;/** 设置或检索伸缩盒对象的子元素的排列方式 **/

  -webkit-line-clamp: 2;/** 显示的行数 **/

  overflow: hidden;

}